@planning-inspectorate/dynamic-forms 3.8.3 → 3.10.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 (59) hide show
  1. package/package.json +1 -1
  2. package/src/components/address/index.njk +1 -6
  3. package/src/components/boolean/index.njk +1 -6
  4. package/src/components/boolean/question.js +5 -2
  5. package/src/components/checkbox/index.njk +1 -6
  6. package/src/components/checkbox/question.js +4 -2
  7. package/src/components/date/index.njk +1 -21
  8. package/src/components/date-period/index.njk +1 -6
  9. package/src/components/date-time/index.njk +1 -6
  10. package/src/components/identifier/index.njk +1 -6
  11. package/src/components/manage-list/index.njk +1 -6
  12. package/src/components/multi-field-input/index.njk +1 -7
  13. package/src/components/number-entry/index.njk +1 -6
  14. package/src/components/radio/index.njk +1 -21
  15. package/src/components/select/index.njk +23 -40
  16. package/src/components/select/question.js +5 -0
  17. package/src/components/select/question.test.js +77 -1
  18. package/src/components/single-line-input/index.njk +1 -6
  19. package/src/components/task-list/index.njk +0 -1
  20. package/src/components/text-entry/index.njk +1 -6
  21. package/src/components/text-entry-redact/index.njk +1 -5
  22. package/src/components/unit-option-entry/index.njk +1 -6
  23. package/src/components/utils/actions.njk +35 -0
  24. package/src/questions/question-props.d.ts +1 -0
  25. package/src/questions/question-types.d.ts +26 -1
  26. package/test/secondary-actions.test.js +253 -0
  27. package/test/snapshots/add-insurance.html +2 -1
  28. package/test/snapshots/companions.html +1 -1
  29. package/test/snapshots/contact-email.html +2 -1
  30. package/test/snapshots/departure-date.html +2 -2
  31. package/test/snapshots/holiday-activities.html +2 -1
  32. package/test/snapshots/holiday-arrival.html +2 -1
  33. package/test/snapshots/holiday-description.html +2 -1
  34. package/test/snapshots/holiday-destination.html +2 -2
  35. package/test/snapshots/holiday-period.html +2 -1
  36. package/test/snapshots/holiday-snack.html +2 -1
  37. package/test/snapshots/hotel-address.html +2 -1
  38. package/test/snapshots/luggage-weight-units.html +2 -1
  39. package/test/snapshots/manage-list-render-questions.html +2 -1
  40. package/test/snapshots/manage-list-render.html +2 -1
  41. package/test/snapshots/nights.html +3 -2
  42. package/test/snapshots/secondary-actions-radio-plain.html +46 -0
  43. package/test/snapshots/secondary-actions-radio.html +53 -0
  44. package/test/snapshots/secret-wish.html +2 -1
  45. package/test/snapshots/travel-class.html +19 -19
  46. package/test/snapshots/travel-companions.html +2 -1
  47. package/test/snapshots/travel-companions_travel-companion-email.html +2 -1
  48. package/test/snapshots/travel-companions_travel-companion-name.html +2 -1
  49. package/test/snapshots/travel-insurance-type.html +2 -2
  50. package/types/src/components/boolean/question.d.ts +3 -1
  51. package/types/src/components/boolean/question.d.ts.map +1 -1
  52. package/types/src/components/checkbox/question.d.ts +3 -1
  53. package/types/src/components/checkbox/question.d.ts.map +1 -1
  54. package/types/src/components/select/question.d.ts +4 -1
  55. package/types/src/components/select/question.d.ts.map +1 -1
  56. package/types/src/questions/question-props.d.ts +1 -0
  57. package/types/src/questions/question-types.d.ts +26 -1
  58. package/types/src/questions/question.d.ts +5 -1
  59. package/types/src/questions/question.d.ts.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planning-inspectorate/dynamic-forms",
3
- "version": "3.8.3",
3
+ "version": "3.10.0",
4
4
  "description": "This package is for building GDS forms using a configuration-based approach.",
5
5
  "main": "./src/index.js",
6
6
  "type": "module",
@@ -2,7 +2,6 @@
2
2
 
3
3
  {% from "govuk/components/input/macro.njk" import govukInput %}
4
4
  {% from "govuk/components/fieldset/macro.njk" import govukFieldset %}
5
- {% from "govuk/components/button/macro.njk" import govukButton %}
6
5
 
7
6
  {% set addressLine1= question.fieldName + "_addressLine1" %}
8
7
  {% set addressLine2= question.fieldName + "_addressLine2" %}
@@ -97,11 +96,7 @@
97
96
  text: errors[postcode].msg
98
97
  }
99
98
  }) }}
100
- {{ govukButton({
101
- text: continueButtonText,
102
- type: "submit",
103
- attributes: { "data-cy":"button-save-and-continue"}
104
- }) }}
99
+ {% include "components/utils/actions.njk" %}
105
100
  {% endcall %}
106
101
  </form>
107
102
  </div>
@@ -2,7 +2,6 @@
2
2
 
3
3
  {% from "govuk/components/radios/macro.njk" import govukRadios %}
4
4
  {% from "govuk/components/checkboxes/macro.njk" import govukCheckboxes %}
5
- {% from "govuk/components/button/macro.njk" import govukButton %}
6
5
 
7
6
  {% if question.html %}
8
7
  {% set htmlHint %}
@@ -55,11 +54,7 @@
55
54
  items: question.options
56
55
  }) }}
57
56
  {% endif %}
58
- {{ govukButton({
59
- text: continueButtonText,
60
- type: "submit",
61
- attributes: { "data-cy":"button-save-and-continue"}
62
- }) }}
57
+ {% include "components/utils/actions.njk" %}
63
58
  </form>
64
59
  </div>
65
60
  </div>
@@ -46,6 +46,7 @@ export default class BooleanQuestion extends RadioQuestion {
46
46
  * @param {Array.<import('../../questions/options-question.js').Option>} [params.options]
47
47
  * @param {Array.<import('#base-validator').BaseValidator>} [params.validators]
48
48
  * @param {boolean} [params.editable]
49
+ * @param {import('#question-types').QuestionParameters['viewData']} [params.viewData]
49
50
  */
50
51
  constructor({
51
52
  title,
@@ -59,7 +60,8 @@ export default class BooleanQuestion extends RadioQuestion {
59
60
  validators,
60
61
  interfaceType = 'radio',
61
62
  options,
62
- editable
63
+ editable,
64
+ viewData
63
65
  }) {
64
66
  let defaultOptions = options || [
65
67
  {
@@ -90,7 +92,8 @@ export default class BooleanQuestion extends RadioQuestion {
90
92
  options: defaultOptions,
91
93
  validators,
92
94
  html,
93
- editable
95
+ editable,
96
+ viewData
94
97
  });
95
98
 
96
99
  this.interfaceType = interfaceType;
@@ -1,7 +1,6 @@
1
1
  {% extends layoutTemplate %}
2
2
 
3
3
  {% from "govuk/components/checkboxes/macro.njk" import govukCheckboxes %}
4
- {% from "govuk/components/button/macro.njk" import govukButton %}
5
4
 
6
5
  {% block dynQuestionContent %}
7
6
  <div class="govuk-grid-row">
@@ -27,11 +26,7 @@
27
26
  },
28
27
  items: question.options
29
28
  }) }}
30
- {{ govukButton({
31
- text: continueButtonText,
32
- type: "submit",
33
- attributes: { "data-cy":"button-save-and-continue"}
34
- }) }}
29
+ {% include "components/utils/actions.njk" %}
35
30
  </form>
36
31
  </div>
37
32
  </div>
@@ -21,8 +21,9 @@ export default class CheckboxQuestion extends OptionsQuestion {
21
21
  * @param {string} [params.description]
22
22
  * @param {Array.<import('../../questions/options-question.js').Option>} params.options
23
23
  * @param {Array.<import('#base-validator').BaseValidator>} [params.validators]
24
+ * @param {import('#question-types').QuestionParameters['viewData']} [params.viewData]
24
25
  */
25
- constructor({ title, question, fieldName, url, pageTitle, description, options, validators }) {
26
+ constructor({ title, question, fieldName, url, pageTitle, description, options, validators, viewData }) {
26
27
  super({
27
28
  title,
28
29
  question,
@@ -32,7 +33,8 @@ export default class CheckboxQuestion extends OptionsQuestion {
32
33
  pageTitle,
33
34
  description,
34
35
  options,
35
- validators
36
+ validators,
37
+ viewData
36
38
  });
37
39
 
38
40
  this.optionJoinString = defaultOptionJoinString;
@@ -1,7 +1,6 @@
1
1
  {% extends layoutTemplate %}
2
2
 
3
3
  {% from "govuk/components/date-input/macro.njk" import govukDateInput %}
4
- {% from "govuk/components/button/macro.njk" import govukButton %}
5
4
 
6
5
  {% set day= question.fieldName + "_day" %}
7
6
  {% set month= question.fieldName + "_month" %}
@@ -62,26 +61,7 @@
62
61
  {{ beforeSubmitButton }}
63
62
  {% endif %}
64
63
 
65
- {{ govukButton({
66
- text: continueButtonText,
67
- type: "submit",
68
- attributes: { "data-cy":"button-save-and-continue"}
69
- }) }}
70
- {% if extraActionButtons|length %}
71
- {% for extraActionButton in extraActionButtons %}
72
- {{ govukButton({
73
- text: extraActionButton.text,
74
- type: extraActionButton.type,
75
- href: extraActionButton.href,
76
- attributes: {
77
- "formaction": extraActionButton.formaction or "",
78
- "data-cy": "button-" + extraActionButton.text|lower|replace(" ", "-"),
79
- "name": extraActionButton.text|lower|replace(" ", "-")
80
- },
81
- classes: extraActionButton.classes or "govuk-button--secondary"
82
- }) }}
83
- {% endfor %}
84
- {% endif %}
64
+ {%- include "components/utils/actions.njk" %}
85
65
  </form>
86
66
  </div>
87
67
  </div>
@@ -1,7 +1,6 @@
1
1
  {% extends layoutTemplate %}
2
2
 
3
3
  {% from "govuk/components/date-input/macro.njk" import govukDateInput %}
4
- {% from "govuk/components/button/macro.njk" import govukButton %}
5
4
  {% from "govuk/components/fieldset/macro.njk" import govukFieldset %}
6
5
 
7
6
  {% set startFieldName = question.fieldName + "_start" %}
@@ -117,11 +116,7 @@
117
116
  ]
118
117
  }) }}
119
118
 
120
- {{ govukButton({
121
- text: continueButtonText,
122
- type: "submit",
123
- attributes: { "data-cy":"button-save-and-continue"}
124
- }) }}
119
+ {% include "components/utils/actions.njk" %}
125
120
  </form>
126
121
  </div>
127
122
  </div>
@@ -1,6 +1,5 @@
1
1
  {% extends layoutTemplate %}
2
2
 
3
- {% from "govuk/components/button/macro.njk" import govukButton %}
4
3
  {% from "govuk/components/date-input/macro.njk" import govukDateInput %}
5
4
  {% from "govuk/components/input/macro.njk" import govukInput %}
6
5
  {% from "govuk/components/select/macro.njk" import govukSelect %}
@@ -117,11 +116,7 @@
117
116
  </fieldset>
118
117
  </div>
119
118
 
120
- {{ govukButton({
121
- text: continueButtonText,
122
- type: "submit",
123
- attributes: { "data-cy":"button-save-and-continue"}
124
- }) }}
119
+ {% include "components/utils/actions.njk" %}
125
120
  </form>
126
121
  </div>
127
122
  </div>
@@ -2,7 +2,6 @@
2
2
 
3
3
  {% from "govuk/components/input/macro.njk" import govukInput %}
4
4
  {% from "govuk/components/label/macro.njk" import govukLabel %}
5
- {% from "govuk/components/button/macro.njk" import govukButton %}
6
5
 
7
6
  {% block dynQuestionContent %}
8
7
  <div class="govuk-grid-row">
@@ -56,11 +55,7 @@
56
55
 
57
56
  {% endif %}
58
57
 
59
- {{ govukButton({
60
- text: continueButtonText,
61
- type: "submit",
62
- attributes: { "data-cy":"button-save-and-continue"}
63
- }) }}
58
+ {% include "components/utils/actions.njk" %}
64
59
  </form>
65
60
  </div>
66
61
  </div>
@@ -1,6 +1,5 @@
1
1
  {% extends layoutTemplate %}
2
2
 
3
- {% from "govuk/components/button/macro.njk" import govukButton %}
4
3
 
5
4
  {% block dynQuestionContent %}
6
5
  <div class="govuk-grid-row">
@@ -50,11 +49,7 @@
50
49
  <a href="{{ util.trimTrailingSlash(originalUrl) }}/{{ question.addAnotherLink }}" class="govuk-link">Add another</a>
51
50
  </p>
52
51
 
53
- {{ govukButton({
54
- text: continueButtonText,
55
- type: "submit",
56
- attributes: { "data-cy":"button-save-and-continue"}
57
- }) }}
52
+ {% include "components/utils/actions.njk" %}
58
53
  </form>
59
54
  </div>
60
55
  </div>
@@ -3,7 +3,6 @@
3
3
  {% from "govuk/components/input/macro.njk" import govukInput %}
4
4
  {% from "govuk/components/label/macro.njk" import govukLabel %}
5
5
  {% from "govuk/components/fieldset/macro.njk" import govukFieldset %}
6
- {% from "govuk/components/button/macro.njk" import govukButton %}
7
6
 
8
7
  {% set inputFields = question.value %}
9
8
 
@@ -63,12 +62,7 @@
63
62
 
64
63
  {% endcall %}
65
64
 
66
- {{ govukButton({
67
- text: continueButtonText,
68
- type: "submit",
69
- attributes: { "data-cy":"button-save-and-continue"}
70
- }) }}
71
-
65
+ {% include "components/utils/actions.njk" %}
72
66
  </form>
73
67
  </div>
74
68
  </div>
@@ -1,7 +1,6 @@
1
1
  {% extends layoutTemplate %}
2
2
 
3
3
  {% from "govuk/components/input/macro.njk" import govukInput %}
4
- {% from "govuk/components/button/macro.njk" import govukButton %}
5
4
 
6
5
  {% block dynQuestionContent %}
7
6
  <div class="govuk-grid-row">
@@ -33,11 +32,7 @@
33
32
  inputmode: 'numeric',
34
33
  spellcheck: false
35
34
  }) }}
36
- {{ govukButton({
37
- text: continueButtonText,
38
- type: "submit",
39
- attributes: { "data-cy":"button-save-and-continue"}
40
- }) }}
35
+ {% include "components/utils/actions.njk" -%}
41
36
  </form>
42
37
  </div>
43
38
  </div>
@@ -1,7 +1,6 @@
1
1
  {% extends layoutTemplate %}
2
2
 
3
3
  {% from "govuk/components/radios/macro.njk" import govukRadios %}
4
- {% from "govuk/components/button/macro.njk" import govukButton %}
5
4
  {% from "govuk/components/fieldset/macro.njk" import govukFieldset %}
6
5
 
7
6
  {% block dynQuestionContent %}
@@ -70,26 +69,7 @@
70
69
 
71
70
  {% endif %}
72
71
 
73
- {{ govukButton({
74
- text: continueButtonText,
75
- type: "submit",
76
- attributes: { "data-cy":"button-save-and-continue"}
77
- }) }}
78
- {% if extraActionButtons|length %}
79
- {% for extraActionButton in extraActionButtons %}
80
- {{ govukButton({
81
- text: extraActionButton.text,
82
- type: extraActionButton.type,
83
- href: extraActionButton.href,
84
- attributes: {
85
- "formaction": extraActionButton.formaction or "",
86
- "data-cy": "button-" + extraActionButton.text|lower|replace(" ", "-"),
87
- "name": extraActionButton.text|lower|replace(" ", "-")
88
- },
89
- classes: extraActionButton.classes or "govuk-button--secondary"
90
- }) }}
91
- {% endfor %}
92
- {% endif %}
72
+ {%- include "components/utils/actions.njk" %}
93
73
  </form>
94
74
  </div>
95
75
  </div>
@@ -1,10 +1,11 @@
1
1
  {% extends layoutTemplate %}
2
2
 
3
3
  {% from "govuk/components/select/macro.njk" import govukSelect %}
4
- {% from "govuk/components/button/macro.njk" import govukButton %}
5
4
 
6
5
  {% block head %}
7
- <link rel="stylesheet" href="/assets/css/accessible-autocomplete.min.css"/>
6
+ {% if not question.disableAccessibleAutocomplete %}
7
+ <link rel="stylesheet" href="/assets/css/accessible-autocomplete.min.css"/>
8
+ {% endif %}
8
9
 
9
10
  {{ super() }}
10
11
  {% endblock %}
@@ -36,47 +37,29 @@
36
37
  items: question.options
37
38
  }) }}
38
39
 
39
- {{ govukButton({
40
- text: continueButtonText,
41
- type: "submit",
42
- attributes: { "data-cy":"button-save-and-continue"}
43
- }) }}
44
-
45
- {% if extraActionButtons|length %}
46
- {% for extraActionButton in extraActionButtons %}
47
- {{ govukButton({
48
- text: extraActionButton.text,
49
- type: extraActionButton.type,
50
- href: extraActionButton.href,
51
- attributes: {
52
- "formaction": extraActionButton.formaction or "",
53
- "data-cy": "button-" + extraActionButton.text|lower|replace(" ", "-"),
54
- "name": extraActionButton.text|lower|replace(" ", "-")
55
- },
56
- classes: extraActionButton.classes or "govuk-button--secondary"
57
- }) }}
58
- {% endfor %}
59
- {% endif %}
60
40
 
41
+ {% include "components/utils/actions.njk" %}
61
42
  </form>
62
43
  </div>
63
44
  </div>
64
- <script src="/assets/js/accessible-autocomplete.min.js"></script>
65
- <script {% if cspNonce %}nonce={{ cspNonce }}{% endif %}>
66
- if (window.accessibleAutocomplete) {
67
- accessibleAutocomplete.enhanceSelectElement({
68
- selectElement: document.querySelector('#{{ question.fieldName }}'),
69
- onConfirm: () => {
70
- let input = document.querySelector('#{{ question.fieldName }}');
71
- let select = document.querySelector('#{{ question.fieldName }}-select');
72
- let options = Array.from(select.options);
73
- if (!input.value || !options.some(option => option.innerText === input.value)) {
74
- select.options.selectedIndex = -1;
75
- } else {
76
- select.options.selectedIndex = options.findIndex(option => option.innerText === input.value);
45
+ {% if not question.disableAccessibleAutocomplete %}
46
+ <script src="/assets/js/accessible-autocomplete.min.js"></script>
47
+ <script {% if cspNonce %}nonce={{ cspNonce }}{% endif %}>
48
+ if (window.accessibleAutocomplete) {
49
+ accessibleAutocomplete.enhanceSelectElement({
50
+ selectElement: document.querySelector('#{{ question.fieldName }}'),
51
+ onConfirm: () => {
52
+ let input = document.querySelector('#{{ question.fieldName }}');
53
+ let select = document.querySelector('#{{ question.fieldName }}-select');
54
+ let options = Array.from(select.options);
55
+ if (!input.value || !options.some(option => option.innerText === input.value)) {
56
+ select.options.selectedIndex = -1;
57
+ } else {
58
+ select.options.selectedIndex = options.findIndex(option => option.innerText === input.value);
59
+ }
77
60
  }
78
- }
79
- })
80
- }
81
- </script>
61
+ })
62
+ }
63
+ </script>
64
+ {% endif %}
82
65
  {% endblock %}
@@ -1,6 +1,7 @@
1
1
  import OptionsQuestion from '../../questions/options-question.js';
2
2
 
3
3
  export default class SelectQuestion extends OptionsQuestion {
4
+ #disableAccessibleAutocomplete;
4
5
  /**
5
6
  * @param {Object} params
6
7
  * @param {string} params.title
@@ -14,6 +15,7 @@ export default class SelectQuestion extends OptionsQuestion {
14
15
  * @param {string} [params.label]
15
16
  * @param {string} [params.html]
16
17
  * @param {string} [params.legend] - optional legend, used instead of h1
18
+ * @param {string} [params.disableAccessibleAutocomplete]
17
19
  * @param {Array.<import('../../questions/options-question.js').Option>} params.options
18
20
  * @param {Object<string, any>} [params.viewData]
19
21
  * @param {Array.<import('#base-validator').BaseValidator>} [params.validators]
@@ -30,6 +32,7 @@ export default class SelectQuestion extends OptionsQuestion {
30
32
  label,
31
33
  html,
32
34
  legend,
35
+ disableAccessibleAutocomplete,
33
36
  options,
34
37
  validators,
35
38
  viewData
@@ -51,6 +54,7 @@ export default class SelectQuestion extends OptionsQuestion {
51
54
  this.html = html;
52
55
  this.label = label;
53
56
  this.legend = legend;
57
+ this.#disableAccessibleAutocomplete = disableAccessibleAutocomplete;
54
58
  }
55
59
 
56
60
  /**
@@ -59,6 +63,7 @@ export default class SelectQuestion extends OptionsQuestion {
59
63
  addCustomDataToViewModel(viewModel) {
60
64
  viewModel.question.label = this.label;
61
65
  viewModel.question.legend = this.legend;
66
+ viewModel.question.disableAccessibleAutocomplete = this.#disableAccessibleAutocomplete;
62
67
  }
63
68
 
64
69
  /**
@@ -1,8 +1,9 @@
1
- import { describe, it } from 'node:test';
1
+ import { describe, it, mock } from 'node:test';
2
2
  import assert from 'node:assert';
3
3
  import ValidOptionValidator from '../../validator/valid-option-validator.js';
4
4
  import SelectQuestion from './question.js';
5
5
  import nunjucks from 'nunjucks';
6
+ import { configureNunjucksTestEnv } from '#test/utils/nunjucks.js';
6
7
 
7
8
  const TITLE = 'Select question';
8
9
  const QUESTION = 'A select question';
@@ -94,6 +95,81 @@ describe('./src/dynamic-forms/components/select/question.js', () => {
94
95
  assert.strictEqual(preppedQuestion.question.label, LABEL);
95
96
  });
96
97
 
98
+ it('should pass in disableAccessibleAutocomplete property to view', (ctx) => {
99
+ nunjucks.render = ctx.mock.fn();
100
+ nunjucks.render.mock.mockImplementation(() => {});
101
+
102
+ const selectQuestion = new SelectQuestion({
103
+ title: TITLE,
104
+ question: QUESTION,
105
+ description: DESCRIPTION,
106
+ fieldName: FIELDNAME,
107
+ html: HTML,
108
+ label: LABEL,
109
+ options: OPTIONS,
110
+ disableAccessibleAutocomplete: true
111
+ });
112
+
113
+ const customViewData = { hello: 'hi' };
114
+
115
+ const preppedQuestion = selectQuestion.prepQuestionForRendering(SECTION, JOURNEY, customViewData);
116
+
117
+ assert.strictEqual(preppedQuestion.question.disableAccessibleAutocomplete, true);
118
+ });
119
+
120
+ it('should include accessible autocomplete by default', async () => {
121
+ const selectQuestion = new SelectQuestion({
122
+ title: TITLE,
123
+ question: QUESTION,
124
+ description: DESCRIPTION,
125
+ fieldName: FIELDNAME,
126
+ html: HTML,
127
+ label: LABEL,
128
+ options: OPTIONS
129
+ });
130
+ const viewModel = selectQuestion.prepQuestionForRendering(SECTION, JOURNEY, {
131
+ layoutTemplate: 'views/layout-journey.njk'
132
+ });
133
+
134
+ const nunjucks = configureNunjucksTestEnv();
135
+ const mockRes = {
136
+ render: mock.fn((view, data) => nunjucks.render(view + '.njk', data))
137
+ };
138
+ selectQuestion.renderAction(mockRes, viewModel);
139
+
140
+ assert.strictEqual(mockRes.render.mock.callCount(), 1);
141
+ const view = mockRes.render.mock.calls[0].result;
142
+ assert.ok(view);
143
+ assert.match(view, /accessible-autocomplete\.min\.js/);
144
+ });
145
+
146
+ it('should not include accessible autocomplete if configured', async () => {
147
+ const selectQuestion = new SelectQuestion({
148
+ title: TITLE,
149
+ question: QUESTION,
150
+ description: DESCRIPTION,
151
+ fieldName: FIELDNAME,
152
+ html: HTML,
153
+ label: LABEL,
154
+ options: OPTIONS,
155
+ disableAccessibleAutocomplete: true
156
+ });
157
+ const viewModel = selectQuestion.prepQuestionForRendering(SECTION, JOURNEY, {
158
+ layoutTemplate: 'views/layout-journey.njk'
159
+ });
160
+
161
+ const nunjucks = configureNunjucksTestEnv();
162
+ const mockRes = {
163
+ render: mock.fn((view, data) => nunjucks.render(view + '.njk', data))
164
+ };
165
+ selectQuestion.renderAction(mockRes, viewModel);
166
+
167
+ assert.strictEqual(mockRes.render.mock.callCount(), 1);
168
+ const view = mockRes.render.mock.calls[0].result;
169
+ assert.ok(view);
170
+ assert.doesNotMatch(view, /accessible-autocomplete\.min\.js/);
171
+ });
172
+
97
173
  it('should add selected attribute to chosen option', (ctx) => {
98
174
  nunjucks.render = ctx.mock.fn();
99
175
  nunjucks.render.mock.mockImplementation(() => {});
@@ -2,7 +2,6 @@
2
2
 
3
3
  {% from "govuk/components/input/macro.njk" import govukInput %}
4
4
  {% from "govuk/components/label/macro.njk" import govukLabel %}
5
- {% from "govuk/components/button/macro.njk" import govukButton %}
6
5
 
7
6
  {% block dynQuestionContent %}
8
7
  <div class="govuk-grid-row">
@@ -70,11 +69,7 @@
70
69
 
71
70
  {% endif %}
72
71
 
73
- {{ govukButton({
74
- text: continueButtonText,
75
- type: "submit",
76
- attributes: { "data-cy":"button-save-and-continue"}
77
- }) }}
72
+ {% include "components/utils/actions.njk" %}
78
73
  </form>
79
74
  </div>
80
75
  </div>
@@ -2,7 +2,6 @@
2
2
 
3
3
  {% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
4
4
  {% from "govuk/components/tag/macro.njk" import govukTag %}
5
- {% from "govuk/components/button/macro.njk" import govukButton %}
6
5
  {% from "./task-list-multi-section.njk" import multiTaskList %}
7
6
  {% from "./task-list-single-section.njk" import singleTaskList %}
8
7
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  {% from "govuk/components/textarea/macro.njk" import govukTextarea %}
4
4
  {% from "govuk/components/label/macro.njk" import govukLabel %}
5
- {% from "govuk/components/button/macro.njk" import govukButton %}
6
5
  {% from "govuk/components/checkboxes/macro.njk" import govukCheckboxes %}
7
6
 
8
7
  {% block dynQuestionContent %}
@@ -78,11 +77,7 @@
78
77
  </div>
79
78
  {% endif %}
80
79
 
81
- {{ govukButton({
82
- text: continueButtonText,
83
- type: "submit",
84
- attributes: { "data-cy":"button-save-and-continue"}
85
- }) }}
80
+ {% include "components/utils/actions.njk" %}
86
81
  </form>
87
82
  </div>
88
83
  </div>
@@ -130,11 +130,7 @@
130
130
  }) }}
131
131
  </div>
132
132
 
133
- {{ govukButton({
134
- text: continueButtonText,
135
- type: "submit",
136
- attributes: { "data-cy":"button-save-and-continue" }
137
- }) }}
133
+ {% include "components/utils/actions.njk" %}
138
134
  </form>
139
135
  </div>
140
136
 
@@ -1,7 +1,6 @@
1
1
  {% extends layoutTemplate %}
2
2
 
3
3
  {% from "govuk/components/radios/macro.njk" import govukRadios %}
4
- {% from "govuk/components/button/macro.njk" import govukButton %}
5
4
  {% from "govuk/components/fieldset/macro.njk" import govukFieldset %}
6
5
 
7
6
  {% block dynQuestionContent %}
@@ -37,11 +36,7 @@
37
36
 
38
37
  {% endcall %}
39
38
 
40
- {{ govukButton({
41
- text: continueButtonText,
42
- type: "submit",
43
- attributes: { "data-cy":"button-save-and-continue"}
44
- }) }}
39
+ {% include "components/utils/actions.njk" %}
45
40
  </form>
46
41
  </div>
47
42
  </div>
@@ -0,0 +1,35 @@
1
+ {% from "govuk/components/button/macro.njk" import govukButton -%}
2
+
3
+ {# for backwards compatibility #}
4
+ {%- set secondaryActions = secondaryActions or extraActionButtons -%}
5
+ {%- set hasSecondaryActions = secondaryActions|length > 0 -%}
6
+
7
+ {% if hasSecondaryActions %}<div class="govuk-button-group">
8
+ {% endif %}
9
+ {{ govukButton({
10
+ text: continueButtonText,
11
+ type: "submit",
12
+ attributes: { "data-cy":"button-save-and-continue"}
13
+ }) }}
14
+
15
+ {% if hasSecondaryActions %}
16
+ {% for secondaryAction in secondaryActions %}
17
+ {%- set name = secondaryAction.text|lower|replace(" ", "-") -%}
18
+ {%- if secondaryAction.href -%}
19
+ {# name and formaction aren't valid for <a> tags #}
20
+ {%- set attributes = {"data-cy": "button-" + name} -%}
21
+ {%- elseif secondaryAction.formaction and (not secondaryAction.type or secondaryAction.type == "submit") -%}
22
+ {%- set attributes = {"data-cy": "button-" + name, "name": name, "formaction": secondaryAction.formaction} -%}
23
+ {%- else -%}
24
+ {%- set attributes = {"data-cy": "button-" + name, "name": name} -%}
25
+ {%- endif %}
26
+ {{ govukButton({
27
+ text: secondaryAction.text,
28
+ type: secondaryAction.type,
29
+ href: secondaryAction.href,
30
+ attributes: attributes,
31
+ classes: secondaryAction.classes or "govuk-button--secondary"
32
+ }) }}
33
+ {% endfor %}
34
+ </div>
35
+ {%- endif %}