@defra/forms-engine-plugin 3.0.0 → 3.0.2
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/plugins/engine/models/FormModel.d.ts +2 -0
- package/.server/server/plugins/engine/models/FormModel.js +4 -1
- package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/adapter/v1.d.ts +4 -0
- package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +25 -0
- package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js +7 -6
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/RepeatPageController.d.ts +1 -0
- package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +8 -1
- package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
- package/.server/server/plugins/engine/routes/index.js +3 -1
- package/.server/server/plugins/engine/routes/index.js.map +1 -1
- package/.server/server/plugins/engine/types/schema.js +3 -2
- package/.server/server/plugins/engine/types/schema.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +4 -1
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/plugins/engine/views/repeat-list-summary.html +15 -5
- package/package.json +2 -2
- package/src/server/plugins/engine/models/FormModel.test.ts +64 -0
- package/src/server/plugins/engine/models/FormModel.ts +5 -2
- package/src/server/plugins/engine/outputFormatters/adapter/v1.test.ts +446 -13
- package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +37 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.ts +8 -6
- package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +8 -1
- package/src/server/plugins/engine/routes/index.ts +3 -1
- package/src/server/plugins/engine/types/schema.test.ts +40 -0
- package/src/server/plugins/engine/types/schema.ts +3 -1
- package/src/server/plugins/engine/types.ts +4 -0
- package/src/server/plugins/engine/views/repeat-list-summary.html +15 -5
|
@@ -156,5 +156,45 @@ describe('Schema validation', () => {
|
|
|
156
156
|
formAdapterSubmissionMessagePayloadSchema.validate(payloadWithoutData)
|
|
157
157
|
expect(error).toBeDefined()
|
|
158
158
|
})
|
|
159
|
+
|
|
160
|
+
it('should validate payload with versionMetadata', () => {
|
|
161
|
+
const payloadWithVersion = {
|
|
162
|
+
...validPayload,
|
|
163
|
+
meta: {
|
|
164
|
+
...validPayload.meta,
|
|
165
|
+
versionMetadata: {
|
|
166
|
+
versionNumber: 19,
|
|
167
|
+
createdAt: new Date('2025-09-08T09:28:15.576Z')
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const { error } =
|
|
172
|
+
formAdapterSubmissionMessagePayloadSchema.validate(payloadWithVersion)
|
|
173
|
+
expect(error).toBeUndefined()
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('should validate payload without versionMetadata', () => {
|
|
177
|
+
const { error } =
|
|
178
|
+
formAdapterSubmissionMessagePayloadSchema.validate(validPayload)
|
|
179
|
+
expect(error).toBeUndefined()
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('should reject invalid versionMetadata', () => {
|
|
183
|
+
const payloadWithInvalidVersion = {
|
|
184
|
+
...validPayload,
|
|
185
|
+
meta: {
|
|
186
|
+
...validPayload.meta,
|
|
187
|
+
versionMetadata: {
|
|
188
|
+
versionNumber: 'not-a-number', // Invalid - should be number
|
|
189
|
+
createdAt: new Date('2025-09-08T09:28:15.576Z')
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const { error } = formAdapterSubmissionMessagePayloadSchema.validate(
|
|
194
|
+
payloadWithInvalidVersion
|
|
195
|
+
)
|
|
196
|
+
expect(error).toBeDefined()
|
|
197
|
+
expect(error?.message).toContain('must be a number')
|
|
198
|
+
})
|
|
159
199
|
})
|
|
160
200
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FormStatus,
|
|
3
|
+
formVersionMetadataSchema,
|
|
3
4
|
idSchema,
|
|
4
5
|
notificationEmailAddressSchema,
|
|
5
6
|
slugSchema,
|
|
@@ -29,7 +30,8 @@ export const formAdapterSubmissionMessageMetaSchema =
|
|
|
29
30
|
.valid(...Object.values(FormStatus))
|
|
30
31
|
.required(),
|
|
31
32
|
isPreview: Joi.boolean().required(),
|
|
32
|
-
notificationEmail: notificationEmailAddressSchema.required()
|
|
33
|
+
notificationEmail: notificationEmailAddressSchema.required(),
|
|
34
|
+
versionMetadata: formVersionMetadataSchema.optional()
|
|
33
35
|
})
|
|
34
36
|
|
|
35
37
|
export const formAdapterSubmissionMessageDataSchema =
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
type Event,
|
|
4
4
|
type FormDefinition,
|
|
5
5
|
type FormMetadata,
|
|
6
|
+
type FormVersionMetadata,
|
|
6
7
|
type Item,
|
|
7
8
|
type List,
|
|
8
9
|
type Page
|
|
@@ -179,6 +180,7 @@ export interface FormContext {
|
|
|
179
180
|
pageMap: Map<string, PageControllerClass>
|
|
180
181
|
componentMap: Map<string, Component>
|
|
181
182
|
referenceNumber: string
|
|
183
|
+
submittedVersionNumber?: number
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
export type FormContextRequest = (
|
|
@@ -327,6 +329,7 @@ export interface RepeaterSummaryPageViewModel extends PageViewModelBase {
|
|
|
327
329
|
errors?: FormSubmissionError[]
|
|
328
330
|
checkAnswers: CheckAnswers[]
|
|
329
331
|
repeatTitle: string
|
|
332
|
+
allowSaveAndExit: boolean
|
|
330
333
|
}
|
|
331
334
|
|
|
332
335
|
export interface FeaturedFormPageViewModel extends FormPageViewModel {
|
|
@@ -405,6 +408,7 @@ export interface FormAdapterSubmissionMessageMeta {
|
|
|
405
408
|
status: FormStatus
|
|
406
409
|
isPreview: boolean
|
|
407
410
|
notificationEmail: string
|
|
411
|
+
versionMetadata?: FormVersionMetadata
|
|
408
412
|
}
|
|
409
413
|
|
|
410
414
|
export type FormAdapterSubmissionMessageMetaSerialised = Omit<
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
{{ govukSummaryList(section.summaryList) }}
|
|
25
25
|
{% endfor %}
|
|
26
26
|
|
|
27
|
-
<
|
|
28
|
-
<
|
|
29
|
-
<input type="hidden" name="crumb" value="{{ crumb }}">
|
|
27
|
+
<form method="post" novalidate>
|
|
28
|
+
<input type="hidden" name="crumb" value="{{ crumb }}">
|
|
30
29
|
|
|
30
|
+
<div class="govuk-button-group">
|
|
31
31
|
{{ govukButton({
|
|
32
32
|
text: "Continue",
|
|
33
33
|
name: "action",
|
|
@@ -42,8 +42,18 @@
|
|
|
42
42
|
classes: "govuk-button--secondary",
|
|
43
43
|
preventDoubleClick: true
|
|
44
44
|
}) }}
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
|
|
46
|
+
{% if allowSaveAndExit %}
|
|
47
|
+
{{ govukButton({
|
|
48
|
+
text: "Save and exit",
|
|
49
|
+
classes: "govuk-button--secondary",
|
|
50
|
+
name: "action",
|
|
51
|
+
value: "save-and-exit",
|
|
52
|
+
preventDoubleClick: true
|
|
53
|
+
}) }}
|
|
54
|
+
{% endif %}
|
|
55
|
+
</div>
|
|
56
|
+
</form>
|
|
47
57
|
</div>
|
|
48
58
|
</div>
|
|
49
59
|
|