@defra/forms-engine-plugin 4.0.33 → 4.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.server/server/constants.d.ts +1 -0
- package/.server/server/constants.js +1 -0
- package/.server/server/constants.js.map +1 -1
- package/.server/server/forms/register-as-a-unicorn-breeder.yaml +0 -1
- package/.server/server/forms/simple-form.yaml +64 -0
- package/.server/server/plugins/engine/beta/form-context.js +1 -2
- package/.server/server/plugins/engine/beta/form-context.js.map +1 -1
- package/.server/server/plugins/engine/components/FileUploadField.d.ts +4 -3
- package/.server/server/plugins/engine/components/FileUploadField.js +38 -0
- package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
- package/.server/server/plugins/engine/components/FormComponent.d.ts +9 -7
- package/.server/server/plugins/engine/components/FormComponent.js +3 -0
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
- package/.server/server/plugins/engine/helpers.d.ts +5 -0
- package/.server/server/plugins/engine/helpers.js +7 -0
- package/.server/server/plugins/engine/helpers.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +6 -2
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +4 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +4 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +33 -35
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/__stubs__/request.d.ts +2 -2
- package/.server/server/plugins/engine/pageControllers/__stubs__/request.js +9 -0
- package/.server/server/plugins/engine/pageControllers/__stubs__/request.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/errors.d.ts +15 -0
- package/.server/server/plugins/engine/pageControllers/errors.js +25 -0
- package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -0
- package/.server/server/plugins/engine/services/localFormsService.js +6 -0
- package/.server/server/plugins/engine/services/localFormsService.js.map +1 -1
- package/.server/server/plugins/engine/views/index.html +1 -1
- package/.server/server/plugins/nunjucks/context.test.js +9 -1
- package/.server/server/plugins/nunjucks/context.test.js.map +1 -1
- package/.server/server/plugins/nunjucks/types.d.ts +4 -0
- package/.server/server/plugins/nunjucks/types.js +1 -0
- package/.server/server/plugins/nunjucks/types.js.map +1 -1
- package/.server/server/services/cacheService.d.ts +1 -0
- package/.server/server/services/cacheService.js +10 -0
- package/.server/server/services/cacheService.js.map +1 -1
- package/.server/typings/hapi/index.d.js.map +1 -1
- package/package.json +1 -1
- package/src/server/constants.js +1 -0
- package/src/server/forms/register-as-a-unicorn-breeder.yaml +0 -1
- package/src/server/forms/simple-form.yaml +64 -0
- package/src/server/plugins/engine/beta/form-context.test.ts +4 -3
- package/src/server/plugins/engine/beta/form-context.ts +4 -3
- package/src/server/plugins/engine/components/FileUploadField.test.ts +203 -2
- package/src/server/plugins/engine/components/FileUploadField.ts +61 -2
- package/src/server/plugins/engine/components/FormComponent.ts +17 -1
- package/src/server/plugins/engine/helpers.ts +8 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +9 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +11 -4
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +6 -0
- package/src/server/plugins/engine/pageControllers/SummaryPageController.test.ts +3 -0
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +55 -46
- package/src/server/plugins/engine/pageControllers/__stubs__/request.ts +14 -4
- package/src/server/plugins/engine/pageControllers/errors.test.ts +63 -0
- package/src/server/plugins/engine/pageControllers/errors.ts +30 -0
- package/src/server/plugins/engine/services/localFormsService.js +7 -0
- package/src/server/plugins/engine/views/index.html +1 -1
- package/src/server/plugins/nunjucks/context.test.js +10 -2
- package/src/server/plugins/nunjucks/types.js +1 -0
- package/src/server/services/cacheService.ts +16 -0
- package/src/typings/hapi/index.d.ts +2 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ComponentType } from '@defra/forms-model'
|
|
2
|
+
|
|
3
|
+
import { FileUploadField } from '~/src/server/plugins/engine/components/FileUploadField.js'
|
|
4
|
+
import { TextField } from '~/src/server/plugins/engine/components/TextField.js'
|
|
5
|
+
import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
|
|
6
|
+
import { InvalidComponentStateError } from '~/src/server/plugins/engine/pageControllers/errors.js'
|
|
7
|
+
import definition from '~/test/form/definitions/file-upload-basic.js'
|
|
8
|
+
|
|
9
|
+
describe('InvalidComponentStateError', () => {
|
|
10
|
+
let model: FormModel
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
model = new FormModel(definition, {
|
|
14
|
+
basePath: 'test'
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
describe('getStateKeys', () => {
|
|
19
|
+
it('should return component name and upload for FileUploadField', () => {
|
|
20
|
+
const page = model.pages.find((p) => p.path === '/file-upload-component')
|
|
21
|
+
const component = new FileUploadField(
|
|
22
|
+
{
|
|
23
|
+
name: 'fileUpload',
|
|
24
|
+
title: 'Upload something',
|
|
25
|
+
type: ComponentType.FileUploadField,
|
|
26
|
+
options: {},
|
|
27
|
+
schema: {}
|
|
28
|
+
},
|
|
29
|
+
{ model, page }
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const error = new InvalidComponentStateError(
|
|
33
|
+
component,
|
|
34
|
+
'Test error message'
|
|
35
|
+
)
|
|
36
|
+
const stateKeys = error.getStateKeys()
|
|
37
|
+
|
|
38
|
+
expect(stateKeys).toEqual(['fileUpload', 'upload'])
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should return only component name for non-FileUploadField components', () => {
|
|
42
|
+
const page = model.pages.find((p) => p.path === '/file-upload-component')
|
|
43
|
+
const component = new TextField(
|
|
44
|
+
{
|
|
45
|
+
name: 'textField',
|
|
46
|
+
title: 'Text field',
|
|
47
|
+
type: ComponentType.TextField,
|
|
48
|
+
options: {},
|
|
49
|
+
schema: {}
|
|
50
|
+
},
|
|
51
|
+
{ model, page }
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
const error = new InvalidComponentStateError(
|
|
55
|
+
component,
|
|
56
|
+
'Test error message'
|
|
57
|
+
)
|
|
58
|
+
const stateKeys = error.getStateKeys()
|
|
59
|
+
|
|
60
|
+
expect(stateKeys).toEqual(['textField'])
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { FileUploadField } from '~/src/server/plugins/engine/components/FileUploadField.js'
|
|
2
|
+
import { type FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Thrown when a component has an invalid state. This is typically only required where state needs
|
|
6
|
+
* to be checked against an external source upon submission of a form. For example: file upload
|
|
7
|
+
* has internal state (file upload IDs) but also external state (files in S3). The internal state
|
|
8
|
+
* is always validated by the engine, but the external state needs validating too.
|
|
9
|
+
*
|
|
10
|
+
* This should be used within a formComponent.onSubmit(...).
|
|
11
|
+
*/
|
|
12
|
+
export class InvalidComponentStateError extends Error {
|
|
13
|
+
public readonly component: FormComponent
|
|
14
|
+
public readonly userMessage: string
|
|
15
|
+
|
|
16
|
+
constructor(component: FormComponent, userMessage: string) {
|
|
17
|
+
const message = `Invalid component state for: ${component.name}`
|
|
18
|
+
super(message)
|
|
19
|
+
this.name = 'InvalidComponentStateError'
|
|
20
|
+
this.component = component
|
|
21
|
+
this.userMessage = userMessage
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getStateKeys() {
|
|
25
|
+
const extraStateKeys =
|
|
26
|
+
this.component instanceof FileUploadField ? ['upload'] : []
|
|
27
|
+
|
|
28
|
+
return [this.component.name].concat(extraStateKeys)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -51,5 +51,12 @@ export const formsService = async () => {
|
|
|
51
51
|
slug: 'components'
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
+
await loader.addForm('src/server/forms/simple-form.yaml', {
|
|
55
|
+
...metadata,
|
|
56
|
+
id: 'a1b2c3d4-e5f6-7890-abcd-ef0123456789',
|
|
57
|
+
title: 'Simple Form',
|
|
58
|
+
slug: 'simple-form'
|
|
59
|
+
})
|
|
60
|
+
|
|
54
61
|
return loader.toFormsService()
|
|
55
62
|
}
|
|
@@ -87,7 +87,11 @@ describe('Nunjucks context', () => {
|
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
89
|
path: '/test',
|
|
90
|
-
url: { search: '' }
|
|
90
|
+
url: { search: '' },
|
|
91
|
+
yar: {
|
|
92
|
+
flash: jest.fn().mockReturnValue([]),
|
|
93
|
+
commit: jest.fn()
|
|
94
|
+
}
|
|
91
95
|
// state intentionally omitted to test real malformed requests
|
|
92
96
|
})
|
|
93
97
|
)
|
|
@@ -121,7 +125,11 @@ describe('Nunjucks context', () => {
|
|
|
121
125
|
},
|
|
122
126
|
path: '/test',
|
|
123
127
|
url: { search: '' },
|
|
124
|
-
state: {}
|
|
128
|
+
state: {},
|
|
129
|
+
yar: {
|
|
130
|
+
flash: jest.fn().mockReturnValue([]),
|
|
131
|
+
commit: jest.fn()
|
|
132
|
+
}
|
|
125
133
|
})
|
|
126
134
|
)
|
|
127
135
|
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* @property {string} [currentPath] - Current path
|
|
18
18
|
* @property {string} [previewMode] - Preview mode
|
|
19
19
|
* @property {string} [slug] - Form slug
|
|
20
|
+
* @property {string} [error] - Error message for temporary error messages (not related to form state)
|
|
20
21
|
* @property {FormContext} [context] - the current form context
|
|
21
22
|
*/
|
|
22
23
|
|
|
@@ -99,6 +99,22 @@ export class CacheService {
|
|
|
99
99
|
request.yar.flash(key.id, message)
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
async resetComponentStates(
|
|
103
|
+
request: AnyFormRequest,
|
|
104
|
+
componentNames: string[]
|
|
105
|
+
) {
|
|
106
|
+
const state = await this.getState(request)
|
|
107
|
+
|
|
108
|
+
for (const componentName of componentNames) {
|
|
109
|
+
if (componentName in state) {
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
111
|
+
delete state[componentName]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return this.setState(request, state)
|
|
116
|
+
}
|
|
117
|
+
|
|
102
118
|
/**
|
|
103
119
|
* The key used to store user session data against.
|
|
104
120
|
* If there are multiple forms on the same runner instance, for example `form-a` and `form-a-feedback` this will prevent CacheService from clearing data from `form-a` if a user gave feedback before they finished `form-a`
|
|
@@ -5,6 +5,7 @@ import { type ServerYar, type Yar } from '@hapi/yar'
|
|
|
5
5
|
import { type Logger } from 'pino'
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
type COMPONENT_STATE_ERROR,
|
|
8
9
|
type EXTERNAL_STATE_APPENDAGE,
|
|
9
10
|
type EXTERNAL_STATE_PAYLOAD
|
|
10
11
|
} from '~/src/server/constants.js'
|
|
@@ -20,6 +21,7 @@ declare module '@hapi/yar' {
|
|
|
20
21
|
interface YarFlashes {
|
|
21
22
|
[EXTERNAL_STATE_APPENDAGE]: object
|
|
22
23
|
[EXTERNAL_STATE_PAYLOAD]: object
|
|
24
|
+
[COMPONENT_STATE_ERROR]: string
|
|
23
25
|
[key: string]: { errors: FormSubmissionError[] }
|
|
24
26
|
}
|
|
25
27
|
}
|