@defra/forms-engine-plugin 1.4.0 → 2.0.0

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.
Files changed (78) hide show
  1. package/.server/server/plugins/engine/README.md +2 -46
  2. package/.server/server/plugins/engine/configureEnginePlugin.d.ts +1 -1
  3. package/.server/server/plugins/engine/configureEnginePlugin.js +5 -2
  4. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  5. package/.server/server/plugins/engine/helpers.d.ts +11 -0
  6. package/.server/server/plugins/engine/helpers.js +7 -1
  7. package/.server/server/plugins/engine/helpers.js.map +1 -1
  8. package/.server/server/plugins/engine/models/FormModel.js +2 -2
  9. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  10. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +1 -1
  11. package/.server/server/plugins/engine/models/SummaryViewModel.js +1 -1
  12. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  13. package/.server/server/plugins/engine/options.js +5 -3
  14. package/.server/server/plugins/engine/options.js.map +1 -1
  15. package/.server/server/plugins/engine/options.test.js +18 -9
  16. package/.server/server/plugins/engine/options.test.js.map +1 -1
  17. package/.server/server/plugins/engine/pageControllers/PageController.d.ts +3 -1
  18. package/.server/server/plugins/engine/pageControllers/PageController.js +5 -1
  19. package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
  20. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -1
  21. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +2 -4
  22. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  23. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +2 -2
  24. package/.server/server/plugins/engine/pageControllers/StartPageController.js +1 -3
  25. package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -1
  26. package/.server/server/plugins/engine/pageControllers/StatusPageController.d.ts +1 -0
  27. package/.server/server/plugins/engine/pageControllers/StatusPageController.js +1 -0
  28. package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -1
  29. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +0 -1
  30. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +1 -4
  31. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  32. package/.server/server/plugins/engine/pageControllers/TerminalPageController.d.ts +1 -0
  33. package/.server/server/plugins/engine/pageControllers/TerminalPageController.js +1 -0
  34. package/.server/server/plugins/engine/pageControllers/TerminalPageController.js.map +1 -1
  35. package/.server/server/plugins/engine/pageControllers/__stubs__/request.d.ts +4 -0
  36. package/.server/server/plugins/engine/pageControllers/__stubs__/request.js +14 -0
  37. package/.server/server/plugins/engine/pageControllers/__stubs__/request.js.map +1 -0
  38. package/.server/server/plugins/engine/pageControllers/__stubs__/server.d.ts +3 -0
  39. package/.server/server/plugins/engine/pageControllers/__stubs__/server.js +23 -0
  40. package/.server/server/plugins/engine/pageControllers/__stubs__/server.js.map +1 -0
  41. package/.server/server/plugins/engine/plugin.js +5 -6
  42. package/.server/server/plugins/engine/plugin.js.map +1 -1
  43. package/.server/server/plugins/engine/types.d.ts +7 -5
  44. package/.server/server/plugins/engine/types.js.map +1 -1
  45. package/.server/server/types.d.ts +2 -1
  46. package/.server/server/types.js.map +1 -1
  47. package/.server/typings/hapi/index.d.js.map +1 -1
  48. package/package.json +1 -1
  49. package/src/server/plugins/engine/README.md +2 -46
  50. package/src/server/plugins/engine/configureEnginePlugin.ts +4 -2
  51. package/src/server/plugins/engine/helpers.test.ts +3 -2
  52. package/src/server/plugins/engine/helpers.ts +9 -1
  53. package/src/server/plugins/engine/models/FormModel.test.ts +96 -21
  54. package/src/server/plugins/engine/models/FormModel.ts +5 -2
  55. package/src/server/plugins/engine/models/SummaryViewModel.test.ts +7 -5
  56. package/src/server/plugins/engine/models/SummaryViewModel.ts +1 -1
  57. package/src/server/plugins/engine/options.js +5 -3
  58. package/src/server/plugins/engine/options.test.js +22 -11
  59. package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +3 -3
  60. package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +12 -1
  61. package/src/server/plugins/engine/pageControllers/PageController.test.ts +9 -0
  62. package/src/server/plugins/engine/pageControllers/PageController.ts +10 -1
  63. package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +34 -28
  64. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +2 -5
  65. package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +19 -4
  66. package/src/server/plugins/engine/pageControllers/StartPageController.test.ts +32 -0
  67. package/src/server/plugins/engine/pageControllers/StartPageController.ts +2 -4
  68. package/src/server/plugins/engine/pageControllers/StatusPageController.test.ts +32 -0
  69. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +1 -0
  70. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +1 -5
  71. package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +9 -0
  72. package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +1 -0
  73. package/src/server/plugins/engine/pageControllers/__stubs__/request.ts +21 -0
  74. package/src/server/plugins/engine/pageControllers/__stubs__/server.ts +27 -0
  75. package/src/server/plugins/engine/plugin.ts +6 -6
  76. package/src/server/plugins/engine/types.ts +14 -9
  77. package/src/server/types.ts +2 -0
  78. package/src/typings/hapi/index.d.ts +2 -0
@@ -3,9 +3,13 @@ import { type ResponseToolkit } from '@hapi/hapi'
3
3
 
4
4
  import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
5
5
  import { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'
6
+ import {
7
+ buildFormContextRequest,
8
+ buildFormRequest
9
+ } from '~/src/server/plugins/engine/pageControllers/__stubs__/request.js'
10
+ import { serverWithSaveAndReturn } from '~/src/server/plugins/engine/pageControllers/__stubs__/server.js'
6
11
  import {
7
12
  type FormContext,
8
- type FormContextRequest,
9
13
  type FormPageViewModel,
10
14
  type FormState,
11
15
  type FormSubmissionState
@@ -51,7 +55,7 @@ describe('QuestionPageController', () => {
51
55
  controller1 = new QuestionPageController(model, page1)
52
56
  controller2 = new QuestionPageController(model, page2)
53
57
 
54
- requestPage1 = {
58
+ requestPage1 = buildFormRequest({
55
59
  method: 'get',
56
60
  url: page1Url,
57
61
  path: page1Url.pathname,
@@ -61,9 +65,9 @@ describe('QuestionPageController', () => {
61
65
  },
62
66
  query: {},
63
67
  app: { model }
64
- } as FormRequest
68
+ } as FormRequest)
65
69
 
66
- requestPage2 = {
70
+ requestPage2 = buildFormRequest({
67
71
  method: 'get',
68
72
  url: page2Url,
69
73
  path: page2Url.pathname,
@@ -73,7 +77,7 @@ describe('QuestionPageController', () => {
73
77
  },
74
78
  query: {},
75
79
  app: { model }
76
- } as FormRequest
80
+ } as FormRequest)
77
81
  })
78
82
 
79
83
  describe('Properties', () => {
@@ -289,7 +293,7 @@ describe('QuestionPageController', () => {
289
293
  applicantTwoAddress__postcode: 'Postcode'
290
294
  }
291
295
 
292
- let request = {
296
+ let request = buildFormContextRequest({
293
297
  method: 'get',
294
298
  url: new URL('http://example.com/test/applicant-one-address'),
295
299
  path: '/test/applicant-one-address',
@@ -299,7 +303,7 @@ describe('QuestionPageController', () => {
299
303
  },
300
304
  query: {},
301
305
  app: { model }
302
- } satisfies FormContextRequest
306
+ })
303
307
 
304
308
  // Calculate our context based on the page we're attempting to load and the above state we provide
305
309
  let context = controller.model.getFormContext(request, state)
@@ -331,7 +335,7 @@ describe('QuestionPageController', () => {
331
335
  // Now mark that we don't have a UK Passport
332
336
  state.ukPassport = false
333
337
 
334
- request = {
338
+ request = buildFormContextRequest({
335
339
  method: 'get',
336
340
  url: new URL('http://example.com/test/summary'),
337
341
  path: '/test/summary',
@@ -341,7 +345,7 @@ describe('QuestionPageController', () => {
341
345
  },
342
346
  query: {},
343
347
  app: { model }
344
- } satisfies FormContextRequest
348
+ })
345
349
 
346
350
  // And recalculate our context
347
351
  context = controller.model.getFormContext(request, state)
@@ -375,7 +379,7 @@ describe('QuestionPageController', () => {
375
379
 
376
380
  const controller = new QuestionPageController(model, pages[0])
377
381
 
378
- const request = {
382
+ const request = buildFormContextRequest({
379
383
  method: 'get',
380
384
  url: new URL('http://example.com/test/page-one'),
381
385
  path: '/test/page-one',
@@ -385,7 +389,7 @@ describe('QuestionPageController', () => {
385
389
  },
386
390
  query: {},
387
391
  app: { model }
388
- } satisfies FormContextRequest
392
+ })
389
393
 
390
394
  const context = controller.model.getFormContext(request, {
391
395
  $$__referenceNumber: 'foobar',
@@ -418,7 +422,7 @@ describe('QuestionPageController', () => {
418
422
  // The state below shows we said we had a UKPassport and entered details for an applicant
419
423
  const state: FormSubmissionState = { $$__referenceNumber: 'foobar' }
420
424
 
421
- const request = {
425
+ const request = buildFormContextRequest({
422
426
  method: 'get',
423
427
  url: new URL('http://example.com/test/page-one'),
424
428
  path: '/test/first-page',
@@ -428,7 +432,7 @@ describe('QuestionPageController', () => {
428
432
  },
429
433
  query: {},
430
434
  app: { model }
431
- } satisfies FormContextRequest
435
+ })
432
436
 
433
437
  const context = controller.model.getFormContext(request, state)
434
438
  const evaluationState = { animalType: 'Barn owl' }
@@ -474,7 +478,7 @@ describe('QuestionPageController', () => {
474
478
  // The state below shows we said we had a UKPassport and entered details for an applicant
475
479
  const state: FormSubmissionState = { $$__referenceNumber: 'foobar' }
476
480
 
477
- const request = {
481
+ const request = buildFormContextRequest({
478
482
  method: 'get',
479
483
  url: new URL('http://example.com/test/page-one'),
480
484
  path: '/test/first-page',
@@ -484,7 +488,7 @@ describe('QuestionPageController', () => {
484
488
  },
485
489
  query: {},
486
490
  app: { model }
487
- } satisfies FormContextRequest
491
+ })
488
492
 
489
493
  const context = controller.model.getFormContext(request, state)
490
494
  const evaluationState = { animalType: 'Swan' }
@@ -738,7 +742,7 @@ describe('QuestionPageController V2', () => {
738
742
  controller1 = model.pages[0] // new QuestionPageController(model, page1)
739
743
  controller2 = model.pages[1] // new QuestionPageController(model, page2)
740
744
 
741
- requestPage1 = {
745
+ requestPage1 = buildFormRequest({
742
746
  method: 'get',
743
747
  url: page1Url,
744
748
  path: page1Url.pathname,
@@ -748,9 +752,9 @@ describe('QuestionPageController V2', () => {
748
752
  },
749
753
  query: {},
750
754
  app: { model }
751
- } as FormRequest
755
+ } as FormRequest)
752
756
 
753
- requestPage2 = {
757
+ requestPage2 = buildFormRequest({
754
758
  method: 'get',
755
759
  url: page2Url,
756
760
  path: page2Url.pathname,
@@ -760,7 +764,7 @@ describe('QuestionPageController V2', () => {
760
764
  },
761
765
  query: {},
762
766
  app: { model }
763
- } as FormRequest
767
+ } as FormRequest)
764
768
  })
765
769
 
766
770
  describe('Properties', () => {
@@ -973,7 +977,7 @@ describe('QuestionPageController V2', () => {
973
977
  applicantTwoAddress__postcode: 'Postcode'
974
978
  }
975
979
 
976
- let request = {
980
+ let request = buildFormContextRequest({
977
981
  method: 'get',
978
982
  url: new URL('http://example.com/test/applicant-one-address'),
979
983
  path: '/test/applicant-one-address',
@@ -983,7 +987,7 @@ describe('QuestionPageController V2', () => {
983
987
  },
984
988
  query: {},
985
989
  app: { model }
986
- } satisfies FormContextRequest
990
+ })
987
991
 
988
992
  // Calculate our context based on the page we're attempting to load and the above state we provide
989
993
  let context = controller.model.getFormContext(request, state)
@@ -1015,7 +1019,7 @@ describe('QuestionPageController V2', () => {
1015
1019
  // Now mark that we don't have a UK Passport
1016
1020
  state.ukPassport = false
1017
1021
 
1018
- request = {
1022
+ request = buildFormContextRequest({
1019
1023
  method: 'get',
1020
1024
  url: new URL('http://example.com/test/summary'),
1021
1025
  path: '/test/summary',
@@ -1025,7 +1029,7 @@ describe('QuestionPageController V2', () => {
1025
1029
  },
1026
1030
  query: {},
1027
1031
  app: { model }
1028
- } satisfies FormContextRequest
1032
+ })
1029
1033
 
1030
1034
  // And recalculate our context
1031
1035
  context = controller.model.getFormContext(request, state)
@@ -1059,7 +1063,7 @@ describe('QuestionPageController V2', () => {
1059
1063
 
1060
1064
  const controller = new QuestionPageController(model, pages[0])
1061
1065
 
1062
- const request = {
1066
+ const request = buildFormContextRequest({
1063
1067
  method: 'get',
1064
1068
  url: new URL('http://example.com/test/page-one'),
1065
1069
  path: '/test/page-one',
@@ -1069,7 +1073,7 @@ describe('QuestionPageController V2', () => {
1069
1073
  },
1070
1074
  query: {},
1071
1075
  app: { model }
1072
- } satisfies FormContextRequest
1076
+ })
1073
1077
 
1074
1078
  const context = controller.model.getFormContext(request, {
1075
1079
  $$__referenceNumber: 'foobar',
@@ -1292,7 +1296,7 @@ describe('Save and Return functionality', () => {
1292
1296
 
1293
1297
  controller1 = new QuestionPageController(model, pages[0])
1294
1298
 
1295
- requestPage1 = {
1299
+ requestPage1 = buildFormRequest({
1296
1300
  method: 'get',
1297
1301
  url: new URL('http://example.com/test/first-page'),
1298
1302
  path: '/test/first-page',
@@ -1302,7 +1306,7 @@ describe('Save and Return functionality', () => {
1302
1306
  },
1303
1307
  query: {},
1304
1308
  app: { model }
1305
- } as FormRequest
1309
+ } as FormRequest)
1306
1310
  })
1307
1311
 
1308
1312
  const response = {
@@ -1321,7 +1325,9 @@ describe('Save and Return functionality', () => {
1321
1325
 
1322
1326
  describe('shouldShowSaveAndReturn', () => {
1323
1327
  it('should return true by default', () => {
1324
- expect(controller1.shouldShowSaveAndReturn()).toBe(true)
1328
+ expect(controller1.shouldShowSaveAndReturn(serverWithSaveAndReturn)).toBe(
1329
+ true
1330
+ )
1325
1331
  })
1326
1332
  })
1327
1333
 
@@ -49,6 +49,7 @@ import { merge } from '~/src/server/services/cacheService.js'
49
49
  export class QuestionPageController extends PageController {
50
50
  collection: ComponentCollection
51
51
  errorSummaryTitle = 'There is a problem'
52
+ allowSaveAndReturn = true
52
53
 
53
54
  constructor(model: FormModel, pageDef: Page) {
54
55
  super(model, pageDef)
@@ -174,7 +175,7 @@ export class QuestionPageController extends PageController {
174
175
  showTitle,
175
176
  components,
176
177
  errors,
177
- allowSaveAndReturn: this.shouldShowSaveAndReturn()
178
+ allowSaveAndReturn: this.shouldShowSaveAndReturn(request.server)
178
179
  }
179
180
  }
180
181
 
@@ -536,10 +537,6 @@ export class QuestionPageController extends PageController {
536
537
  return proceed(request, h, nextUrl)
537
538
  }
538
539
 
539
- shouldShowSaveAndReturn(): boolean {
540
- return true
541
- }
542
-
543
540
  /**
544
541
  * Handle save-and-return action by processing form data and redirecting to exit page
545
542
  */
@@ -1,5 +1,10 @@
1
1
  import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
2
2
  import { RepeatPageController } from '~/src/server/plugins/engine/pageControllers/RepeatPageController.js'
3
+ import { buildFormContextRequest } from '~/src/server/plugins/engine/pageControllers/__stubs__/request.js'
4
+ import {
5
+ server,
6
+ serverWithSaveAndReturn
7
+ } from '~/src/server/plugins/engine/pageControllers/__stubs__/server.js'
3
8
  import {
4
9
  type FormContextRequest,
5
10
  type FormPageViewModel,
@@ -44,7 +49,7 @@ describe('RepeatPageController', () => {
44
49
 
45
50
  controller = new RepeatPageController(model, pages[0])
46
51
 
47
- requestPage = {
52
+ requestPage = buildFormContextRequest({
48
53
  method: 'get',
49
54
  url: pageUrl,
50
55
  path: pageUrl.pathname,
@@ -54,7 +59,7 @@ describe('RepeatPageController', () => {
54
59
  },
55
60
  query: {},
56
61
  app: { model }
57
- }
62
+ })
58
63
 
59
64
  requestPageItem = {
60
65
  method: 'get',
@@ -66,7 +71,8 @@ describe('RepeatPageController', () => {
66
71
  itemId: itemId1
67
72
  },
68
73
  query: {},
69
- app: { model }
74
+ app: { model },
75
+ server
70
76
  }
71
77
 
72
78
  requestPageSummary = {
@@ -78,7 +84,8 @@ describe('RepeatPageController', () => {
78
84
  slug: 'repeat'
79
85
  },
80
86
  query: {},
81
- app: { model }
87
+ app: { model },
88
+ server
82
89
  }
83
90
  })
84
91
 
@@ -263,4 +270,12 @@ describe('RepeatPageController', () => {
263
270
  expect(result.errors).toHaveLength(3)
264
271
  })
265
272
  })
273
+
274
+ describe('shouldShowSaveAndReturn', () => {
275
+ it('should return true when save and return is enabled', () => {
276
+ expect(controller.shouldShowSaveAndReturn(serverWithSaveAndReturn)).toBe(
277
+ true
278
+ )
279
+ })
280
+ })
266
281
  })
@@ -0,0 +1,32 @@
1
+ import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
2
+ import { StartPageController } from '~/src/server/plugins/engine/pageControllers/StartPageController.js'
3
+ import { serverWithSaveAndReturn } from '~/src/server/plugins/engine/pageControllers/__stubs__/server.js'
4
+ import definition from '~/test/form/definitions/basic.js'
5
+
6
+ describe('StartPageController', () => {
7
+ let model: FormModel
8
+ let controller: StartPageController
9
+
10
+ beforeEach(() => {
11
+ model = new FormModel(definition, {
12
+ basePath: 'test'
13
+ })
14
+
15
+ // Create a mock page for StartPageController
16
+ const mockPage = {
17
+ ...definition.pages[0],
18
+ controller: 'start'
19
+ }
20
+
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ controller = new StartPageController(model, mockPage as any)
23
+ })
24
+
25
+ describe('shouldShowSaveAndReturn', () => {
26
+ it('should return false (StartPageController does not allow save and return)', () => {
27
+ expect(controller.shouldShowSaveAndReturn(serverWithSaveAndReturn)).toBe(
28
+ false
29
+ )
30
+ })
31
+ })
32
+ })
@@ -9,14 +9,12 @@ export class StartPageController extends QuestionPageController {
9
9
  * but start pages should really live on gov.uk (whitehall publisher) so a user can be properly signposted.
10
10
  */
11
11
 
12
+ allowSaveAndReturn = false
13
+
12
14
  getViewModel(request: FormRequest, context: FormContext) {
13
15
  return {
14
16
  ...super.getViewModel(request, context),
15
17
  isStartPage: true
16
18
  }
17
19
  }
18
-
19
- shouldShowSaveAndReturn(): boolean {
20
- return false
21
- }
22
20
  }
@@ -0,0 +1,32 @@
1
+ import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
2
+ import { StatusPageController } from '~/src/server/plugins/engine/pageControllers/StatusPageController.js'
3
+ import { serverWithSaveAndReturn } from '~/src/server/plugins/engine/pageControllers/__stubs__/server.js'
4
+ import definition from '~/test/form/definitions/basic.js'
5
+
6
+ describe('StatusPageController', () => {
7
+ let model: FormModel
8
+ let controller: StatusPageController
9
+
10
+ beforeEach(() => {
11
+ model = new FormModel(definition, {
12
+ basePath: 'test'
13
+ })
14
+
15
+ // Create a mock page for StatusPageController
16
+ const mockPage = {
17
+ ...definition.pages[0],
18
+ controller: 'status'
19
+ }
20
+
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ controller = new StatusPageController(model, mockPage as any)
23
+ })
24
+
25
+ describe('shouldShowSaveAndReturn', () => {
26
+ it('should return false (StatusPageController does not allow save and return)', () => {
27
+ expect(controller.shouldShowSaveAndReturn(serverWithSaveAndReturn)).toBe(
28
+ false
29
+ )
30
+ })
31
+ })
32
+ })
@@ -9,6 +9,7 @@ import { type FormRequest } from '~/src/server/routes/types.js'
9
9
 
10
10
  export class StatusPageController extends QuestionPageController {
11
11
  declare pageDef: PageStatus
12
+ allowSaveAndReturn = false
12
13
 
13
14
  constructor(model: FormModel, pageDef: PageStatus) {
14
15
  super(model, pageDef)
@@ -68,7 +68,7 @@ export class SummaryPageController extends QuestionPageController {
68
68
  viewModel.feedbackLink = this.feedbackLink
69
69
  viewModel.phaseTag = this.phaseTag
70
70
  viewModel.components = components
71
- viewModel.allowSaveAndReturn = this.shouldShowSaveAndReturn()
71
+ viewModel.allowSaveAndReturn = this.shouldShowSaveAndReturn(request.server)
72
72
 
73
73
  return viewModel
74
74
  }
@@ -144,10 +144,6 @@ export class SummaryPageController extends QuestionPageController {
144
144
  }
145
145
  }
146
146
  }
147
-
148
- shouldShowSaveAndReturn(): boolean {
149
- return true
150
- }
151
147
  }
152
148
 
153
149
  async function submitForm(
@@ -1,5 +1,6 @@
1
1
  import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
2
2
  import { TerminalPageController } from '~/src/server/plugins/engine/pageControllers/TerminalPageController.js'
3
+ import { serverWithSaveAndReturn } from '~/src/server/plugins/engine/pageControllers/__stubs__/server.js'
3
4
  import definition from '~/test/form/definitions/basic.js'
4
5
 
5
6
  describe('TerminalController', () => {
@@ -25,4 +26,12 @@ describe('TerminalController', () => {
25
26
  )
26
27
  })
27
28
  })
29
+
30
+ describe('shouldShowSaveAndReturn', () => {
31
+ it('should return false (TerminalPageController does not allow save and return)', () => {
32
+ expect(controller1.shouldShowSaveAndReturn(serverWithSaveAndReturn)).toBe(
33
+ false
34
+ )
35
+ })
36
+ })
28
37
  })
@@ -8,6 +8,7 @@ import { type FormRequestPayload } from '~/src/server/routes/types.js'
8
8
 
9
9
  export class TerminalPageController extends QuestionPageController {
10
10
  declare pageDef: PageTerminal
11
+ allowSaveAndReturn = false
11
12
 
12
13
  makePostRouteHandler(): (
13
14
  request: FormRequestPayload,
@@ -0,0 +1,21 @@
1
+ import { server } from '~/src/server/plugins/engine/pageControllers/__stubs__/server.js'
2
+ import { type FormContextRequest } from '~/src/server/plugins/engine/types.js'
3
+ import { type FormRequest } from '~/src/server/routes/types.js'
4
+
5
+ export function buildFormRequest(
6
+ request: Omit<FormRequest, 'server'>
7
+ ): FormRequest {
8
+ return {
9
+ ...request,
10
+ server
11
+ } as FormRequest
12
+ }
13
+
14
+ export function buildFormContextRequest(
15
+ request: Omit<FormContextRequest, 'server'>
16
+ ): FormContextRequest {
17
+ return {
18
+ ...request,
19
+ server
20
+ } as FormContextRequest
21
+ }
@@ -0,0 +1,27 @@
1
+ import { type Server } from '@hapi/hapi'
2
+
3
+ import { type PluginOptions } from '~/src/server/plugins/engine/types.js'
4
+ import { type CacheService } from '~/src/server/services/index.js'
5
+
6
+ export const server: Server = {
7
+ plugins: {
8
+ 'forms-engine-plugin': {
9
+ baseLayoutPath: '',
10
+ cacheService: {} as CacheService
11
+ }
12
+ }
13
+ } as Server // only mocking out properties we care about;
14
+
15
+ export const serverWithSaveAndReturn: Server = {
16
+ plugins: {
17
+ ...server.plugins,
18
+ 'forms-engine-plugin': {
19
+ ...server.plugins['forms-engine-plugin'],
20
+ saveAndReturn: {
21
+ keyGenerator: jest.fn().mockReturnValue('foobar'),
22
+ sessionHydrator: jest.fn().mockReturnValue({}),
23
+ sessionPersister: jest.fn().mockImplementation(() => Promise.resolve())
24
+ } as Pick<PluginOptions, 'saveAndReturn'>
25
+ }
26
+ }
27
+ } as Server // only mocking out properties we care about
@@ -32,20 +32,19 @@ export const plugin = {
32
32
  const {
33
33
  model,
34
34
  cacheName,
35
- keyGenerator,
36
- sessionHydrator,
37
- sessionPersister,
35
+ saveAndReturn,
38
36
  nunjucks: nunjucksOptions,
39
37
  viewContext,
40
38
  preparePageEventRequestOptions
41
39
  } = options
40
+
42
41
  const cacheService = new CacheService({
43
42
  server,
44
43
  cacheName,
45
44
  options: {
46
- keyGenerator,
47
- sessionHydrator,
48
- sessionPersister
45
+ keyGenerator: saveAndReturn?.keyGenerator,
46
+ sessionHydrator: saveAndReturn?.sessionHydrator,
47
+ sessionPersister: saveAndReturn?.sessionPersister
49
48
  }
50
49
  })
51
50
 
@@ -54,6 +53,7 @@ export const plugin = {
54
53
  server.expose('baseLayoutPath', nunjucksOptions.baseLayoutPath)
55
54
  server.expose('viewContext', viewContext)
56
55
  server.expose('cacheService', cacheService)
56
+ server.expose('saveAndReturn', saveAndReturn)
57
57
 
58
58
  server.app.model = model
59
59
 
@@ -177,7 +177,10 @@ export type FormContextRequest = (
177
177
  payload?: object | undefined
178
178
  }
179
179
  ) &
180
- Pick<FormRequest, 'app' | 'method' | 'params' | 'path' | 'query' | 'url'>
180
+ Pick<
181
+ FormRequest,
182
+ 'app' | 'method' | 'params' | 'path' | 'query' | 'url' | 'server'
183
+ >
181
184
 
182
185
  export interface UploadInitiateResponse {
183
186
  uploadId: string
@@ -305,7 +308,7 @@ export interface FormPageViewModel extends PageViewModelBase {
305
308
  context: FormContext
306
309
  errors?: FormSubmissionError[]
307
310
  hasMissingNotificationEmail?: boolean
308
- allowSaveAndReturn?: boolean
311
+ allowSaveAndReturn: boolean
309
312
  }
310
313
 
311
314
  export interface RepeaterSummaryPageViewModel extends PageViewModelBase {
@@ -363,13 +366,15 @@ export interface PluginOptions {
363
366
  cacheName?: string
364
367
  globals?: Record<string, GlobalFunction>
365
368
  filters?: Record<string, FilterFunction>
366
- keyGenerator?: (request: RequestType) => string
367
- sessionHydrator?: (request: RequestType) => Promise<FormSubmissionState>
368
- sessionPersister?: (
369
- key: string,
370
- state: FormSubmissionState,
371
- request: RequestType
372
- ) => Promise<void>
369
+ saveAndReturn?: {
370
+ keyGenerator: (request: RequestType) => string
371
+ sessionHydrator: (request: RequestType) => Promise<FormSubmissionState>
372
+ sessionPersister: (
373
+ key: string,
374
+ state: FormSubmissionState,
375
+ request: RequestType
376
+ ) => Promise<void>
377
+ }
373
378
  pluginPath?: string
374
379
  nunjucks: {
375
380
  baseLayoutPath: string
@@ -10,6 +10,7 @@ import { type DetailItem } from '~/src/server/plugins/engine/models/types.js'
10
10
  import { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'
11
11
  import {
12
12
  type OnRequestCallback,
13
+ type PluginOptions,
13
14
  type PreparePageEventRequestOptions
14
15
  } from '~/src/server/plugins/engine/types.js'
15
16
  import {
@@ -47,6 +48,7 @@ export interface RouteConfig {
47
48
  controllers?: Record<string, typeof PageController>
48
49
  preparePageEventRequestOptions?: PreparePageEventRequestOptions
49
50
  onRequest?: OnRequestCallback
51
+ saveAndReturn?: PluginOptions['saveAndReturn']
50
52
  }
51
53
 
52
54
  export interface OutputService {
@@ -5,6 +5,7 @@ import { type ServerYar, type Yar } from '@hapi/yar'
5
5
  import { type Logger } from 'pino'
6
6
 
7
7
  import { type FormModel } from '~/src/server/plugins/engine/models/index.js'
8
+ import { type PluginOptions } from '~/src/server/plugins/engine/types.ts'
8
9
  import {
9
10
  type FormRequest,
10
11
  type FormRequestPayload
@@ -24,6 +25,7 @@ declare module '@hapi/hapi' {
24
25
  viewContext?: (
25
26
  request: FormRequest | FormRequestPayload | null
26
27
  ) => Record<string, unknown> | Promise<Record<string, unknown>>
28
+ saveAndReturn?: PluginOptions['saveAndReturn']
27
29
  }
28
30
  }
29
31