@planning-inspectorate/dynamic-forms 3.20.5 → 3.22.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 (69) hide show
  1. package/README.md +100 -0
  2. package/docs/Dynamic Sections.md +47 -0
  3. package/docs/Getting Started.md +8 -2
  4. package/package.json +1 -1
  5. package/src/components/boolean/question.d.ts +1 -1
  6. package/src/components/boolean/question.js +1 -1
  7. package/src/components/date/question.d.ts +1 -1
  8. package/src/components/date/question.js +1 -1
  9. package/src/components/date-period/question.d.ts +1 -1
  10. package/src/components/date-period/question.js +1 -1
  11. package/src/components/date-time/question.d.ts +1 -1
  12. package/src/components/date-time/question.js +1 -1
  13. package/src/components/manage-list/question.d.ts.map +1 -1
  14. package/src/components/manage-list/question.js +5 -0
  15. package/src/components/manage-list/question.test.js +3 -1
  16. package/src/components/multi-field-input/question.d.ts.map +1 -1
  17. package/src/components/multi-field-input/question.js +8 -6
  18. package/src/components/multi-field-input/question.test.js +126 -213
  19. package/src/components/single-line-input/index.njk +4 -0
  20. package/src/components/single-line-input/question.d.ts +2 -0
  21. package/src/components/single-line-input/question.d.ts.map +1 -1
  22. package/src/components/single-line-input/question.js +4 -0
  23. package/src/components/single-line-input/question.test.js +6 -0
  24. package/src/components/text-entry-redact/question.d.ts.map +1 -1
  25. package/src/components/text-entry-redact/question.js +3 -1
  26. package/src/components/text-entry-redact/question.test.js +9 -0
  27. package/src/components/unit-option-entry/question.d.ts +1 -1
  28. package/src/components/unit-option-entry/question.d.ts.map +1 -1
  29. package/src/components/unit-option-entry/question.js +4 -2
  30. package/src/components/unit-option-entry/question.test.js +9 -0
  31. package/src/controller.d.ts +15 -3
  32. package/src/controller.d.ts.map +1 -1
  33. package/src/controller.js +19 -11
  34. package/src/controller.test.js +182 -153
  35. package/src/dynamic-section.d.ts +40 -0
  36. package/src/dynamic-section.d.ts.map +1 -0
  37. package/src/dynamic-section.js +51 -0
  38. package/src/dynamic-section.test.js +113 -0
  39. package/src/index.d.ts +2 -1
  40. package/src/index.js +2 -1
  41. package/src/index.test.js +3 -0
  42. package/src/journey/journey.d.ts +10 -0
  43. package/src/journey/journey.d.ts.map +1 -1
  44. package/src/journey/journey.js +15 -0
  45. package/src/lib/answer-utils.d.ts +22 -0
  46. package/src/lib/answer-utils.d.ts.map +1 -0
  47. package/src/lib/answer-utils.js +34 -0
  48. package/src/{components/manage-list/utils.test.js → lib/answer-utils.test.js} +9 -11
  49. package/src/lib/session-answer-store.d.ts.map +1 -1
  50. package/src/lib/session-answer-store.js +14 -6
  51. package/src/lib/session-answer-store.test.js +43 -0
  52. package/src/middleware/redirect-to-unanswered-question.d.ts.map +1 -1
  53. package/src/middleware/redirect-to-unanswered-question.js +4 -3
  54. package/src/middleware/redirect-to-unanswered-question.test.js +32 -0
  55. package/src/questions/options-question.js +1 -1
  56. package/src/questions/question.d.ts +8 -3
  57. package/src/questions/question.d.ts.map +1 -1
  58. package/src/questions/question.js +16 -6
  59. package/src/questions/question.test.js +19 -0
  60. package/src/section.d.ts +19 -0
  61. package/src/section.d.ts.map +1 -1
  62. package/src/section.js +50 -9
  63. package/src/section.test.js +9 -0
  64. package/test/dynamic-journey.test.js +372 -0
  65. package/typedefs/question-props.d.ts +3 -1
  66. package/typedefs/question-types.d.ts +3 -0
  67. package/src/components/manage-list/utils.d.ts +0 -18
  68. package/src/components/manage-list/utils.d.ts.map +0 -1
  69. package/src/components/manage-list/utils.js +0 -35
@@ -2,6 +2,8 @@ import { describe, it, mock } from 'node:test';
2
2
  import assert from 'node:assert';
3
3
  import MultiFieldInputQuestion from './question.js';
4
4
  import { Journey } from '#journey';
5
+ import { Section } from '#section';
6
+ import { DynamicSection } from '#src/dynamic-section.js';
5
7
 
6
8
  const TITLE = 'title';
7
9
  const QUESTION = 'Question?';
@@ -226,30 +228,39 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
226
228
  });
227
229
 
228
230
  describe('formatAnswerForSummary', () => {
229
- it('should return formatted answer', async () => {
230
- const question = createMultiFieldInputQuestion();
231
+ const createJourney = (response, question = createMultiFieldInputQuestion(), dynamicSection = false) => {
232
+ const section = dynamicSection
233
+ ? new DynamicSection('Questions', 'questions', 'myList')
234
+ : new Section('Questions', 'questions');
231
235
  const journey = new Journey({
232
236
  journeyId: 'TEST',
233
237
  makeBaseUrl: () => 'base',
234
238
  taskListUrl: 'cases/create-a-case/check-your-answers',
235
- response: {
236
- answers: {
237
- testField1: 'planning-permission',
238
- testField2: 'Test User'
239
- }
240
- },
239
+ response,
241
240
  journeyTemplate: 'mock template',
242
241
  taskListTemplate: 'mock path',
243
242
  journeyTitle: 'mock title',
244
- sections: []
243
+ sections: [section.addQuestion(question)]
244
+ });
245
+ return { question, journey };
246
+ };
247
+ const action = {
248
+ href: 'base/questions/' + FIELDNAME,
249
+ visuallyHiddenText: QUESTION
250
+ };
251
+ it('should return formatted answer', async () => {
252
+ const { question, journey } = createJourney({
253
+ answers: {
254
+ testField1: 'planning-permission',
255
+ testField2: 'Test User'
256
+ }
245
257
  });
246
258
 
247
259
  const expectedResult = [
248
260
  {
249
261
  action: {
250
- href: 'base/cases/create-a-case/check-your-answers',
251
- text: 'Change',
252
- visuallyHiddenText: 'Question?'
262
+ ...action,
263
+ text: 'Change'
253
264
  },
254
265
  key: 'title',
255
266
  value: 'planning-permission<br>Test User'
@@ -261,29 +272,18 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
261
272
  assert.deepStrictEqual(result, expectedResult);
262
273
  });
263
274
  it('should return an empty string as answer text for unanswered multi field question', async () => {
264
- const question = createMultiFieldInputQuestion();
265
- const journey = new Journey({
266
- journeyId: 'TEST',
267
- makeBaseUrl: () => 'base',
268
- taskListUrl: 'cases/create-a-case/check-your-answers',
269
- response: {
270
- answers: {
271
- testField1: null,
272
- testField2: null
273
- }
274
- },
275
- journeyTemplate: 'mock template',
276
- taskListTemplate: 'mock path',
277
- journeyTitle: 'mock title',
278
- sections: []
275
+ const { question, journey } = createJourney({
276
+ answers: {
277
+ testField1: null,
278
+ testField2: null
279
+ }
279
280
  });
280
281
 
281
282
  const expectedResult = [
282
283
  {
283
284
  action: {
284
- href: 'base/cases/create-a-case/check-your-answers',
285
- text: 'Answer',
286
- visuallyHiddenText: 'Question?'
285
+ ...action,
286
+ text: 'Answer'
287
287
  },
288
288
  key: 'title',
289
289
  value: ''
@@ -295,29 +295,18 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
295
295
  assert.deepStrictEqual(result, expectedResult);
296
296
  });
297
297
  it('should return not started text for undefined multi field question', async () => {
298
- const question = createMultiFieldInputQuestion();
299
- const journey = new Journey({
300
- journeyId: 'TEST',
301
- makeBaseUrl: () => 'base',
302
- taskListUrl: 'cases/create-a-case/check-your-answers',
303
- response: {
304
- answers: {
305
- testField1: undefined,
306
- testField2: undefined
307
- }
308
- },
309
- journeyTemplate: 'mock template',
310
- taskListTemplate: 'mock path',
311
- journeyTitle: 'mock title',
312
- sections: []
298
+ const { question, journey } = createJourney({
299
+ answers: {
300
+ testField1: undefined,
301
+ testField2: undefined
302
+ }
313
303
  });
314
304
 
315
305
  const expectedResult = [
316
306
  {
317
307
  action: {
318
- href: 'base/cases/create-a-case/check-your-answers',
319
- text: 'Answer',
320
- visuallyHiddenText: 'Question?'
308
+ ...action,
309
+ text: 'Answer'
321
310
  },
322
311
  key: 'title',
323
312
  value: 'Not started'
@@ -329,26 +318,15 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
329
318
  assert.deepStrictEqual(result, expectedResult);
330
319
  });
331
320
  it('should return escaped text with newlines (no <br>) when isInManageListSection is true', () => {
332
- const question = createMultiFieldInputQuestion();
321
+ const { question, journey } = createJourney({
322
+ answers: {
323
+ testField1: 'Line 1',
324
+ testField2: 'Line & 2'
325
+ }
326
+ });
333
327
 
334
328
  question.isInManageListSection = true;
335
329
 
336
- const journey = new Journey({
337
- journeyId: 'TEST',
338
- makeBaseUrl: () => 'base',
339
- taskListUrl: 'cases/create-a-case/check-your-answers',
340
- response: {
341
- answers: {
342
- testField1: 'Line 1',
343
- testField2: 'Line & 2'
344
- }
345
- },
346
- journeyTemplate: 'mock template',
347
- taskListTemplate: 'mock path',
348
- journeyTitle: 'mock title',
349
- sections: []
350
- });
351
-
352
330
  const expectedValue = 'Line 1\nLine &amp; 2';
353
331
 
354
332
  const result = question.formatAnswerForSummary('questions', journey);
@@ -365,21 +343,15 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
365
343
  formatSummaryValue: ({ formattedAnswer }) => `Custom: ${formattedAnswer}`
366
344
  });
367
345
 
368
- const journey = new Journey({
369
- journeyId: 'TEST',
370
- makeBaseUrl: () => 'base',
371
- taskListUrl: 'cases/create-a-case/check-your-answers',
372
- response: {
346
+ const { journey } = createJourney(
347
+ {
373
348
  answers: {
374
349
  testField1: 'Value 1',
375
350
  testField2: 'Value 2'
376
351
  }
377
352
  },
378
- journeyTemplate: 'mock template',
379
- taskListTemplate: 'mock path',
380
- journeyTitle: 'mock title',
381
- sections: []
382
- });
353
+ question
354
+ );
383
355
 
384
356
  const result = question.formatAnswerForSummary('questions', journey);
385
357
 
@@ -397,22 +369,15 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
397
369
  { fieldName: 'testField2', formatSummaryValue, formatJoinString: '<br>' }
398
370
  ]
399
371
  });
400
-
401
- const journey = new Journey({
402
- journeyId: 'TEST',
403
- makeBaseUrl: () => 'base',
404
- taskListUrl: 'cases/create-a-case/check-your-answers',
405
- response: {
372
+ const { journey } = createJourney(
373
+ {
406
374
  answers: {
407
375
  testField1: 'Value 1',
408
376
  testField2: 'Value 2'
409
377
  }
410
378
  },
411
- journeyTemplate: 'mock template',
412
- taskListTemplate: 'mock path',
413
- journeyTitle: 'mock title',
414
- sections: []
415
- });
379
+ question
380
+ );
416
381
 
417
382
  // formatSummaryValue should be applied in summary (with HTML not escaped)
418
383
  const summaryResult = question.formatAnswerForSummary('questions', journey);
@@ -432,22 +397,16 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
432
397
  inputFields: [{ fieldName: 'testField1', formatSummaryValue }]
433
398
  });
434
399
 
435
- const journey = new Journey({
436
- journeyId: 'TEST',
437
- makeBaseUrl: () => 'base',
438
- taskListUrl: 'cases/create-a-case/check-your-answers',
439
- response: {
400
+ const { journey } = createJourney(
401
+ {
440
402
  answers: {
441
403
  testField1: 'Test Value'
442
404
  }
443
405
  },
444
- journeyTemplate: 'mock template',
445
- taskListTemplate: 'mock path',
446
- journeyTitle: 'mock title',
447
- sections: []
448
- });
406
+ question
407
+ );
449
408
 
450
- question.formatAnswerForSummary('test-section', journey);
409
+ question.formatAnswerForSummary('questions', journey);
451
410
 
452
411
  assert.strictEqual(formatSummaryValue.mock.callCount(), 1);
453
412
  const capturedContext = formatSummaryValue.mock.calls[0].arguments[0];
@@ -455,7 +414,7 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
455
414
  assert.strictEqual(capturedContext.formattedAnswer, 'Test Value');
456
415
  assert.strictEqual(capturedContext.question, question);
457
416
  assert.strictEqual(capturedContext.journey, journey);
458
- assert.strictEqual(capturedContext.sectionSegment, 'test-section');
417
+ assert.strictEqual(capturedContext.sectionSegment, 'questions');
459
418
  assert.strictEqual(capturedContext.field.fieldName, 'testField1');
460
419
  });
461
420
  it('should apply formatPrefix to each field value in summary', () => {
@@ -468,22 +427,15 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
468
427
  { fieldName: 'testField2', formatPrefix: 'Email: ' }
469
428
  ]
470
429
  });
471
-
472
- const journey = new Journey({
473
- journeyId: 'TEST',
474
- makeBaseUrl: () => 'base',
475
- taskListUrl: 'cases/create-a-case/check-your-answers',
476
- response: {
430
+ const { journey } = createJourney(
431
+ {
477
432
  answers: {
478
433
  testField1: 'John Doe',
479
434
  testField2: 'john@example.com'
480
435
  }
481
436
  },
482
- journeyTemplate: 'mock template',
483
- taskListTemplate: 'mock path',
484
- journeyTitle: 'mock title',
485
- sections: []
486
- });
437
+ question
438
+ );
487
439
 
488
440
  const result = question.formatAnswerForSummary('questions', journey);
489
441
 
@@ -492,21 +444,15 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
492
444
  it('should only include answered fields in summary (partial answers)', () => {
493
445
  const question = createMultiFieldInputQuestion();
494
446
 
495
- const journey = new Journey({
496
- journeyId: 'TEST',
497
- makeBaseUrl: () => 'base',
498
- taskListUrl: 'cases/create-a-case/check-your-answers',
499
- response: {
447
+ const { journey } = createJourney(
448
+ {
500
449
  answers: {
501
450
  testField1: 'Answered value',
502
451
  testField2: null
503
452
  }
504
453
  },
505
- journeyTemplate: 'mock template',
506
- taskListTemplate: 'mock path',
507
- journeyTitle: 'mock title',
508
- sections: []
509
- });
454
+ question
455
+ );
510
456
 
511
457
  const result = question.formatAnswerForSummary('questions', journey);
512
458
 
@@ -521,43 +467,26 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
521
467
  inputFields: [{ fieldName: 'testField1' }, { fieldName: 'testField2' }]
522
468
  });
523
469
 
524
- const journey = new Journey({
525
- journeyId: 'TEST',
526
- makeBaseUrl: () => 'base',
527
- taskListUrl: 'cases/create-a-case/check-your-answers',
528
- response: {
470
+ const { journey } = createJourney(
471
+ {
529
472
  answers: {
530
473
  testField1: false,
531
474
  testField2: 0
532
475
  }
533
476
  },
534
- journeyTemplate: 'mock template',
535
- taskListTemplate: 'mock path',
536
- journeyTitle: 'mock title',
537
- sections: []
538
- });
477
+ question
478
+ );
539
479
 
540
480
  const result = question.formatAnswerForSummary('questions', journey);
541
481
 
542
482
  assert.strictEqual(result[0].value, 'false<br>0');
543
483
  });
544
484
  it('should exclude fields with an empty string answer from the summary', () => {
545
- const question = createMultiFieldInputQuestion();
546
-
547
- const journey = new Journey({
548
- journeyId: 'TEST',
549
- makeBaseUrl: () => 'base',
550
- taskListUrl: 'cases/create-a-case/check-your-answers',
551
- response: {
552
- answers: {
553
- testField1: 'Answered value',
554
- testField2: ''
555
- }
556
- },
557
- journeyTemplate: 'mock template',
558
- taskListTemplate: 'mock path',
559
- journeyTitle: 'mock title',
560
- sections: []
485
+ const { journey, question } = createJourney({
486
+ answers: {
487
+ testField1: 'Answered value',
488
+ testField2: ''
489
+ }
561
490
  });
562
491
 
563
492
  const result = question.formatAnswerForSummary('questions', journey);
@@ -566,22 +495,11 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
566
495
  assert.strictEqual(result[0].value, 'Answered value');
567
496
  });
568
497
  it('should escape HTML characters in field values by default', () => {
569
- const question = createMultiFieldInputQuestion();
570
-
571
- const journey = new Journey({
572
- journeyId: 'TEST',
573
- makeBaseUrl: () => 'base',
574
- taskListUrl: 'cases/create-a-case/check-your-answers',
575
- response: {
576
- answers: {
577
- testField1: '<script>alert("xss")</script>',
578
- testField2: 'Safe & Sound'
579
- }
580
- },
581
- journeyTemplate: 'mock template',
582
- taskListTemplate: 'mock path',
583
- journeyTitle: 'mock title',
584
- sections: []
498
+ const { journey, question } = createJourney({
499
+ answers: {
500
+ testField1: '<script>alert("xss")</script>',
501
+ testField2: 'Safe & Sound'
502
+ }
585
503
  });
586
504
 
587
505
  const result = question.formatAnswerForSummary('questions', journey);
@@ -598,22 +516,15 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
598
516
  { fieldName: 'testField2' }
599
517
  ]
600
518
  });
601
-
602
- const journey = new Journey({
603
- journeyId: 'TEST',
604
- makeBaseUrl: () => 'base',
605
- taskListUrl: 'cases/create-a-case/check-your-answers',
606
- response: {
519
+ const { journey } = createJourney(
520
+ {
607
521
  answers: {
608
522
  testField1: 'Value 1',
609
523
  testField2: 'Value 2'
610
524
  }
611
525
  },
612
- journeyTemplate: 'mock template',
613
- taskListTemplate: 'mock path',
614
- journeyTitle: 'mock title',
615
- sections: []
616
- });
526
+ question
527
+ );
617
528
 
618
529
  const result = question.formatAnswerForSummary('questions', journey);
619
530
 
@@ -632,22 +543,15 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
632
543
  { fieldName: 'testField2', formatTextFunction }
633
544
  ]
634
545
  });
635
-
636
- const journey = new Journey({
637
- journeyId: 'TEST',
638
- makeBaseUrl: () => 'base',
639
- taskListUrl: 'cases/create-a-case/check-your-answers',
640
- response: {
546
+ const { journey } = createJourney(
547
+ {
641
548
  answers: {
642
549
  testField1: 'Value 1',
643
550
  testField2: 'Value 2'
644
551
  }
645
552
  },
646
- journeyTemplate: 'mock template',
647
- taskListTemplate: 'mock path',
648
- journeyTitle: 'mock title',
649
- sections: []
650
- });
553
+ question
554
+ );
651
555
 
652
556
  const result = question.formatAnswerForSummary('questions', journey);
653
557
 
@@ -662,20 +566,14 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
662
566
  inputFields: [{ fieldName: 'testField1', formatTextFunction }]
663
567
  });
664
568
 
665
- const journey = new Journey({
666
- journeyId: 'TEST',
667
- makeBaseUrl: () => 'base',
668
- taskListUrl: 'cases/create-a-case/check-your-answers',
669
- response: {
569
+ const { journey } = createJourney(
570
+ {
670
571
  answers: {
671
572
  testField1: 'Value 1'
672
573
  }
673
574
  },
674
- journeyTemplate: 'mock template',
675
- taskListTemplate: 'mock path',
676
- journeyTitle: 'mock title',
677
- sections: []
678
- });
575
+ question
576
+ );
679
577
 
680
578
  const result = question.formatAnswerForSummary('questions', journey);
681
579
 
@@ -691,20 +589,14 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
691
589
  inputFields: [{ fieldName: 'testField1', formatTextFunction, formatSummaryValue }]
692
590
  });
693
591
 
694
- const journey = new Journey({
695
- journeyId: 'TEST',
696
- makeBaseUrl: () => 'base',
697
- taskListUrl: 'cases/create-a-case/check-your-answers',
698
- response: {
592
+ const { journey } = createJourney(
593
+ {
699
594
  answers: {
700
595
  testField1: 'Value 1'
701
596
  }
702
597
  },
703
- journeyTemplate: 'mock template',
704
- taskListTemplate: 'mock path',
705
- journeyTitle: 'mock title',
706
- sections: []
707
- });
598
+ question
599
+ );
708
600
 
709
601
  const result = question.formatAnswerForSummary('questions', journey);
710
602
 
@@ -727,26 +619,47 @@ describe('./src/dynamic-forms/components/multi-field-input/question.js', () => {
727
619
  ]
728
620
  });
729
621
 
730
- const journey = new Journey({
731
- journeyId: 'TEST',
732
- makeBaseUrl: () => 'base',
733
- taskListUrl: 'cases/create-a-case/check-your-answers',
734
- response: {
622
+ const { journey } = createJourney(
623
+ {
735
624
  answers: {
736
625
  testField1: 'Value 1',
737
626
  testField2: 'Value 2'
738
627
  }
739
628
  },
740
- journeyTemplate: 'mock template',
741
- taskListTemplate: 'mock path',
742
- journeyTitle: 'mock title',
743
- sections: []
744
- });
629
+ question
630
+ );
745
631
 
746
632
  const result = question.formatAnswerForSummary('questions', journey);
747
633
 
748
634
  assert.strictEqual(result[0].value, 'Value 1 - Value 2');
749
635
  });
636
+ it('should use section-scoped answers in summary for dynamic sections', () => {
637
+ const { journey, question } = createJourney(
638
+ {
639
+ answers: {
640
+ // root answers should not be used for a dynamic section summary
641
+ testField1: 'root value 1',
642
+ testField2: 'root value 2',
643
+ myList: [{ id: 'questions', testField1: 'nested value 1', testField2: 'nested value 2' }]
644
+ }
645
+ },
646
+ createMultiFieldInputQuestion(),
647
+ true
648
+ );
649
+
650
+ const result = question.formatAnswerForSummary('questions', journey);
651
+
652
+ assert.deepStrictEqual(result, [
653
+ {
654
+ action: {
655
+ ...action,
656
+ text: 'Change'
657
+ },
658
+ key: 'title',
659
+ value: 'nested value 1<br>nested value 2'
660
+ }
661
+ ]);
662
+ });
750
663
  });
751
664
  describe('formatAnswer', () => {
752
665
  it('should return notStartedText for null', () => {
@@ -38,6 +38,8 @@
38
38
  text: errors[question.fieldName].msg
39
39
  },
40
40
  classes: question.classes,
41
+ prefix: question.prefix,
42
+ suffix: question.suffix,
41
43
  attributes: question.attributes,
42
44
  type: question.type,
43
45
  autocomplete: question.autocomplete
@@ -62,6 +64,8 @@
62
64
  text: errors[question.fieldName].msg
63
65
  },
64
66
  classes: question.classes,
67
+ prefix: question.prefix,
68
+ suffix: question.suffix,
65
69
  attributes: question.attributes,
66
70
  type: question.type,
67
71
  autocomplete: question.autocomplete
@@ -10,6 +10,8 @@ export class SingleLineInputQuestion extends Question {
10
10
  inputAttributes: Record<string, string>;
11
11
  label: string | undefined;
12
12
  classes: string;
13
+ prefix: import("#typedefs/question-props.d.ts").Affix | undefined;
14
+ suffix: import("#typedefs/question-props.d.ts").Affix | undefined;
13
15
  }
14
16
  export default SingleLineInputQuestion;
15
17
  import { Question } from '#question';
@@ -1 +1 @@
1
- {"version":3,"file":"question.d.ts","sourceRoot":"","sources":["question.js"],"names":[],"mappings":"AAEA;;GAEG;AACH;IAIC;;OAEG;IACH,oBAFW,OAAO,+BAA+B,EAAE,6BAA6B,EAW/E;IAfD,qCAAqC;IACrC,iBADW,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CACjB;IAWf,0BAAyB;IAEzB,gBAAmC;CAepC;;yBAnCwB,WAAW"}
1
+ {"version":3,"file":"question.d.ts","sourceRoot":"","sources":["question.js"],"names":[],"mappings":"AAEA;;GAEG;AACH;IAIC;;OAEG;IACH,oBAFW,OAAO,+BAA+B,EAAE,6BAA6B,EAa/E;IAjBD,qCAAqC;IACrC,iBADW,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CACjB;IAWf,0BAAyB;IAEzB,gBAAmC;IACnC,kEAA2B;IAC3B,kEAA2B;CAiB5B;;yBAvCwB,WAAW"}
@@ -19,6 +19,8 @@ export class SingleLineInputQuestion extends Question {
19
19
  this.label = params.label;
20
20
  this.inputAttributes = params.inputAttributes || {};
21
21
  this.classes = params.classes || '';
22
+ this.prefix = params.prefix;
23
+ this.suffix = params.suffix;
22
24
  }
23
25
 
24
26
  /**
@@ -32,6 +34,8 @@ export class SingleLineInputQuestion extends Question {
32
34
  viewModel.question.type = type;
33
35
 
34
36
  viewModel.question.classes = this.classes;
37
+ viewModel.question.prefix = this.prefix;
38
+ viewModel.question.suffix = this.suffix;
35
39
  }
36
40
  }
37
41
 
@@ -11,6 +11,8 @@ describe('./src/dynamic-forms/components/single-line-input/question.js', () => {
11
11
  const HTML = '/path/to/html.njk';
12
12
  const HINT = 'hint';
13
13
  const LABEL = 'A label';
14
+ const PREFIX = { text: '£', classes: 'govuk-!-font-weight-bold' };
15
+ const SUFFIX = { text: 'per year' };
14
16
 
15
17
  const question = new SingleLineInputQuestion({
16
18
  title: TITLE,
@@ -20,6 +22,8 @@ describe('./src/dynamic-forms/components/single-line-input/question.js', () => {
20
22
  html: HTML,
21
23
  hint: HINT,
22
24
  label: LABEL,
25
+ prefix: PREFIX,
26
+ suffix: SUFFIX,
23
27
  autocomplete: FIELDNAME
24
28
  });
25
29
 
@@ -31,6 +35,8 @@ describe('./src/dynamic-forms/components/single-line-input/question.js', () => {
31
35
  assert.strictEqual(question.html, HTML);
32
36
  assert.strictEqual(question.hint, HINT);
33
37
  assert.strictEqual(question.label, LABEL);
38
+ assert.strictEqual(question.prefix, PREFIX);
39
+ assert.strictEqual(question.suffix, SUFFIX);
34
40
  assert.strictEqual(question.autocomplete, FIELDNAME);
35
41
  });
36
42
  });
@@ -1 +1 @@
1
- {"version":3,"file":"question.d.ts","sourceRoot":"","sources":["question.js"],"names":[],"mappings":"AAGA,+BAAgC,QAAG,CAAC;AACpC,mCAAoC,GAAG,CAAC;AAExC;;GAEG;AACH;IACC;;OAEG;IACH,gLAFW,OAAO,+BAA+B,EAAE,6BAA6B,EAwB/E;IAPA,yFAA0C;IAC1C,0BAAkB;IAClB,qDAAsE;IACtE,iDAA8D;IAC9D,uCAA0C;IAC1C,gCAA8B;IAC9B,2CAAkD;IAkBnD,+NAOC;IAED,yCAEC;IAYD;;OAEG;IACH,iJAuBC;CACD;;yBAtGwB,WAAW"}
1
+ {"version":3,"file":"question.d.ts","sourceRoot":"","sources":["question.js"],"names":[],"mappings":"AAGA,+BAAgC,QAAG,CAAC;AACpC,mCAAoC,GAAG,CAAC;AAExC;;GAEG;AACH;IACC;;OAEG;IACH,gLAFW,OAAO,+BAA+B,EAAE,6BAA6B,EAwB/E;IAPA,yFAA0C;IAC1C,0BAAkB;IAClB,qDAAsE;IACtE,iDAA8D;IAC9D,uCAA0C;IAC1C,gCAA8B;IAC9B,2CAAkD;IAkBnD,+NAOC;IAED,yCAEC;IAYD;;OAEG;IACH,iJAyBC;CACD;;yBAxGwB,WAAW"}
@@ -77,7 +77,9 @@ export class TextEntryRedactQuestion extends Question {
77
77
  * returns the formatted answers values to be used to build task list elements
78
78
  */
79
79
  formatAnswerForSummary(sectionSegment, journey, answer, capitals = true) {
80
- const redacted = journey.response.answers[this.fieldName + 'Redacted'];
80
+ // get the response/answers for the section we're in - which might be a dynamic section
81
+ const response = journey.responseForSection(sectionSegment);
82
+ const redacted = response.answers[this.fieldName + 'Redacted'];
81
83
  let toShow;
82
84
  if (this.onlyShowRedactedValueForSummary) {
83
85
  toShow = redacted;
@@ -211,6 +211,9 @@ describe('./src/dynamic-forms/components/text-entry-redact/question.js', () => {
211
211
  getCurrentQuestionUrl: () => {
212
212
  return '/redacted-comment';
213
213
  },
214
+ responseForSection() {
215
+ return this.response;
216
+ },
214
217
  response: {
215
218
  answers: {}
216
219
  }
@@ -248,6 +251,9 @@ describe('./src/dynamic-forms/components/text-entry-redact/question.js', () => {
248
251
  getCurrentQuestionUrl: () => {
249
252
  return '/redacted-comment';
250
253
  },
254
+ responseForSection() {
255
+ return this.response;
256
+ },
251
257
  response: {
252
258
  answers: {}
253
259
  }
@@ -284,6 +290,9 @@ describe('./src/dynamic-forms/components/text-entry-redact/question.js', () => {
284
290
  getCurrentQuestionUrl: () => {
285
291
  return '/redacted-comment';
286
292
  },
293
+ responseForSection() {
294
+ return this.response;
295
+ },
287
296
  response: {
288
297
  answers: {}
289
298
  }