@ons/design-system 49.2.0 → 51.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 (167) hide show
  1. package/README.md +35 -13
  2. package/components/access-code/_macro.njk +1 -1
  3. package/components/access-code/_macro.spec.js +162 -0
  4. package/components/access-code/uac.spec.js +26 -0
  5. package/components/accordion/_macro.spec.js +224 -0
  6. package/components/accordion/accordion.spec.js +134 -0
  7. package/components/address-input/_macro.njk +1 -1
  8. package/components/address-input/_macro.spec.js +465 -0
  9. package/components/address-input/autosuggest.address.js +5 -4
  10. package/components/address-input/autosuggest.address.setter.js +3 -1
  11. package/components/address-input/autosuggest.address.spec.js +733 -0
  12. package/components/address-output/_macro.njk +6 -6
  13. package/components/address-output/_macro.spec.js +122 -0
  14. package/components/autosuggest/_macro.njk +1 -1
  15. package/components/autosuggest/_macro.spec.js +229 -0
  16. package/components/autosuggest/autosuggest.helpers.js +2 -3
  17. package/components/autosuggest/autosuggest.helpers.spec.js +85 -0
  18. package/components/autosuggest/autosuggest.js +4 -2
  19. package/components/autosuggest/autosuggest.spec.js +625 -0
  20. package/components/autosuggest/autosuggest.ui.js +6 -2
  21. package/components/breadcrumbs/_macro.spec.js +129 -0
  22. package/components/button/_macro.njk +5 -5
  23. package/components/button/_macro.spec.js +446 -0
  24. package/components/button/button.spec.js +290 -0
  25. package/components/call-to-action/_macro.njk +3 -1
  26. package/components/call-to-action/_macro.spec.js +52 -0
  27. package/components/card/_macro.njk +26 -19
  28. package/components/card/_macro.spec.js +261 -0
  29. package/components/char-check-limit/_macro.spec.js +73 -0
  30. package/components/char-check-limit/character-check.spec.js +196 -0
  31. package/components/char-check-limit/character-limit.js +1 -1
  32. package/components/checkboxes/_checkbox-macro.njk +2 -2
  33. package/components/checkboxes/_checkbox-macro.spec.js +419 -0
  34. package/components/checkboxes/_macro.njk +3 -5
  35. package/components/checkboxes/_macro.spec.js +306 -0
  36. package/components/checkboxes/checkboxes.spec.js +208 -0
  37. package/components/code-highlight/_macro.spec.js +56 -0
  38. package/components/code-highlight/code-highlight.spec.js +18 -0
  39. package/components/collapsible/_macro.spec.js +204 -0
  40. package/components/collapsible/collapsible.js +2 -1
  41. package/components/collapsible/collapsible.spec.js +236 -0
  42. package/components/content-pagination/_macro.spec.js +199 -0
  43. package/components/cookies-banner/_macro.njk +1 -1
  44. package/components/cookies-banner/_macro.spec.js +171 -0
  45. package/components/cookies-banner/cookies-banner.spec.js +90 -0
  46. package/components/date-input/_macro.njk +8 -5
  47. package/components/date-input/_macro.spec.js +286 -0
  48. package/components/document-list/_macro.njk +3 -5
  49. package/components/document-list/_macro.spec.js +491 -0
  50. package/components/download-resources/download-resources.spec.js +540 -0
  51. package/components/duration/_macro.njk +7 -6
  52. package/components/duration/_macro.spec.js +251 -0
  53. package/components/error/_macro.spec.js +97 -0
  54. package/components/external-link/_macro.spec.js +60 -0
  55. package/components/feedback/_macro.njk +5 -3
  56. package/components/feedback/_macro.spec.js +122 -0
  57. package/components/field/_macro.njk +2 -2
  58. package/components/field/_macro.spec.js +97 -0
  59. package/components/fieldset/_macro.njk +3 -3
  60. package/components/fieldset/_macro.spec.js +173 -0
  61. package/components/footer/_macro.njk +11 -48
  62. package/components/footer/_macro.spec.js +549 -0
  63. package/components/header/_macro.njk +2 -2
  64. package/components/header/_macro.spec.js +562 -0
  65. package/components/hero/_hero.scss +0 -3
  66. package/components/hero/_macro.njk +4 -4
  67. package/components/hero/_macro.spec.js +224 -0
  68. package/components/icons/_macro.njk +15 -15
  69. package/components/icons/_macro.spec.js +140 -0
  70. package/components/images/_macro.njk +1 -1
  71. package/components/images/_macro.spec.js +121 -0
  72. package/components/input/_input-type.scss +12 -5
  73. package/components/input/_macro.njk +6 -7
  74. package/components/input/_macro.spec.js +658 -0
  75. package/components/label/_macro.spec.js +189 -0
  76. package/components/language-selector/_macro.spec.js +129 -0
  77. package/components/lists/_list.scss +4 -0
  78. package/components/lists/_macro.njk +4 -7
  79. package/components/lists/_macro.spec.js +618 -0
  80. package/components/message/_macro.spec.js +137 -0
  81. package/components/message-list/_macro.njk +7 -7
  82. package/components/message-list/_macro.spec.js +159 -0
  83. package/components/metadata/_macro.spec.js +167 -0
  84. package/components/modal/_macro.njk +6 -6
  85. package/components/modal/_macro.spec.js +87 -0
  86. package/components/modal/modal.js +0 -16
  87. package/components/modal/modal.spec.js +59 -0
  88. package/components/mutually-exclusive/_macro.njk +38 -21
  89. package/components/mutually-exclusive/_macro.spec.js +182 -0
  90. package/components/mutually-exclusive/mutually-exclusive.checkboxes.spec.js +203 -0
  91. package/components/mutually-exclusive/mutually-exclusive.date.spec.js +142 -0
  92. package/components/mutually-exclusive/mutually-exclusive.duration.spec.js +141 -0
  93. package/components/mutually-exclusive/mutually-exclusive.email.spec.js +117 -0
  94. package/components/mutually-exclusive/mutually-exclusive.js +32 -23
  95. package/components/mutually-exclusive/mutually-exclusive.multiple-options.checkboxes.spec.js +213 -0
  96. package/components/mutually-exclusive/mutually-exclusive.number.spec.js +125 -0
  97. package/components/mutually-exclusive/mutually-exclusive.textarea.spec.js +131 -0
  98. package/components/navigation/_macro.njk +6 -6
  99. package/components/navigation/_macro.spec.js +327 -0
  100. package/components/navigation/navigation.dom.js +1 -1
  101. package/components/navigation/navigation.spec.js +232 -0
  102. package/components/pagination/_macro.njk +1 -1
  103. package/components/pagination/_macro.spec.js +411 -0
  104. package/components/panel/_macro.njk +6 -6
  105. package/components/panel/_macro.spec.js +423 -0
  106. package/components/password/_macro.spec.js +137 -0
  107. package/components/password/password.spec.js +40 -0
  108. package/components/phase-banner/_macro.spec.js +73 -0
  109. package/components/promotional-banner/_macro.spec.js +97 -0
  110. package/components/question/_macro.njk +25 -33
  111. package/components/question/_macro.spec.js +309 -0
  112. package/components/quote/_macro.spec.js +81 -0
  113. package/components/radios/_macro.njk +98 -102
  114. package/components/radios/_macro.spec.js +575 -0
  115. package/components/radios/radios.spec.js +180 -0
  116. package/components/related-content/_macro.njk +1 -0
  117. package/components/related-content/_macro.spec.js +142 -0
  118. package/components/relationships/_macro.spec.js +108 -0
  119. package/components/relationships/relationships.spec.js +84 -0
  120. package/components/reply/_macro.njk +2 -2
  121. package/components/reply/_macro.spec.js +69 -0
  122. package/components/reply/reply.spec.js +78 -0
  123. package/components/search/_macro.njk +14 -12
  124. package/components/search/_macro.spec.js +44 -0
  125. package/components/search/_search.scss +7 -7
  126. package/components/section-navigation/_macro.njk +7 -2
  127. package/components/section-navigation/_macro.spec.js +206 -0
  128. package/components/select/_macro.njk +3 -3
  129. package/components/select/_macro.spec.js +203 -0
  130. package/components/select/select.spec.js +56 -0
  131. package/components/share-page/_macro.njk +2 -2
  132. package/components/share-page/_macro.spec.js +110 -0
  133. package/components/skip-to-content/_macro.spec.js +57 -0
  134. package/components/skip-to-content/skip-to-content.spec.js +44 -0
  135. package/components/status/_macro.spec.js +77 -0
  136. package/components/summary/_macro.njk +5 -5
  137. package/components/summary/_macro.spec.js +472 -0
  138. package/components/table/_macro.njk +2 -2
  139. package/components/table/_macro.spec.js +557 -0
  140. package/components/table/table.spec.js +155 -0
  141. package/components/table-of-contents/_macro.njk +35 -35
  142. package/components/table-of-contents/_macro.spec.js +178 -0
  143. package/components/table-of-contents/toc.js +29 -25
  144. package/components/table-of-contents/toc.spec.js +61 -0
  145. package/components/tabs/_macro.njk +1 -1
  146. package/components/tabs/_macro.spec.js +79 -0
  147. package/components/tabs/tabs.spec.js +162 -0
  148. package/components/text-indent/_macro.spec.js +52 -0
  149. package/components/textarea/_macro.njk +7 -5
  150. package/components/textarea/_macro.spec.js +300 -0
  151. package/components/textarea/textarea.spec.js +98 -0
  152. package/components/timeline/_macro.njk +3 -3
  153. package/components/timeline/_macro.spec.js +81 -0
  154. package/components/timeout-modal/_macro.spec.js +68 -0
  155. package/components/timeout-modal/timeout-modal.spec.js +226 -0
  156. package/components/timeout-panel/_macro.njk +0 -1
  157. package/components/timeout-panel/_macro.spec.js +54 -0
  158. package/components/timeout-panel/timeout-panel.dom.js +1 -2
  159. package/components/timeout-panel/timeout-panel.spec.js +161 -0
  160. package/components/upload/_macro.spec.js +75 -0
  161. package/components/video/_macro.spec.js +34 -0
  162. package/css/census.css +1 -1
  163. package/css/main.css +1 -1
  164. package/js/cookies-settings.spec.js +154 -0
  165. package/package.json +10 -23
  166. package/scripts/main.es5.js +1 -1
  167. package/scripts/main.js +2 -2
@@ -0,0 +1,171 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import * as cheerio from 'cheerio';
4
+
5
+ import axe from '../../tests/helpers/axe';
6
+ import { renderComponent, templateFaker } from '../../tests/helpers/rendering';
7
+
8
+ const EXAMPLE_COOKIES_BANNER_MINIMAL = {
9
+ statementTitle: 'Tell us whether you accept cookies',
10
+ statementText:
11
+ 'We use <a href="#0">cookies to collect information</a> about how you use census.gov.uk. We use this information to make the website work as well as possible and improve our services.',
12
+ confirmationText: 'You’ve accepted all cookies. You can <a href="#0">change your cookie preferences</a> at any time.',
13
+ };
14
+
15
+ const EXAMPLE_COOKIES_BANNER = {
16
+ ...EXAMPLE_COOKIES_BANNER_MINIMAL,
17
+ ariaLabel: 'the cookies banner',
18
+ primaryButtonText: 'Accept cookies',
19
+ secondaryButtonText: 'Set preferences',
20
+ secondaryButtonUrl: 'https://example.com/cookies/set-preferences',
21
+ confirmationButtonText: 'Close',
22
+ confirmationButtonTextAria: 'the cookie banner',
23
+ };
24
+
25
+ describe('macro: cookies-banner', () => {
26
+ it.each([
27
+ ['minimal parameters', EXAMPLE_COOKIES_BANNER_MINIMAL],
28
+ ['all parameters', EXAMPLE_COOKIES_BANNER],
29
+ ])('passes jest-axe checks with %s', async (_, params) => {
30
+ const $ = cheerio.load(renderComponent('cookies-banner', params));
31
+
32
+ const results = await axe($.html());
33
+ expect(results).toHaveNoViolations();
34
+ });
35
+
36
+ it('has a `role` of "region"', () => {
37
+ const $ = cheerio.load(renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER_MINIMAL));
38
+
39
+ expect($('.ons-cookies-banner').attr('role')).toBe('region');
40
+ });
41
+
42
+ it('has a default `aria-label` of "Cookies banner"', () => {
43
+ const $ = cheerio.load(renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER_MINIMAL));
44
+
45
+ expect($('.ons-cookies-banner').attr('aria-label')).toBe('Cookies banner');
46
+ });
47
+
48
+ it('has the provided `ariaLabel` for `aria-label`', () => {
49
+ const $ = cheerio.load(renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER));
50
+
51
+ expect($('.ons-cookies-banner').attr('aria-label')).toBe('the cookies banner');
52
+ });
53
+
54
+ describe('content', () => {
55
+ it('has provided `statementTitle` title text', () => {
56
+ const $ = cheerio.load(renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER_MINIMAL));
57
+
58
+ const statementTitle = $('.ons-cookies-banner__title')
59
+ .text()
60
+ .trim();
61
+ expect(statementTitle).toBe('Tell us whether you accept cookies');
62
+ });
63
+
64
+ it('has provided `statementText` text', () => {
65
+ const $ = cheerio.load(renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER_MINIMAL));
66
+
67
+ const statementText = $('.ons-cookies-banner__primary .ons-cookies-banner__desc')
68
+ .html()
69
+ .trim();
70
+ expect(statementText).toBe(
71
+ 'We use <a href="#0">cookies to collect information</a> about how you use census.gov.uk. We use this information to make the website work as well as possible and improve our services.',
72
+ );
73
+ });
74
+
75
+ it('has provided `confirmationText` text', () => {
76
+ const $ = cheerio.load(renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER_MINIMAL));
77
+
78
+ const statementText = $('.ons-cookies-banner__confirmation .ons-cookies-banner__desc')
79
+ .html()
80
+ .trim();
81
+ expect(statementText).toBe('You’ve accepted all cookies. You can <a href="#0">change your cookie preferences</a> at any time.');
82
+ });
83
+ });
84
+
85
+ describe('primary button', () => {
86
+ it('assumes default text "Accept all cookies"', () => {
87
+ const faker = templateFaker();
88
+ const buttonSpy = faker.spy('button');
89
+
90
+ faker.renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER_MINIMAL);
91
+
92
+ expect(buttonSpy.occurrences[0].text).toBe('Accept all cookies');
93
+ });
94
+
95
+ it('has provided `primaryButtonText` text', () => {
96
+ const faker = templateFaker();
97
+ const buttonSpy = faker.spy('button');
98
+
99
+ faker.renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER);
100
+
101
+ expect(buttonSpy.occurrences[0].text).toBe('Accept cookies');
102
+ });
103
+ });
104
+
105
+ describe('secondary button', () => {
106
+ it('assumes default text "Set cookie preferences"', () => {
107
+ const faker = templateFaker();
108
+ const buttonSpy = faker.spy('button');
109
+
110
+ faker.renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER_MINIMAL);
111
+
112
+ expect(buttonSpy.occurrences[1].text).toBe('Set cookie preferences');
113
+ });
114
+
115
+ it('has provided `secondaryButtonText` text', () => {
116
+ const faker = templateFaker();
117
+ const buttonSpy = faker.spy('button');
118
+
119
+ faker.renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER);
120
+
121
+ expect(buttonSpy.occurrences[1].text).toBe('Set preferences');
122
+ });
123
+
124
+ it('has provided `secondaryButtonUrl`', () => {
125
+ const faker = templateFaker();
126
+ const buttonSpy = faker.spy('button');
127
+
128
+ faker.renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER);
129
+
130
+ expect(buttonSpy.occurrences[1].url).toBe('https://example.com/cookies/set-preferences');
131
+ });
132
+ });
133
+
134
+ describe('confirmation button', () => {
135
+ it('assumes default text "Hide"', () => {
136
+ const faker = templateFaker();
137
+ const buttonSpy = faker.spy('button');
138
+
139
+ faker.renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER_MINIMAL);
140
+
141
+ expect(buttonSpy.occurrences[2].text).toBe('Hide');
142
+ });
143
+
144
+ it('has provided `confirmationButtonText` text', () => {
145
+ const faker = templateFaker();
146
+ const buttonSpy = faker.spy('button');
147
+
148
+ faker.renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER);
149
+
150
+ expect(buttonSpy.occurrences[2].text).toBe('Close');
151
+ });
152
+
153
+ it('has a default `buttonContext` of "cookie banner"', () => {
154
+ const faker = templateFaker();
155
+ const buttonSpy = faker.spy('button');
156
+
157
+ faker.renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER_MINIMAL);
158
+
159
+ expect(buttonSpy.occurrences[2].buttonContext).toBe('the cookie message');
160
+ });
161
+
162
+ it('has the provided `confirmationButtonTextAria` for `buttonContext`', () => {
163
+ const faker = templateFaker();
164
+ const buttonSpy = faker.spy('button');
165
+
166
+ faker.renderComponent('cookies-banner', EXAMPLE_COOKIES_BANNER);
167
+
168
+ expect(buttonSpy.occurrences[2].buttonContext).toBe('the cookie banner');
169
+ });
170
+ });
171
+ });
@@ -0,0 +1,90 @@
1
+ import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
2
+
3
+ const EXAMPLE_COOKIES_BANNER_PAGE = renderComponent('cookies-banner', {
4
+ statementTitle: 'Tell us whether you accept cookies',
5
+ statementText: 'We use <a href="#0">cookies to collect information</a> about how you use census.gov.uk.',
6
+ confirmationText: 'You’ve accepted all cookies. You can <a href="#0">change your cookie preferences</a> at any time.',
7
+ });
8
+
9
+ describe('script: cookies-banner', () => {
10
+ beforeEach(async () => {
11
+ const client = await page.target().createCDPSession();
12
+ await client.send('Network.clearBrowserCookies');
13
+ });
14
+
15
+ it('should show the cookie banner', async () => {
16
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
17
+
18
+ const displayStyle = await page.$eval('.ons-cookies-banner', node => window.getComputedStyle(node).getPropertyValue('display'));
19
+ expect(displayStyle).toBe('block');
20
+ });
21
+
22
+ it('sets all cookies to true when accepting cookies', async () => {
23
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
24
+
25
+ await page.click('.ons-js-accept-cookies');
26
+
27
+ const cookies = await page.cookies();
28
+ const ons_cookie_policy = cookies.find(cookie => cookie.name === 'ons_cookie_policy');
29
+ const policy = JSON.parse(ons_cookie_policy.value.replace(/'/g, '"'));
30
+
31
+ expect(policy).toEqual({
32
+ essential: true,
33
+ settings: true,
34
+ usage: true,
35
+ campaigns: true,
36
+ });
37
+ });
38
+
39
+ it('sets seen cookie message when accepting cookies', async () => {
40
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
41
+
42
+ await page.click('.ons-js-accept-cookies');
43
+
44
+ const cookies = await page.cookies();
45
+ const ons_cookie_message_displayed = cookies.find(cookie => cookie.name === 'ons_cookie_message_displayed');
46
+
47
+ expect(ons_cookie_message_displayed.value).toBe('true');
48
+ });
49
+
50
+ it('should hide the primary message when pressing the accept button', async () => {
51
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
52
+
53
+ await page.click('.ons-js-accept-cookies');
54
+
55
+ const displayStyle = await page.$eval('.ons-cookies-banner__primary', node =>
56
+ window.getComputedStyle(node).getPropertyValue('display'),
57
+ );
58
+ expect(displayStyle).toBe('none');
59
+ });
60
+
61
+ it('should show the secondary message when pressing the accept button', async () => {
62
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
63
+
64
+ await page.click('.ons-js-accept-cookies');
65
+
66
+ const displayStyle = await page.$eval('.ons-cookies-banner__confirmation', node =>
67
+ window.getComputedStyle(node).getPropertyValue('display'),
68
+ );
69
+ expect(displayStyle).not.toBe('none');
70
+ });
71
+ //...
72
+ it('should hide the secondary message when pressing the hide button', async () => {
73
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
74
+
75
+ await page.click('.ons-js-accept-cookies');
76
+ await page.click('.ons-js-hide-button');
77
+
78
+ const displayStyle = await page.$eval('.ons-cookies-banner', node => window.getComputedStyle(node).getPropertyValue('display'));
79
+ expect(displayStyle).toBe('none');
80
+ });
81
+
82
+ it('does not show the banner if user has acknowledged the banner previously and consent cookie is present', async () => {
83
+ await page.setCookie({ name: 'ons_cookie_message_displayed', value: 'true' });
84
+
85
+ await setTestPage('/test', EXAMPLE_COOKIES_BANNER_PAGE);
86
+
87
+ const displayStyle = await page.$eval('.ons-cookies-banner', node => window.getComputedStyle(node).getPropertyValue('display'));
88
+ expect(displayStyle).toBe('none');
89
+ });
90
+ });
@@ -34,7 +34,8 @@
34
34
  "attributes": params.day.attributes,
35
35
  "label": {
36
36
  "text": params.day.label.text if numberOfFields > 1 else params.legendOrLabel,
37
- "description": params.day.label.description if numberOfFields > 1 else params.description
37
+ "description": params.day.label.description if numberOfFields > 1 else params.description,
38
+ "id": params.id + "-day-label"
38
39
  },
39
40
  "value": params.day.value
40
41
  }) }}
@@ -53,7 +54,8 @@
53
54
  "attributes": params.month.attributes,
54
55
  "label": {
55
56
  "text": params.month.label.text if numberOfFields > 1 else params.legendOrLabel,
56
- "description": params.month.label.description if numberOfFields > 1 else params.description
57
+ "description": params.month.label.description if numberOfFields > 1 else params.description,
58
+ "id": params.id + "-month-label"
57
59
  },
58
60
  "value": params.month.value
59
61
  }) }}
@@ -72,7 +74,8 @@
72
74
  "attributes": params.year.attributes,
73
75
  "label": {
74
76
  "text": params.year.label.text if numberOfFields > 1 else params.legendOrLabel,
75
- "description": params.year.label.description if numberOfFields > 1 else params.description
77
+ "description": params.year.label.description if numberOfFields > 1 else params.description,
78
+ "id": params.id + "-year-label"
76
79
  },
77
80
  "value": params.year.value
78
81
  }) }}
@@ -96,11 +99,11 @@
96
99
  "classes": params.classes,
97
100
  "dontWrap": params.dontWrap if numberOfFields > 1 else true,
98
101
  "legendIsQuestionTitle": params.legendIsQuestionTitle,
99
- "checkbox": params.mutuallyExclusive.checkbox,
102
+ "exclusiveOptions": params.mutuallyExclusive.exclusiveOptions,
100
103
  "or": params.mutuallyExclusive.or,
101
104
  "deselectMessage": params.mutuallyExclusive.deselectMessage,
102
105
  "deselectGroupAdjective": params.mutuallyExclusive.deselectGroupAdjective,
103
- "deselectCheckboxAdjective": params.mutuallyExclusive.deselectCheckboxAdjective,
106
+ "deselectExclusiveOptionAdjective": params.mutuallyExclusive.deselectExclusiveOptionAdjective,
104
107
  "error": params.error
105
108
  }) %}
106
109
  {{ fields | safe }}
@@ -0,0 +1,286 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import * as cheerio from 'cheerio';
4
+
5
+ import axe from '../../tests/helpers/axe';
6
+ import { renderComponent, templateFaker } from '../../tests/helpers/rendering';
7
+
8
+ const EXAMPLE_DATE_INPUT_BASE = {
9
+ id: 'date',
10
+ legendOrLabel: 'Date of birth',
11
+ description: 'For example, 31 3 1980',
12
+ };
13
+
14
+ const EXAMPLE_DAY_FIELD = {
15
+ day: {
16
+ label: {
17
+ text: 'Day',
18
+ description: 'The day',
19
+ },
20
+ value: 'Day',
21
+ name: 'day',
22
+ attributes: {
23
+ autocomplete: 'bday-day',
24
+ },
25
+ },
26
+ };
27
+
28
+ const EXAMPLE_MONTH_FIELD = {
29
+ month: {
30
+ label: {
31
+ text: 'Month',
32
+ description: 'The month',
33
+ },
34
+ value: 'Month',
35
+ name: 'month',
36
+ attributes: {
37
+ autocomplete: 'bday-month',
38
+ },
39
+ },
40
+ };
41
+
42
+ const EXAMPLE_YEAR_FIELD = {
43
+ year: {
44
+ label: {
45
+ text: 'Year',
46
+ description: 'The year',
47
+ },
48
+ value: 'Year',
49
+ name: 'year',
50
+ attributes: {
51
+ autocomplete: 'bday-year',
52
+ },
53
+ },
54
+ };
55
+
56
+ const EXAMPLE_DATE_SINGLE_FIELD = {
57
+ ...EXAMPLE_DATE_INPUT_BASE,
58
+ ...EXAMPLE_YEAR_FIELD,
59
+ };
60
+
61
+ const EXAMPLE_DATE_MULTIPLE_FIELDS = {
62
+ ...EXAMPLE_DATE_INPUT_BASE,
63
+ ...EXAMPLE_DAY_FIELD,
64
+ ...EXAMPLE_MONTH_FIELD,
65
+ ...EXAMPLE_YEAR_FIELD,
66
+ };
67
+
68
+ describe('macro: date input', () => {
69
+ describe('mode: multiple fields', () => {
70
+ it('passes jest-axe checks', async () => {
71
+ const $ = cheerio.load(renderComponent('date-input', EXAMPLE_DATE_MULTIPLE_FIELDS));
72
+
73
+ const results = await axe($.html());
74
+ expect(results).toHaveNoViolations();
75
+ });
76
+
77
+ it('has the expected `input` output for the `day` field', () => {
78
+ const faker = templateFaker();
79
+ const inputSpy = faker.spy('input');
80
+
81
+ faker.renderComponent('date-input', EXAMPLE_DATE_MULTIPLE_FIELDS);
82
+
83
+ expect(inputSpy.occurrences[0]).toEqual({
84
+ id: 'date-day',
85
+ type: 'number',
86
+ name: 'day',
87
+ width: '2',
88
+ min: 1,
89
+ max: 31,
90
+ maxLength: 2,
91
+ classes: '',
92
+ label: {
93
+ text: 'Day',
94
+ description: 'The day',
95
+ id: 'date-day-label',
96
+ },
97
+ value: 'Day',
98
+ attributes: {
99
+ autocomplete: 'bday-day',
100
+ },
101
+ });
102
+ });
103
+
104
+ it('has the expected `input` output for the `month` field', () => {
105
+ const faker = templateFaker();
106
+ const inputSpy = faker.spy('input');
107
+
108
+ faker.renderComponent('date-input', EXAMPLE_DATE_MULTIPLE_FIELDS);
109
+
110
+ expect(inputSpy.occurrences[1]).toEqual({
111
+ id: 'date-month',
112
+ type: 'number',
113
+ name: 'month',
114
+ width: '2',
115
+ min: 1,
116
+ max: 12,
117
+ maxLength: 2,
118
+ classes: '',
119
+ label: {
120
+ text: 'Month',
121
+ description: 'The month',
122
+ id: 'date-month-label',
123
+ },
124
+ value: 'Month',
125
+ attributes: {
126
+ autocomplete: 'bday-month',
127
+ },
128
+ });
129
+ });
130
+
131
+ it('has the expected `input` output for the `year` field', () => {
132
+ const faker = templateFaker();
133
+ const inputSpy = faker.spy('input');
134
+
135
+ faker.renderComponent('date-input', EXAMPLE_DATE_MULTIPLE_FIELDS);
136
+
137
+ expect(inputSpy.occurrences[2]).toEqual({
138
+ id: 'date-year',
139
+ type: 'number',
140
+ name: 'year',
141
+ width: '4',
142
+ min: 1000,
143
+ max: 3000,
144
+ maxLength: 4,
145
+ classes: '',
146
+ label: {
147
+ text: 'Year',
148
+ description: 'The year',
149
+ id: 'date-year-label',
150
+ },
151
+ value: 'Year',
152
+ attributes: {
153
+ autocomplete: 'bday-year',
154
+ },
155
+ });
156
+ });
157
+
158
+ it('has the group class div', () => {
159
+ const $ = cheerio.load(renderComponent('date-input', EXAMPLE_DATE_MULTIPLE_FIELDS));
160
+ const div = $('.ons-field:first-child').parent();
161
+ expect($(div).hasClass('ons-field-group')).toBe(true);
162
+ });
163
+
164
+ it('has the expected `fieldset` output', () => {
165
+ const faker = templateFaker();
166
+ const fieldsetSpy = faker.spy('fieldset');
167
+
168
+ faker.renderComponent('date-input', {
169
+ ...EXAMPLE_DATE_MULTIPLE_FIELDS,
170
+ legendClasses: 'custom-legend-class',
171
+ classes: 'custom-class',
172
+ dontWrap: true,
173
+ legendIsQuestionTitle: true,
174
+ error: false,
175
+ });
176
+
177
+ expect(fieldsetSpy.occurrences[0]).toEqual({
178
+ id: 'date',
179
+ legend: 'Date of birth',
180
+ description: 'For example, 31 3 1980',
181
+ legendClasses: 'custom-legend-class',
182
+ classes: 'custom-class',
183
+ dontWrap: true,
184
+ legendIsQuestionTitle: true,
185
+ error: false,
186
+ });
187
+ });
188
+ });
189
+
190
+ describe('mode: multiple fields with mutually exclusive', () => {
191
+ it('has the correct class on each input', async () => {
192
+ const $ = cheerio.load(renderComponent('date-input', { ...EXAMPLE_DATE_MULTIPLE_FIELDS, mutuallyExclusive: {} }));
193
+
194
+ const exclusiveClassCount = $('.ons-js-exclusive-group-item').length;
195
+ expect(exclusiveClassCount).toBe(3);
196
+ });
197
+
198
+ it('has the expected `mutuallyExclusive` output', () => {
199
+ const faker = templateFaker();
200
+ const mutuallyExclusiveSpy = faker.spy('mutually-exclusive');
201
+
202
+ faker.renderComponent('date-input', {
203
+ ...EXAMPLE_DATE_MULTIPLE_FIELDS,
204
+ legendClasses: 'custom-legend-class',
205
+ classes: 'custom-class',
206
+ dontWrap: true,
207
+ legendIsQuestionTitle: true,
208
+ error: false,
209
+ mutuallyExclusive: {
210
+ exclusiveOptions: {},
211
+ or: 'Or',
212
+ deselectMessage: 'Deselect message',
213
+ deselectGroupAdjective: 'Deselect group adjective',
214
+ deselectExclusiveOptionAdjective: 'Deselect checkbox adjective',
215
+ },
216
+ });
217
+
218
+ expect(mutuallyExclusiveSpy.occurrences[0]).toEqual({
219
+ id: 'date',
220
+ legend: 'Date of birth',
221
+ description: 'For example, 31 3 1980',
222
+ legendClasses: 'custom-legend-class',
223
+ classes: 'custom-class',
224
+ dontWrap: true,
225
+ legendIsQuestionTitle: true,
226
+ error: false,
227
+ exclusiveOptions: {},
228
+ or: 'Or',
229
+ deselectMessage: 'Deselect message',
230
+ deselectGroupAdjective: 'Deselect group adjective',
231
+ deselectExclusiveOptionAdjective: 'Deselect checkbox adjective',
232
+ });
233
+ });
234
+ });
235
+
236
+ describe('mode: single field', () => {
237
+ it('passes jest-axe checks', async () => {
238
+ const $ = cheerio.load(renderComponent('date-input', EXAMPLE_DATE_SINGLE_FIELD));
239
+
240
+ const results = await axe($.html());
241
+ expect(results).toHaveNoViolations();
242
+ });
243
+
244
+ it('has the expected `input` output for the field', () => {
245
+ const faker = templateFaker();
246
+ const inputSpy = faker.spy('input');
247
+
248
+ faker.renderComponent('date-input', EXAMPLE_DATE_SINGLE_FIELD);
249
+
250
+ expect(inputSpy.occurrences[0]).toEqual({
251
+ id: 'date-year',
252
+ type: 'number',
253
+ name: 'year',
254
+ width: '4',
255
+ min: 1000,
256
+ max: 3000,
257
+ maxLength: 4,
258
+ classes: '',
259
+ label: {
260
+ text: 'Date of birth',
261
+ description: 'For example, 31 3 1980',
262
+ id: 'date-year-label',
263
+ },
264
+ value: 'Year',
265
+ attributes: {
266
+ autocomplete: 'bday-year',
267
+ },
268
+ });
269
+ });
270
+
271
+ it('has the expected `error` output', () => {
272
+ const faker = templateFaker();
273
+ const errorSpy = faker.spy('error');
274
+
275
+ faker.renderComponent('date-input', {
276
+ ...EXAMPLE_DATE_SINGLE_FIELD,
277
+ error: { text: 'Enter a date that is after 1 January 2019', dsExample: false },
278
+ });
279
+
280
+ expect(errorSpy.occurrences[0]).toEqual({
281
+ text: 'Enter a date that is after 1 January 2019',
282
+ dsExample: false,
283
+ });
284
+ });
285
+ });
286
+ });
@@ -31,17 +31,15 @@
31
31
  <{{ titleTag }} class="ons-document-list__item-title ons-u-fs-m ons-u-mt-no ons-u-mb-xs">
32
32
  <a href="{{ document.url }}">{{ document.title }}
33
33
  {%- if document.metadata is defined and document.metadata and document.metadata.file is defined and document.metadata.file %}
34
- <span class="ons-u-vh">,
35
-
34
+ <span class="ons-u-vh">
36
35
  {% set fileMetadataItems = [] %}
37
-
38
36
  {% if document.metadata.file.fileType is defined and document.metadata.file.fileType %}{% set fileMetadataItems = (fileMetadataItems.push(document.metadata.file.fileType + ' document download'), fileMetadataItems) %}{% endif %}
39
37
  {% if document.metadata.file.fileSize is defined and document.metadata.file.fileSize %}{% set fileMetadataItems = (fileMetadataItems.push(document.metadata.file.fileSize), fileMetadataItems) %}{% endif %}
40
38
  {% if document.metadata.file.filePages is defined and document.metadata.file.filePages %}{% set fileMetadataItems = (fileMetadataItems.push(document.metadata.file.filePages), fileMetadataItems) %}{% endif %}
41
39
 
42
- {{ fileMetadataItems | join(', ') }}
40
+ , {{ fileMetadataItems | join(', ') }}
43
41
 
44
- {% endif -%}
42
+ {% endif %}
45
43
 
46
44
  </span></a>
47
45
  </{{ titleTag }}>