@ons/design-system 68.0.0 → 68.0.1

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 (199) hide show
  1. package/README.md +6 -0
  2. package/components/access-code/_macro.njk +1 -1
  3. package/components/access-code/_macro.spec.js +2 -10
  4. package/components/access-code/access-code.dom.js +1 -1
  5. package/components/access-code/access-code.spec.js +2 -2
  6. package/components/access-code/example-access-code-error.njk +9 -14
  7. package/components/access-code/example-access-code.njk +3 -5
  8. package/components/accordion/accordion.js +4 -4
  9. package/components/address-input/_macro.spec.js +3 -15
  10. package/components/address-input/autosuggest.address.dom.js +1 -1
  11. package/components/address-input/autosuggest.address.js +3 -2
  12. package/components/address-input/autosuggest.address.setter.js +3 -3
  13. package/components/address-input/autosuggest.address.spec.js +66 -69
  14. package/components/address-output/_macro.spec.js +6 -30
  15. package/components/autosuggest/_autosuggest.scss +1 -1
  16. package/components/autosuggest/autosuggest.dom.js +1 -1
  17. package/components/autosuggest/autosuggest.helpers.js +1 -1
  18. package/components/back-to-top/_back-to-top.scss +34 -0
  19. package/components/back-to-top/_macro.njk +17 -0
  20. package/components/back-to-top/_macro.spec.js +60 -0
  21. package/components/back-to-top/back-to-top.dom.js +12 -0
  22. package/components/back-to-top/back-to-top.js +58 -0
  23. package/components/back-to-top/back-to-top.spec.js +117 -0
  24. package/components/back-to-top/example-back-to-top.njk +37 -0
  25. package/components/back-to-top/example-full-page-back-to-top.njk +192 -0
  26. package/components/browser-banner/_macro.spec.js +4 -12
  27. package/components/button/_macro.njk +6 -6
  28. package/components/button/_macro.spec.js +1 -5
  29. package/components/button/button.js +7 -8
  30. package/components/button/button.spec.js +17 -39
  31. package/components/call-to-action/_macro.spec.js +2 -6
  32. package/components/card/_macro.njk +25 -25
  33. package/components/card/_macro.spec.js +10 -34
  34. package/components/char-check-limit/_macro.njk +1 -1
  35. package/components/char-check-limit/_macro.spec.js +3 -7
  36. package/components/char-check-limit/character-check.spec.js +24 -20
  37. package/components/checkboxes/_checkbox-macro.njk +1 -1
  38. package/components/checkboxes/_checkbox.scss +0 -3
  39. package/components/checkboxes/_macro.spec.js +1 -5
  40. package/components/checkboxes/checkbox-with-autoselect.js +3 -3
  41. package/components/checkboxes/checkbox-with-fieldset.js +2 -2
  42. package/components/checkboxes/checkboxes-with-reveal.js +4 -2
  43. package/components/checkboxes/checkboxes.dom.js +2 -2
  44. package/components/checkboxes/checkboxes.spec.js +13 -13
  45. package/components/content-pagination/_macro.spec.js +2 -2
  46. package/components/cookies-banner/cookies-banner.dom.js +1 -1
  47. package/components/cookies-banner/cookies-banner.js +1 -1
  48. package/components/cookies-banner/cookies-banner.spec.js +7 -7
  49. package/components/date-input/_macro.njk +71 -69
  50. package/components/date-input/_macro.spec.js +20 -5
  51. package/components/date-input/example-date-input-double-field.njk +27 -0
  52. package/components/date-input/example-date-input-single-field.njk +18 -0
  53. package/components/details/details.spec.js +12 -12
  54. package/components/details/example-details-with-warning.njk +5 -7
  55. package/components/document-list/_macro.spec.js +9 -27
  56. package/components/document-list/document-list.scss +1 -1
  57. package/components/document-list/example-document-list-downloads.njk +3 -3
  58. package/components/document-list/example-document-list-search-result-featured.njk +1 -1
  59. package/components/document-list/example-document-list-search-results.njk +3 -3
  60. package/components/download-resources/download-resources.js +54 -54
  61. package/components/download-resources/download-resources.spec.js +3 -1
  62. package/components/duration/_macro.njk +52 -48
  63. package/components/duration/_macro.spec.js +112 -4
  64. package/components/duration/example-duration-error-for-single-field.njk +1 -1
  65. package/components/duration/example-duration-single-field.njk +24 -0
  66. package/components/error/_macro.njk +1 -1
  67. package/components/error/_macro.spec.js +2 -6
  68. package/components/feedback/_macro.njk +1 -1
  69. package/components/feedback/_macro.spec.js +4 -20
  70. package/components/field/_field-group.scss +3 -4
  71. package/components/field/_macro.spec.js +1 -3
  72. package/components/fieldset/_fieldset.scss +1 -2
  73. package/components/fieldset/_macro.spec.js +3 -9
  74. package/components/footer/_footer.scss +8 -0
  75. package/components/footer/_macro.njk +8 -7
  76. package/components/footer/_macro.spec.js +14 -2
  77. package/components/header/_macro.njk +1 -1
  78. package/components/header/_macro.spec.js +1 -1
  79. package/components/helpers/grid.njk +15 -15
  80. package/components/icon/_macro.njk +17 -13
  81. package/components/icon/_macro.spec.js +8 -16
  82. package/components/image/_macro.spec.js +1 -5
  83. package/components/input/_macro.njk +22 -23
  84. package/components/input/_macro.spec.js +1 -1
  85. package/components/input/character-check.dom.js +1 -1
  86. package/components/input/input.spec.js +1 -4
  87. package/components/label/_label.scss +1 -0
  88. package/components/label/_macro.njk +3 -3
  89. package/components/label/_macro.spec.js +4 -13
  90. package/components/list/_macro.spec.js +4 -12
  91. package/components/message/_macro.njk +17 -17
  92. package/components/message/_macro.spec.js +9 -33
  93. package/components/message-list/_macro.spec.js +7 -39
  94. package/components/metadata/_macro.njk +10 -10
  95. package/components/modal/_macro.spec.js +3 -9
  96. package/components/modal/modal.dom.js +1 -1
  97. package/components/modal/modal.spec.js +5 -5
  98. package/components/multiple-input-fields/_macro.njk +49 -0
  99. package/components/mutually-exclusive/_macro.spec.js +2 -10
  100. package/components/mutually-exclusive/mutually-exclusive.checkboxes.spec.js +26 -26
  101. package/components/mutually-exclusive/mutually-exclusive.date.spec.js +128 -14
  102. package/components/mutually-exclusive/mutually-exclusive.dom.js +1 -1
  103. package/components/mutually-exclusive/mutually-exclusive.duration.spec.js +129 -8
  104. package/components/mutually-exclusive/mutually-exclusive.email.spec.js +7 -7
  105. package/components/mutually-exclusive/mutually-exclusive.js +13 -13
  106. package/components/mutually-exclusive/mutually-exclusive.multiple-options.checkboxes.spec.js +29 -29
  107. package/components/mutually-exclusive/mutually-exclusive.number.spec.js +7 -7
  108. package/components/mutually-exclusive/mutually-exclusive.textarea.spec.js +8 -8
  109. package/components/navigation/navigation.spec.js +0 -2
  110. package/components/pagination/_macro.spec.js +11 -53
  111. package/components/panel/_macro.njk +17 -17
  112. package/components/panel/_macro.spec.js +25 -25
  113. package/components/panel/_panel.scss +10 -9
  114. package/components/panel/example-panel-bare.njk +3 -4
  115. package/components/panel/example-panel-with-announcement.njk +6 -10
  116. package/components/panel/example-panel-with-error-summary.njk +2 -2
  117. package/components/panel/example-panel-with-information.njk +0 -1
  118. package/components/panel/example-panel-with-success-message.njk +1 -1
  119. package/components/panel/example-panel-with-warning.njk +2 -3
  120. package/components/password/password.dom.js +1 -1
  121. package/components/phase-banner/_macro.spec.js +3 -9
  122. package/components/question/_macro.njk +1 -1
  123. package/components/question/_macro.spec.js +5 -19
  124. package/components/question/_question.scss +1 -4
  125. package/components/question/example-question-interviewer-note.njk +1 -1
  126. package/components/quote/_macro.spec.js +2 -10
  127. package/components/radios/clear-radios.js +3 -3
  128. package/components/radios/radio-with-fieldset.js +4 -4
  129. package/components/radios/radios.dom.js +1 -1
  130. package/components/radios/radios.spec.js +26 -26
  131. package/components/related-content/_macro.spec.js +2 -4
  132. package/components/related-content/_section-macro.spec.js +2 -8
  133. package/components/relationships/example-relationships-error.njk +16 -18
  134. package/components/relationships/relationships.dom.js +1 -1
  135. package/components/relationships/relationships.js +2 -2
  136. package/components/reply/_macro.spec.js +3 -3
  137. package/components/reply/reply.dom.js +1 -1
  138. package/components/reply/reply.spec.js +3 -3
  139. package/components/section-navigation/_macro.njk +12 -12
  140. package/components/section-navigation/_macro.spec.js +13 -21
  141. package/components/select/_macro.spec.js +6 -6
  142. package/components/share-page/_macro.spec.js +6 -14
  143. package/components/skip-to-content/_macro.spec.js +3 -11
  144. package/components/skip-to-content/skip-to-content.dom.js +1 -1
  145. package/components/skip-to-content/skip-to-content.js +1 -1
  146. package/components/skip-to-content/skip-to-content.spec.js +2 -2
  147. package/components/status/_macro.njk +2 -2
  148. package/components/status/_macro.spec.js +5 -9
  149. package/components/status/example-status-dead.njk +1 -1
  150. package/components/status/example-status-error.njk +1 -1
  151. package/components/status/example-status-pending.njk +1 -1
  152. package/components/status/example-status-small.njk +1 -1
  153. package/components/status/example-status-success.njk +1 -1
  154. package/components/summary/_macro.njk +7 -8
  155. package/components/summary/_macro.spec.js +27 -9
  156. package/components/table/_macro.spec.js +6 -10
  157. package/components/table/scrollable-table.dom.js +1 -1
  158. package/components/table/scrollable-table.js +1 -1
  159. package/components/table/sortable-table.js +4 -4
  160. package/components/table/table.spec.js +21 -17
  161. package/components/table-of-contents/_macro.njk +31 -31
  162. package/components/table-of-contents/_macro.spec.js +3 -11
  163. package/components/table-of-contents/toc.dom.js +1 -1
  164. package/components/table-of-contents/toc.spec.js +36 -32
  165. package/components/tabs/example-tabs-details.njk +1 -1
  166. package/components/tabs/tabs.dom.js +1 -1
  167. package/components/tabs/tabs.js +8 -8
  168. package/components/text-indent/_macro.spec.js +2 -6
  169. package/components/textarea/textarea.dom.js +1 -1
  170. package/components/textarea/textarea.spec.js +8 -8
  171. package/components/timeout-modal/_macro.spec.js +1 -3
  172. package/components/timeout-modal/timeout-modal.dom.js +1 -1
  173. package/components/timeout-modal/timeout-modal.spec.js +10 -10
  174. package/components/timeout-panel/_macro.njk +16 -17
  175. package/components/timeout-panel/_macro.spec.js +1 -1
  176. package/components/timeout-panel/timeout-panel.dom.js +1 -1
  177. package/components/timeout-panel/timeout-panel.spec.js +8 -8
  178. package/components/video/_macro.spec.js +1 -5
  179. package/components/video/video.dom.js +1 -1
  180. package/components/video/video.spec.js +16 -12
  181. package/css/main.css +1 -1
  182. package/favicons/safari-pinned-tab.svg +23 -23
  183. package/js/analytics.js +15 -14
  184. package/js/cookies-settings.dom.js +1 -1
  185. package/js/cookies-settings.spec.js +19 -19
  186. package/js/domready.js +1 -1
  187. package/js/fetch.js +1 -1
  188. package/js/inpagelink.js +3 -3
  189. package/js/main.js +1 -0
  190. package/js/print-button.js +1 -1
  191. package/js/timeout.js +1 -1
  192. package/package.json +2 -1
  193. package/scripts/main.es5.js +1 -1
  194. package/scripts/main.js +1 -1
  195. package/scss/base/_typography.scss +8 -2
  196. package/scss/main.scss +1 -0
  197. package/scss/overrides/hcm.scss +8 -1
  198. package/scss/vars/_colors.scss +2 -1
  199. package/components/date-field-input/_macro.njk +0 -86
@@ -31,7 +31,35 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_DATE_PARAMS = {
31
31
  deselectExclusiveOptionAdjective: 'deselected',
32
32
  exclusiveOptions: [
33
33
  {
34
- id: 'date-exclusive-exclusive-option',
34
+ id: 'date-exclusive-option',
35
+ name: 'no-paid-job',
36
+ value: 'no-paid-job',
37
+ label: {
38
+ text: 'I have never had a paid job',
39
+ },
40
+ },
41
+ ],
42
+ },
43
+ };
44
+
45
+ const EXAMPLE_MUTUALLY_EXCLUSIVE_DATE_SINGLE_PARAMS = {
46
+ id: 'date-mutually-exclusive',
47
+ legendOrLabel: 'What year was your last MOT?',
48
+ description: 'For example, 2018',
49
+ year: {
50
+ label: {
51
+ text: 'Year',
52
+ },
53
+ name: 'year-exclusive',
54
+ },
55
+ mutuallyExclusive: {
56
+ or: 'Or',
57
+ deselectMessage: 'Selecting this will clear the date if one has been inputted',
58
+ deselectGroupAdjective: 'cleared',
59
+ deselectExclusiveOptionAdjective: 'deselected',
60
+ exclusiveOptions: [
61
+ {
62
+ id: 'date-exclusive-option',
35
63
  name: 'no-paid-job',
36
64
  value: 'no-paid-job',
37
65
  label: {
@@ -57,27 +85,27 @@ describe('script: mutually-exclusive', () => {
57
85
 
58
86
  describe('when the user clicks the mutually exclusive option', () => {
59
87
  beforeEach(async () => {
60
- await page.click('#date-exclusive-exclusive-option');
88
+ await page.click('#date-exclusive-option');
61
89
  });
62
90
 
63
91
  it('then the mutually exclusive option should be checked', async () => {
64
- const isChecked = await page.$eval('#date-exclusive-exclusive-option', node => node.checked);
92
+ const isChecked = await page.$eval('#date-exclusive-option', (node) => node.checked);
65
93
  expect(isChecked).toBe(true);
66
94
  });
67
95
 
68
96
  it('then the date input should be cleared', async () => {
69
- const dayValue = await page.$eval('#date-mutually-exclusive-day', node => node.value);
97
+ const dayValue = await page.$eval('#date-mutually-exclusive-day', (node) => node.value);
70
98
  expect(dayValue).toBe('');
71
- const monthValue = await page.$eval('#date-mutually-exclusive-month', node => node.value);
99
+ const monthValue = await page.$eval('#date-mutually-exclusive-month', (node) => node.value);
72
100
  expect(monthValue).toBe('');
73
- const yearValue = await page.$eval('#date-mutually-exclusive-year', node => node.value);
101
+ const yearValue = await page.$eval('#date-mutually-exclusive-year', (node) => node.value);
74
102
  expect(yearValue).toBe('');
75
103
  });
76
104
 
77
105
  it('then the aria alert should tell the user that the date input has been cleared', async () => {
78
106
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
79
107
 
80
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
108
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
81
109
  expect(alertText).toBe('Day cleared. Month cleared. Year cleared.');
82
110
  });
83
111
  });
@@ -85,7 +113,7 @@ describe('script: mutually-exclusive', () => {
85
113
 
86
114
  describe('Given the user has checked the mutually exclusive exclusive option', () => {
87
115
  beforeEach(async () => {
88
- await page.click('#date-exclusive-exclusive-option');
116
+ await page.click('#date-exclusive-option');
89
117
  });
90
118
 
91
119
  describe('when the user populates the dateInput', () => {
@@ -95,15 +123,15 @@ describe('script: mutually-exclusive', () => {
95
123
  await page.type('#date-mutually-exclusive-year', '2018');
96
124
  });
97
125
 
98
- it('then the mutually exclusive option should be checked', async () => {
99
- const isChecked = await page.$eval('#date-exclusive-exclusive-option', node => node.checked);
126
+ it('then the mutually exclusive option should be unchecked', async () => {
127
+ const isChecked = await page.$eval('#date-exclusive-option', (node) => node.checked);
100
128
  expect(isChecked).toBe(false);
101
129
  });
102
130
 
103
131
  it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => {
104
132
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
105
133
 
106
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
134
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
107
135
  expect(alertText).toBe('I have never had a paid job deselected.');
108
136
  });
109
137
  });
@@ -120,20 +148,106 @@ describe('script: mutually-exclusive', () => {
120
148
  it('then the aria alert shouldnt say anything', async () => {
121
149
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
122
150
 
123
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
151
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
152
+ expect(alertText).toBe('');
153
+ });
154
+ });
155
+
156
+ describe('when the user clicks the mutually exclusive option', () => {
157
+ beforeEach(async () => {
158
+ await page.click('#date-exclusive-option');
159
+ });
160
+
161
+ it('then the aria alert shouldnt say anything', async () => {
162
+ await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
163
+
164
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
165
+ expect(alertText).toBe('');
166
+ });
167
+ });
168
+ });
169
+ });
170
+ describe('date-year', () => {
171
+ beforeEach(async () => {
172
+ await setTestPage('/test', renderComponent('date-input', EXAMPLE_MUTUALLY_EXCLUSIVE_DATE_SINGLE_PARAMS));
173
+ });
174
+
175
+ describe('Given the user populated the date input', () => {
176
+ beforeEach(async () => {
177
+ await page.type('#date-mutually-exclusive-year', '2018');
178
+ });
179
+
180
+ describe('when the user clicks the mutually exclusive option', () => {
181
+ beforeEach(async () => {
182
+ await page.click('#date-exclusive-option');
183
+ });
184
+
185
+ it('then the mutually exclusive option should be checked', async () => {
186
+ const isChecked = await page.$eval('#date-exclusive-option', (node) => node.checked);
187
+ expect(isChecked).toBe(true);
188
+ });
189
+
190
+ it('then the date input should be cleared', async () => {
191
+ const yearValue = await page.$eval('#date-mutually-exclusive-year', (node) => node.value);
192
+ expect(yearValue).toBe('');
193
+ });
194
+
195
+ it('then the aria alert should tell the user that the date input has been cleared', async () => {
196
+ await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
197
+
198
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
199
+ expect(alertText).toBe('What year was your last MOT? cleared.');
200
+ });
201
+ });
202
+ });
203
+
204
+ describe('Given the user has checked the mutually exclusive exclusive option', () => {
205
+ beforeEach(async () => {
206
+ await page.click('#date-exclusive-option');
207
+ });
208
+
209
+ describe('when the user populates the dateInput', () => {
210
+ beforeEach(async () => {
211
+ await page.type('#date-mutually-exclusive-year', '2018');
212
+ });
213
+
214
+ it('then the mutually exclusive option should be unchecked', async () => {
215
+ const isChecked = await page.$eval('#date-exclusive-option', (node) => node.checked);
216
+ expect(isChecked).toBe(false);
217
+ });
218
+
219
+ it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => {
220
+ await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
221
+
222
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
223
+ expect(alertText).toBe('I have never had a paid job deselected.');
224
+ });
225
+ });
226
+ });
227
+
228
+ describe('Given the user has not populated the date input or checked the exclusive option', () => {
229
+ describe('when the user populates the date input', () => {
230
+ beforeEach(async () => {
231
+ await page.type('#date-mutually-exclusive-year', '2018');
232
+ });
233
+
234
+ it('then the aria alert shouldnt say anything', async () => {
235
+ await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
236
+
237
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
124
238
  expect(alertText).toBe('');
125
239
  });
126
240
  });
127
241
 
128
242
  describe('when the user clicks the mutually exclusive option', () => {
129
243
  beforeEach(async () => {
130
- await page.click('#date-exclusive-exclusive-option');
244
+ await page.click('#date-exclusive-option');
131
245
  });
132
246
 
133
247
  it('then the aria alert shouldnt say anything', async () => {
134
248
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
135
249
 
136
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
250
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
137
251
  expect(alertText).toBe('');
138
252
  });
139
253
  });
@@ -8,7 +8,7 @@ async function mutuallyExclusiveInputs() {
8
8
  if (exclusiveWrapperElements.length) {
9
9
  const MutuallyExclusive = (await import('./mutually-exclusive')).default;
10
10
 
11
- exclusiveWrapperElements.forEach(element => new MutuallyExclusive(element));
11
+ exclusiveWrapperElements.forEach((element) => new MutuallyExclusive(element));
12
12
  }
13
13
  }
14
14
 
@@ -48,6 +48,40 @@ const EXAMPLE_MUTUALLY_EXCLUSIVE_DURATION_PARAMS = {
48
48
  },
49
49
  };
50
50
 
51
+ const EXAMPLE_MUTUALLY_EXCLUSIVE_DURATION_SINGLE_PARAMS = {
52
+ id: 'address-duration',
53
+ legendOrLabel: 'How long have you lived at this address?',
54
+ description: 'If you have lived at this address for less than a year then enter 0 into the year input.',
55
+ field1: {
56
+ id: 'address-duration-years',
57
+ name: 'address-duration-years',
58
+ suffix: {
59
+ text: 'Years',
60
+ id: 'address-duration-years-suffix',
61
+ },
62
+ attributes: {
63
+ min: 0,
64
+ max: 100,
65
+ },
66
+ },
67
+ mutuallyExclusive: {
68
+ or: 'Or',
69
+ deselectMessage: 'Selecting this will clear the date if one has been inputted',
70
+ deselectGroupAdjective: 'cleared',
71
+ deselectExclusiveOptionAdjective: 'deselected',
72
+ exclusiveOptions: [
73
+ {
74
+ id: 'duration-exclusive-option',
75
+ name: 'no-duration',
76
+ value: 'no-duration',
77
+ label: {
78
+ text: 'I have not moved in to this address yet',
79
+ },
80
+ },
81
+ ],
82
+ },
83
+ };
84
+
51
85
  describe('script: mutually-exclusive', () => {
52
86
  describe('duration', () => {
53
87
  beforeEach(async () => {
@@ -66,21 +100,21 @@ describe('script: mutually-exclusive', () => {
66
100
  });
67
101
 
68
102
  it('then the mutually exclusive option should be checked', async () => {
69
- const isChecked = await page.$eval('#duration-exclusive-option', node => node.checked);
103
+ const isChecked = await page.$eval('#duration-exclusive-option', (node) => node.checked);
70
104
  expect(isChecked).toBe(true);
71
105
  });
72
106
 
73
107
  it('then the inputs should be cleared', async () => {
74
- const yearsValue = await page.$eval('#address-duration-years', node => node.value);
108
+ const yearsValue = await page.$eval('#address-duration-years', (node) => node.value);
75
109
  expect(yearsValue).toBe('');
76
- const monthsValue = await page.$eval('#address-duration-months', node => node.value);
110
+ const monthsValue = await page.$eval('#address-duration-months', (node) => node.value);
77
111
  expect(monthsValue).toBe('');
78
112
  });
79
113
 
80
114
  it('then the aria alert should tell the user that the inputs have been cleared', async () => {
81
115
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
82
116
 
83
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
117
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
84
118
  expect(alertText).toBe('Years cleared. Months cleared.');
85
119
  });
86
120
  });
@@ -98,14 +132,14 @@ describe('script: mutually-exclusive', () => {
98
132
  });
99
133
 
100
134
  it('then the exclusive option should be unchecked', async () => {
101
- const isChecked = await page.$eval('#duration-exclusive-option', node => node.checked);
135
+ const isChecked = await page.$eval('#duration-exclusive-option', (node) => node.checked);
102
136
  expect(isChecked).toBe(false);
103
137
  });
104
138
 
105
139
  it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => {
106
140
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
107
141
 
108
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
142
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
109
143
  expect(alertText).toBe('I have not moved in to this address yet deselected.');
110
144
  });
111
145
  });
@@ -121,7 +155,94 @@ describe('script: mutually-exclusive', () => {
121
155
  it('then the aria alert shouldnt say anything', async () => {
122
156
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
123
157
 
124
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
158
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
159
+ expect(alertText).toBe('');
160
+ });
161
+ });
162
+
163
+ describe('when the user clicks the mutually exclusive option', () => {
164
+ beforeEach(async () => {
165
+ await page.click('#duration-exclusive-option');
166
+ });
167
+
168
+ it('then the aria alert shouldnt say anything', async () => {
169
+ await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
170
+
171
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
172
+ expect(alertText).toBe('');
173
+ });
174
+ });
175
+ });
176
+ });
177
+
178
+ describe('duration-single', () => {
179
+ beforeEach(async () => {
180
+ await setTestPage('/test', renderComponent('duration', EXAMPLE_MUTUALLY_EXCLUSIVE_DURATION_SINGLE_PARAMS));
181
+ });
182
+
183
+ describe('Given the user populated the duration', () => {
184
+ beforeEach(async () => {
185
+ await page.type('#address-duration-years', '2');
186
+ });
187
+
188
+ describe('when the user clicks the mutually exclusive option', () => {
189
+ beforeEach(async () => {
190
+ await page.click('#duration-exclusive-option');
191
+ });
192
+
193
+ it('then the mutually exclusive option should be checked', async () => {
194
+ const isChecked = await page.$eval('#duration-exclusive-option', (node) => node.checked);
195
+ expect(isChecked).toBe(true);
196
+ });
197
+
198
+ it('then the inputs should be cleared', async () => {
199
+ const yearsValue = await page.$eval('#address-duration-years', (node) => node.value);
200
+ expect(yearsValue).toBe('');
201
+ });
202
+
203
+ it('then the aria alert should tell the user that the inputs have been cleared', async () => {
204
+ await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
205
+
206
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
207
+ expect(alertText).toBe('How long have you lived at this address? cleared.');
208
+ });
209
+ });
210
+ });
211
+
212
+ describe('Given the user has checked the mutually exclusive exclusive option', () => {
213
+ beforeEach(async () => {
214
+ await page.click('#duration-exclusive-option');
215
+ });
216
+
217
+ describe('when the user populates the duration fields', () => {
218
+ beforeEach(async () => {
219
+ await page.type('#address-duration-years', '2');
220
+ });
221
+
222
+ it('then the exclusive option should be unchecked', async () => {
223
+ const isChecked = await page.$eval('#duration-exclusive-option', (node) => node.checked);
224
+ expect(isChecked).toBe(false);
225
+ });
226
+
227
+ it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => {
228
+ await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
229
+
230
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
231
+ expect(alertText).toBe('I have not moved in to this address yet deselected.');
232
+ });
233
+ });
234
+ });
235
+
236
+ describe('Given the user has not populated the duration inputs or checked the exclusive option', () => {
237
+ describe('when the user populates the duration inputs', () => {
238
+ beforeEach(async () => {
239
+ await page.type('#address-duration-years', '2');
240
+ });
241
+
242
+ it('then the aria alert shouldnt say anything', async () => {
243
+ await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
244
+
245
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
125
246
  expect(alertText).toBe('');
126
247
  });
127
248
  });
@@ -134,7 +255,7 @@ describe('script: mutually-exclusive', () => {
134
255
  it('then the aria alert shouldnt say anything', async () => {
135
256
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
136
257
 
137
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
258
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
138
259
  expect(alertText).toBe('');
139
260
  });
140
261
  });
@@ -44,19 +44,19 @@ describe('script: mutually-exclusive', () => {
44
44
  });
45
45
 
46
46
  it('then the mutually exclusive option should be checked', async () => {
47
- const isChecked = await page.$eval('#email-exclusive-option', node => node.checked);
47
+ const isChecked = await page.$eval('#email-exclusive-option', (node) => node.checked);
48
48
  expect(isChecked).toBe(true);
49
49
  });
50
50
 
51
51
  it('then the email input should be cleared', async () => {
52
- const inputValue = await page.$eval('#email', node => node.value);
52
+ const inputValue = await page.$eval('#email', (node) => node.value);
53
53
  expect(inputValue).toBe('');
54
54
  });
55
55
 
56
56
  it('then the aria alert should tell the user that the email input has been cleared', async () => {
57
57
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
58
58
 
59
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
59
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
60
60
  expect(alertText).toBe('Enter an email cleared.');
61
61
  });
62
62
  });
@@ -73,14 +73,14 @@ describe('script: mutually-exclusive', () => {
73
73
  });
74
74
 
75
75
  it('then the exclusive option should be unchecked', async () => {
76
- const isChecked = await page.$eval('#email-exclusive-option', node => node.checked);
76
+ const isChecked = await page.$eval('#email-exclusive-option', (node) => node.checked);
77
77
  expect(isChecked).toBe(false);
78
78
  });
79
79
 
80
80
  it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => {
81
81
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
82
82
 
83
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
83
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
84
84
  expect(alertText).toBe('I dont want to receive a confirmation email deselected.');
85
85
  });
86
86
  });
@@ -95,7 +95,7 @@ describe('script: mutually-exclusive', () => {
95
95
  it('then the aria alert shouldnt say anything', async () => {
96
96
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
97
97
 
98
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
98
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
99
99
  expect(alertText).toBe('');
100
100
  });
101
101
  });
@@ -108,7 +108,7 @@ describe('script: mutually-exclusive', () => {
108
108
  it('then the aria alert shouldnt say anything', async () => {
109
109
  await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
110
110
 
111
- const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
111
+ const alertText = await page.$eval('.ons-js-exclusive-alert', (node) => node.textContent);
112
112
  expect(alertText).toBe('');
113
113
  });
114
114
  });
@@ -12,7 +12,7 @@ export default class MutuallyExclusive {
12
12
 
13
13
  const groupInputs = [...context.getElementsByClassName(exclusiveGroupItemClass)];
14
14
  this.numberOfGroupInputs = groupInputs.length;
15
- this.groupInputs = groupInputs.map(element => ({
15
+ this.groupInputs = groupInputs.map((element) => ({
16
16
  element,
17
17
  labelText: this.getElementLabelText(element),
18
18
  hasValue: this.inputHasValue(element),
@@ -21,7 +21,7 @@ export default class MutuallyExclusive {
21
21
 
22
22
  const exclusiveElements = [...context.getElementsByClassName(optionClass)];
23
23
  this.numberOfExclusiveElements = exclusiveElements.length;
24
- this.exclusiveElements = exclusiveElements.map(element => ({
24
+ this.exclusiveElements = exclusiveElements.map((element) => ({
25
25
  element,
26
26
  label: context.querySelector(`label[for=${element.id}]`),
27
27
  labelText: this.getElementLabelText(element),
@@ -39,14 +39,14 @@ export default class MutuallyExclusive {
39
39
  }
40
40
 
41
41
  bindEventListeners() {
42
- this.allInputs.forEach(input => {
42
+ this.allInputs.forEach((input) => {
43
43
  const event = ['checkbox', 'radio'].includes(input.element.type) ? 'click' : 'input';
44
44
  input.element.addEventListener(event, () => this.handleValueChange(input));
45
45
  });
46
46
  }
47
47
 
48
48
  handleValueChange(input) {
49
- const previousSelectedValues = this.allInputs.filter(input => input.hasValue).map(input => input.labelText);
49
+ const previousSelectedValues = this.allInputs.filter((input) => input.hasValue).map((input) => input.labelText);
50
50
  let adjective;
51
51
 
52
52
  input.hasValue = this.inputHasValue(input.element);
@@ -57,8 +57,8 @@ export default class MutuallyExclusive {
57
57
  adjective = this.groupAdjective;
58
58
 
59
59
  this.allInputs
60
- .filter(input => !input.exclusive)
61
- .forEach(input => {
60
+ .filter((input) => !input.exclusive)
61
+ .forEach((input) => {
62
62
  input.hasValue = false;
63
63
 
64
64
  if (['checkbox', 'radio'].includes(input.element.type)) {
@@ -70,10 +70,10 @@ export default class MutuallyExclusive {
70
70
  }
71
71
  });
72
72
  } else if (!input.exclusive) {
73
- const inputs = this.allInputs.filter(input => input.exclusive);
73
+ const inputs = this.allInputs.filter((input) => input.exclusive);
74
74
  adjective = this.optionAttrAdjective;
75
75
 
76
- inputs.forEach(input => {
76
+ inputs.forEach((input) => {
77
77
  input.hasValue = false;
78
78
  input.element.checked = false;
79
79
  });
@@ -81,8 +81,8 @@ export default class MutuallyExclusive {
81
81
  this.triggerEvent(input.element, 'change');
82
82
  }
83
83
 
84
- const updatedSelectedValues = this.allInputs.filter(input => input.hasValue).map(input => input.labelText);
85
- const deselectedValues = previousSelectedValues.filter(labelText => !updatedSelectedValues.includes(labelText));
84
+ const updatedSelectedValues = this.allInputs.filter((input) => input.hasValue).map((input) => input.labelText);
85
+ const deselectedValues = previousSelectedValues.filter((labelText) => !updatedSelectedValues.includes(labelText));
86
86
 
87
87
  this.setDeselectMessage();
88
88
 
@@ -113,7 +113,7 @@ export default class MutuallyExclusive {
113
113
  } else if (label.classList.contains(inputLegendClass) && label.querySelector('h1')) {
114
114
  labelText = label.querySelector('h1').innerText;
115
115
  } else {
116
- labelText = [...label.childNodes].filter(node => node.nodeType === 3 && node.textContent.trim())[0].textContent.trim();
116
+ labelText = [...label.childNodes].filter((node) => node.nodeType === 3 && node.textContent.trim())[0].textContent.trim();
117
117
  }
118
118
  }
119
119
 
@@ -129,7 +129,7 @@ export default class MutuallyExclusive {
129
129
  }
130
130
 
131
131
  setAriaLive(deselectedValues, adjective) {
132
- const deselectionMessage = deselectedValues.map(label => `${label} ${adjective}.`).join(' ');
132
+ const deselectionMessage = deselectedValues.map((label) => `${label} ${adjective}.`).join(' ');
133
133
 
134
134
  // Only update aria-live if value changes to prevent typing from clearing the message before it's read
135
135
  if (deselectionMessage) {
@@ -138,7 +138,7 @@ export default class MutuallyExclusive {
138
138
  }
139
139
 
140
140
  setDeselectMessage() {
141
- const groupElementSelected = this.groupInputs.find(input => input.hasValue);
141
+ const groupElementSelected = this.groupInputs.find((input) => input.hasValue);
142
142
 
143
143
  if (!this.deselectMessageElement && groupElementSelected) {
144
144
  const deselectMessageElement = document.createElement('span');