@ons/design-system 50.0.1 → 53.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.
- package/README.md +35 -15
- package/components/access-code/_macro.njk +1 -1
- package/components/access-code/_macro.spec.js +162 -0
- package/components/access-code/uac.spec.js +26 -0
- package/components/accordion/_macro.spec.js +224 -0
- package/components/accordion/accordion.spec.js +134 -0
- package/components/address-input/_macro.njk +1 -1
- package/components/address-input/_macro.spec.js +465 -0
- package/components/address-input/autosuggest.address.js +5 -4
- package/components/address-input/autosuggest.address.setter.js +9 -3
- package/components/address-input/autosuggest.address.spec.js +733 -0
- package/components/address-output/_macro.njk +6 -6
- package/components/address-output/_macro.spec.js +122 -0
- package/components/autosuggest/_macro.njk +1 -1
- package/components/autosuggest/_macro.spec.js +229 -0
- package/components/autosuggest/autosuggest.helpers.js +2 -3
- package/components/autosuggest/autosuggest.helpers.spec.js +85 -0
- package/components/autosuggest/autosuggest.js +4 -2
- package/components/autosuggest/autosuggest.spec.js +625 -0
- package/components/autosuggest/autosuggest.ui.js +6 -2
- package/components/breadcrumbs/_macro.spec.js +129 -0
- package/components/button/_button.scss +75 -33
- package/components/button/_macro.njk +6 -6
- package/components/button/_macro.spec.js +446 -0
- package/components/button/button.spec.js +290 -0
- package/components/call-to-action/_macro.njk +3 -1
- package/components/call-to-action/_macro.spec.js +52 -0
- package/components/card/_macro.njk +26 -19
- package/components/card/_macro.spec.js +261 -0
- package/components/char-check-limit/_macro.spec.js +73 -0
- package/components/char-check-limit/character-check.spec.js +196 -0
- package/components/char-check-limit/character-limit.js +1 -1
- package/components/checkboxes/_checkbox-macro.spec.js +419 -0
- package/components/checkboxes/_macro.njk +1 -3
- package/components/checkboxes/_macro.spec.js +306 -0
- package/components/checkboxes/checkbox-with-autoselect.js +2 -1
- package/components/checkboxes/checkboxes.spec.js +208 -0
- package/components/code-highlight/_macro.spec.js +56 -0
- package/components/code-highlight/code-highlight.spec.js +18 -0
- package/components/collapsible/_macro.spec.js +204 -0
- package/components/collapsible/collapsible.js +2 -1
- package/components/collapsible/collapsible.spec.js +236 -0
- package/components/content-pagination/_macro.spec.js +199 -0
- package/components/cookies-banner/_macro.njk +1 -1
- package/components/cookies-banner/_macro.spec.js +171 -0
- package/components/cookies-banner/cookies-banner.spec.js +90 -0
- package/components/date-input/_macro.njk +6 -3
- package/components/date-input/_macro.spec.js +286 -0
- package/components/document-list/_macro.njk +3 -5
- package/components/document-list/_macro.spec.js +491 -0
- package/components/download-resources/download-resources.spec.js +540 -0
- package/components/duration/_macro.njk +7 -6
- package/components/duration/_macro.spec.js +251 -0
- package/components/error/_macro.spec.js +97 -0
- package/components/external-link/_macro.njk +5 -2
- package/components/external-link/_macro.spec.js +77 -0
- package/components/feedback/_macro.njk +5 -3
- package/components/feedback/_macro.spec.js +122 -0
- package/components/field/_macro.njk +2 -2
- package/components/field/_macro.spec.js +97 -0
- package/components/fieldset/_macro.njk +3 -3
- package/components/fieldset/_macro.spec.js +173 -0
- package/components/footer/_footer.scss +19 -4
- package/components/footer/_macro.njk +106 -137
- package/components/footer/_macro.spec.js +678 -0
- package/components/header/_header.scss +65 -46
- package/components/header/_macro.njk +173 -121
- package/components/header/_macro.spec.js +618 -0
- package/components/hero/_hero.scss +30 -143
- package/components/hero/_macro.njk +12 -23
- package/components/hero/_macro.spec.js +218 -0
- package/components/icons/_macro.njk +258 -30
- package/components/icons/_macro.spec.js +140 -0
- package/components/images/_macro.njk +1 -1
- package/components/images/_macro.spec.js +121 -0
- package/components/input/_input-type.scss +12 -5
- package/components/input/_input.scss +8 -0
- package/components/input/_macro.njk +4 -5
- package/components/input/_macro.spec.js +658 -0
- package/components/label/_macro.spec.js +189 -0
- package/components/language-selector/_macro.njk +1 -1
- package/components/language-selector/_macro.spec.js +137 -0
- package/components/lists/_list.scss +4 -0
- package/components/lists/_macro.njk +4 -7
- package/components/lists/_macro.spec.js +618 -0
- package/components/message/_macro.spec.js +137 -0
- package/components/message-list/_macro.njk +7 -7
- package/components/message-list/_macro.spec.js +159 -0
- package/components/metadata/_macro.spec.js +167 -0
- package/components/modal/_macro.njk +6 -6
- package/components/modal/_macro.spec.js +87 -0
- package/components/modal/modal.spec.js +59 -0
- package/components/mutually-exclusive/_macro.njk +2 -2
- package/components/mutually-exclusive/_macro.spec.js +184 -0
- package/components/mutually-exclusive/mutually-exclusive.checkboxes.spec.js +203 -0
- package/components/mutually-exclusive/mutually-exclusive.date.spec.js +142 -0
- package/components/mutually-exclusive/mutually-exclusive.duration.spec.js +141 -0
- package/components/mutually-exclusive/mutually-exclusive.email.spec.js +117 -0
- package/components/mutually-exclusive/mutually-exclusive.multiple-options.checkboxes.spec.js +213 -0
- package/components/mutually-exclusive/mutually-exclusive.number.spec.js +125 -0
- package/components/mutually-exclusive/mutually-exclusive.textarea.spec.js +131 -0
- package/components/navigation/_macro.njk +45 -38
- package/components/navigation/_macro.spec.js +329 -0
- package/components/navigation/_navigation.scss +20 -4
- package/components/navigation/navigation.dom.js +1 -1
- package/components/navigation/navigation.spec.js +232 -0
- package/components/pagination/_macro.njk +1 -1
- package/components/pagination/_macro.spec.js +411 -0
- package/components/panel/_macro.njk +6 -6
- package/components/panel/_macro.spec.js +423 -0
- package/components/password/_macro.spec.js +137 -0
- package/components/password/password.spec.js +40 -0
- package/components/phase-banner/_macro.spec.js +73 -0
- package/components/promotional-banner/_macro.spec.js +97 -0
- package/components/question/_macro.njk +16 -22
- package/components/question/_macro.spec.js +309 -0
- package/components/quote/_macro.spec.js +81 -0
- package/components/radios/_macro.njk +3 -6
- package/components/radios/_macro.spec.js +575 -0
- package/components/radios/radios.spec.js +180 -0
- package/components/related-content/_macro.njk +14 -21
- package/components/related-content/_macro.spec.js +133 -0
- package/components/related-content/_section-macro.njk +10 -0
- package/components/related-content/_section-macro.spec.js +43 -0
- package/components/relationships/_macro.spec.js +108 -0
- package/components/relationships/relationships.spec.js +84 -0
- package/components/reply/_macro.njk +2 -2
- package/components/reply/_macro.spec.js +69 -0
- package/components/reply/reply.spec.js +78 -0
- package/components/search/_macro.njk +14 -12
- package/components/search/_macro.spec.js +44 -0
- package/components/search/_search.scss +7 -7
- package/components/section-navigation/_macro.njk +7 -2
- package/components/section-navigation/_macro.spec.js +206 -0
- package/components/select/_macro.njk +3 -3
- package/components/select/_macro.spec.js +203 -0
- package/components/select/select.spec.js +56 -0
- package/components/share-page/_macro.njk +6 -4
- package/components/share-page/_macro.spec.js +110 -0
- package/components/skip-to-content/_macro.spec.js +57 -0
- package/components/skip-to-content/skip-to-content.spec.js +44 -0
- package/components/status/_macro.spec.js +77 -0
- package/components/summary/_macro.njk +5 -5
- package/components/summary/_macro.spec.js +472 -0
- package/components/table/_macro.njk +2 -2
- package/components/table/_macro.spec.js +557 -0
- package/components/table/table.spec.js +155 -0
- package/components/table-of-contents/_macro.njk +35 -35
- package/components/table-of-contents/_macro.spec.js +178 -0
- package/components/table-of-contents/toc.js +29 -25
- package/components/table-of-contents/toc.spec.js +61 -0
- package/components/tabs/_macro.njk +1 -1
- package/components/tabs/_macro.spec.js +79 -0
- package/components/tabs/tabs.spec.js +162 -0
- package/components/text-indent/_macro.spec.js +52 -0
- package/components/textarea/_macro.njk +5 -3
- package/components/textarea/_macro.spec.js +300 -0
- package/components/textarea/textarea.spec.js +98 -0
- package/components/timeline/_macro.njk +3 -3
- package/components/timeline/_macro.spec.js +81 -0
- package/components/timeout-modal/_macro.spec.js +68 -0
- package/components/timeout-modal/timeout-modal.spec.js +226 -0
- package/components/timeout-panel/_macro.njk +0 -1
- package/components/timeout-panel/_macro.spec.js +54 -0
- package/components/timeout-panel/timeout-panel.dom.js +1 -2
- package/components/timeout-panel/timeout-panel.spec.js +161 -0
- package/components/upload/_macro.spec.js +75 -0
- package/components/video/_macro.spec.js +34 -0
- package/css/census.css +3 -1
- package/css/ids.css +2 -0
- package/css/main.css +1 -1
- package/img/dummy-brand-logo.svg +1 -0
- package/js/cookies-settings.spec.js +154 -0
- package/layout/_template.njk +7 -4
- package/package.json +10 -23
- package/scripts/main.es5.js +2 -2
- package/scripts/main.js +1 -1
- package/scss/ids.scss +2 -0
- package/scss/settings/_census.scss +141 -0
- package/scss/settings/_ids.scss +48 -0
- package/scss/utilities/_margin.scss +1 -0
- package/scss/vars/_colors.scss +5 -2
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
|
|
2
|
+
|
|
3
|
+
describe('script: button', () => {
|
|
4
|
+
describe('mode: link', () => {
|
|
5
|
+
it('navigates to url when button is clicked with the spacebar', async () => {
|
|
6
|
+
await setTestPage(
|
|
7
|
+
'/test',
|
|
8
|
+
renderComponent('button', {
|
|
9
|
+
id: 'test-button',
|
|
10
|
+
url: '/test/path#abc',
|
|
11
|
+
}),
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
await page.focus('#test-button');
|
|
15
|
+
|
|
16
|
+
await Promise.all([page.waitForNavigation(), page.keyboard.press('Space')]);
|
|
17
|
+
|
|
18
|
+
const url = await page.url();
|
|
19
|
+
expect(url).toBe(`http://localhost:${process.env.TEST_PORT}/test/path#abc`);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('mode: standard', () => {
|
|
24
|
+
it('allow rapidly repeated submissions when in a form', async () => {
|
|
25
|
+
await setTestPage(
|
|
26
|
+
'/test',
|
|
27
|
+
`
|
|
28
|
+
<form>
|
|
29
|
+
${renderComponent('button', {
|
|
30
|
+
id: 'test-button',
|
|
31
|
+
})}
|
|
32
|
+
</form>
|
|
33
|
+
`,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
await page.evaluate(() => {
|
|
37
|
+
window.__COUNTER = 0;
|
|
38
|
+
document.querySelector('form').addEventListener('submit', event => {
|
|
39
|
+
window.__COUNTER++;
|
|
40
|
+
event.preventDefault();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
await page.click('#test-button');
|
|
45
|
+
await page.click('#test-button');
|
|
46
|
+
|
|
47
|
+
const counter = await page.evaluate(() => window.__COUNTER);
|
|
48
|
+
expect(counter).toBe(2);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('mode: loader', () => {
|
|
53
|
+
it('disables button when clicked', async () => {
|
|
54
|
+
await setTestPage(
|
|
55
|
+
'/test',
|
|
56
|
+
renderComponent('button', {
|
|
57
|
+
id: 'test-button',
|
|
58
|
+
text: 'Submit',
|
|
59
|
+
submitType: 'loader',
|
|
60
|
+
}),
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
await page.click('#test-button');
|
|
64
|
+
|
|
65
|
+
const isButtonDisabled = await page.evaluate(() => document.querySelector('#test-button').getAttribute('disabled'));
|
|
66
|
+
expect(isButtonDisabled).toBe('true');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('initialised without loading style applied', async () => {
|
|
70
|
+
await setTestPage(
|
|
71
|
+
'/test',
|
|
72
|
+
renderComponent('button', {
|
|
73
|
+
id: 'test-button',
|
|
74
|
+
text: 'Submit',
|
|
75
|
+
submitType: 'loader',
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const hasIsLoadingClass = await page.evaluate(() => document.querySelector('#test-button').classList.contains('ons-is-loading'));
|
|
80
|
+
expect(hasIsLoadingClass).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('applies loading style when clicked', async () => {
|
|
84
|
+
await setTestPage(
|
|
85
|
+
'/test',
|
|
86
|
+
renderComponent('button', {
|
|
87
|
+
id: 'test-button',
|
|
88
|
+
text: 'Submit',
|
|
89
|
+
submitType: 'loader',
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
await page.click('#test-button');
|
|
94
|
+
|
|
95
|
+
const hasIsLoadingClass = await page.evaluate(() => document.querySelector('#test-button').classList.contains('ons-is-loading'));
|
|
96
|
+
expect(hasIsLoadingClass).toBe(true);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('disables button when clicked when in a form', async () => {
|
|
100
|
+
await setTestPage(
|
|
101
|
+
'/test',
|
|
102
|
+
`
|
|
103
|
+
<form onsubmit="return false;">
|
|
104
|
+
${renderComponent('button', {
|
|
105
|
+
id: 'test-button',
|
|
106
|
+
text: 'Submit',
|
|
107
|
+
submitType: 'loader',
|
|
108
|
+
})}
|
|
109
|
+
</form>
|
|
110
|
+
`,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
await page.click('#test-button');
|
|
114
|
+
|
|
115
|
+
const isButtonDisabled = (await page.$('#test-button[disabled]')) !== null;
|
|
116
|
+
expect(isButtonDisabled).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('initialised without loading style applied when in a form', async () => {
|
|
120
|
+
await setTestPage(
|
|
121
|
+
'/test',
|
|
122
|
+
`
|
|
123
|
+
<form>
|
|
124
|
+
${renderComponent('button', {
|
|
125
|
+
id: 'test-button',
|
|
126
|
+
text: 'Submit',
|
|
127
|
+
submitType: 'loader',
|
|
128
|
+
})}
|
|
129
|
+
</form>
|
|
130
|
+
`,
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const hasIsLoadingClass = await page.evaluate(() => document.querySelector('#test-button').classList.contains('ons-is-loading'));
|
|
134
|
+
expect(hasIsLoadingClass).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('applies loading style when clicked when in a form', async () => {
|
|
138
|
+
await setTestPage(
|
|
139
|
+
'/test',
|
|
140
|
+
`
|
|
141
|
+
<form onsubmit="return false;">
|
|
142
|
+
${renderComponent('button', {
|
|
143
|
+
id: 'test-button',
|
|
144
|
+
text: 'Submit',
|
|
145
|
+
submitType: 'loader',
|
|
146
|
+
})}
|
|
147
|
+
</form>
|
|
148
|
+
`,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
await page.click('#test-button');
|
|
152
|
+
|
|
153
|
+
const hasIsLoadingClass = await page.evaluate(() => document.querySelector('#test-button').classList.contains('ons-is-loading'));
|
|
154
|
+
expect(hasIsLoadingClass).toBe(true);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe('mode: timer', () => {
|
|
159
|
+
it('allow intentional repeated submissions', async () => {
|
|
160
|
+
await setTestPage(
|
|
161
|
+
'/test',
|
|
162
|
+
renderComponent('button', {
|
|
163
|
+
id: 'test-button',
|
|
164
|
+
submitType: 'timer',
|
|
165
|
+
text: 'Submit',
|
|
166
|
+
}),
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
await page.evaluate(() => {
|
|
170
|
+
window.__COUNTER = 0;
|
|
171
|
+
document.querySelector('#test-button').addEventListener('click', event => {
|
|
172
|
+
window.__COUNTER++;
|
|
173
|
+
event.preventDefault();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
await page.click('#test-button');
|
|
178
|
+
await page.click('#test-button', { delay: 1000 });
|
|
179
|
+
|
|
180
|
+
const counter = await page.evaluate(() => window.__COUNTER);
|
|
181
|
+
expect(counter).toBe(2);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('prevents unintentional repeated submissions', async () => {
|
|
185
|
+
await setTestPage(
|
|
186
|
+
'/test',
|
|
187
|
+
renderComponent('button', {
|
|
188
|
+
id: 'test-button',
|
|
189
|
+
submitType: 'timer',
|
|
190
|
+
text: 'Submit',
|
|
191
|
+
}),
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
await page.evaluate(() => {
|
|
195
|
+
window.__COUNTER = 0;
|
|
196
|
+
document.querySelector('#test-button').addEventListener('click', event => {
|
|
197
|
+
window.__COUNTER++;
|
|
198
|
+
event.preventDefault();
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
await page.click('#test-button');
|
|
203
|
+
await page.click('#test-button');
|
|
204
|
+
|
|
205
|
+
const counter = await page.evaluate(() => window.__COUNTER);
|
|
206
|
+
expect(counter).toBe(1);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('allow intentional repeated submissions when in a form', async () => {
|
|
210
|
+
await setTestPage(
|
|
211
|
+
'/test',
|
|
212
|
+
`
|
|
213
|
+
<form>
|
|
214
|
+
${renderComponent('button', {
|
|
215
|
+
id: 'test-button',
|
|
216
|
+
submitType: 'timer',
|
|
217
|
+
text: 'Submit',
|
|
218
|
+
})}
|
|
219
|
+
</form>
|
|
220
|
+
`,
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
await page.evaluate(() => {
|
|
224
|
+
window.__COUNTER = 0;
|
|
225
|
+
document.querySelector('form').addEventListener('submit', event => {
|
|
226
|
+
window.__COUNTER++;
|
|
227
|
+
event.preventDefault();
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
await page.click('#test-button');
|
|
232
|
+
await page.click('#test-button', { delay: 1000 });
|
|
233
|
+
|
|
234
|
+
const counter = await page.evaluate(() => window.__COUNTER);
|
|
235
|
+
expect(counter).toBe(2);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('prevents unintentional repeated submissions when in a form', async () => {
|
|
239
|
+
await setTestPage(
|
|
240
|
+
'/test',
|
|
241
|
+
`
|
|
242
|
+
<form>
|
|
243
|
+
${renderComponent('button', {
|
|
244
|
+
id: 'test-button',
|
|
245
|
+
submitType: 'timer',
|
|
246
|
+
text: 'Submit',
|
|
247
|
+
})}
|
|
248
|
+
</form>
|
|
249
|
+
`,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
await page.evaluate(() => {
|
|
253
|
+
window.__COUNTER = 0;
|
|
254
|
+
document.querySelector('form').addEventListener('submit', event => {
|
|
255
|
+
window.__COUNTER++;
|
|
256
|
+
event.preventDefault();
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
await page.click('#test-button');
|
|
261
|
+
await page.click('#test-button');
|
|
262
|
+
|
|
263
|
+
const counter = await page.evaluate(() => window.__COUNTER);
|
|
264
|
+
expect(counter).toBe(1);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
describe('style: print', () => {
|
|
269
|
+
it('displays the browsers print interface', async () => {
|
|
270
|
+
await setTestPage(
|
|
271
|
+
'/test',
|
|
272
|
+
renderComponent('button', {
|
|
273
|
+
id: 'test-button',
|
|
274
|
+
type: 'button',
|
|
275
|
+
text: 'Print this page',
|
|
276
|
+
buttonStyle: 'print',
|
|
277
|
+
}),
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
await page.evaluate(() => {
|
|
281
|
+
window.print = () => (window.wasPrinted = 'yes');
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
await page.click('#test-button');
|
|
285
|
+
|
|
286
|
+
const wasPrinted = await page.evaluate(() => window.wasPrinted);
|
|
287
|
+
expect(wasPrinted).toBe('yes');
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
<div class="ons-grid ons-grid--flex ons-grid--vertical-center ons-grid--no-wrap@s">
|
|
6
6
|
<div class="ons-grid__col ons-col-auto ons-u-flex-shrink@s">
|
|
7
7
|
<h2 class="ons-call-to-action__heading ons-u-fs-r--b ons-u-di">{{ params.headingText }}</h2>
|
|
8
|
-
|
|
8
|
+
{% if params.paragraphText is defined and params.paragraphText %}
|
|
9
|
+
<p class="ons-call-to-action__text ons-u-di">{{ params.paragraphText }}</p>
|
|
10
|
+
{% endif %}
|
|
9
11
|
</div>
|
|
10
12
|
<div class="ons-grid__col ons-col-auto ons-u-flex-no-grow ons-u-mt-xs@xxs@s">
|
|
11
13
|
{{ onsButton({
|
|
@@ -0,0 +1,52 @@
|
|
|
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_CALL_TO_ACTION = {
|
|
9
|
+
headingText: 'Call to action heading.',
|
|
10
|
+
paragraphText: 'Descriptive text about call to action',
|
|
11
|
+
button: {
|
|
12
|
+
text: 'Start',
|
|
13
|
+
url: 'https://example.com/start',
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe('macro: call-to-action', () => {
|
|
18
|
+
it('passes jest-axe checks', async () => {
|
|
19
|
+
const $ = cheerio.load(renderComponent('call-to-action', EXAMPLE_CALL_TO_ACTION));
|
|
20
|
+
|
|
21
|
+
const results = await axe($.html());
|
|
22
|
+
expect(results).toHaveNoViolations();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('has the provided `headingText`', () => {
|
|
26
|
+
const $ = cheerio.load(renderComponent('call-to-action', EXAMPLE_CALL_TO_ACTION));
|
|
27
|
+
|
|
28
|
+
const headingText = $('.ons-call-to-action__heading')
|
|
29
|
+
.text()
|
|
30
|
+
.trim();
|
|
31
|
+
expect(headingText).toBe('Call to action heading.');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('has the provided `paragraphText`', () => {
|
|
35
|
+
const $ = cheerio.load(renderComponent('call-to-action', EXAMPLE_CALL_TO_ACTION));
|
|
36
|
+
|
|
37
|
+
const paragraphText = $('.ons-call-to-action__text')
|
|
38
|
+
.text()
|
|
39
|
+
.trim();
|
|
40
|
+
expect(paragraphText).toBe('Descriptive text about call to action');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('outputs the expected call-to-action button', () => {
|
|
44
|
+
const faker = templateFaker();
|
|
45
|
+
const buttonSpy = faker.spy('button');
|
|
46
|
+
|
|
47
|
+
faker.renderComponent('call-to-action', EXAMPLE_CALL_TO_ACTION);
|
|
48
|
+
|
|
49
|
+
expect(buttonSpy.occurrences[0]).toHaveProperty('text', 'Start');
|
|
50
|
+
expect(buttonSpy.occurrences[0]).toHaveProperty('url', 'https://example.com/start');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -4,28 +4,35 @@
|
|
|
4
4
|
|
|
5
5
|
{% set titleSize = params.titleSize | default('2') %}
|
|
6
6
|
|
|
7
|
-
<div class="ons-card" aria-
|
|
8
|
-
|
|
9
|
-
{%- if params.image -%}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<img class="ons-card__image ons-u-mb-s" height="200" width="303" srcset="{{ params.image.smallSrc }} 1x, {{ params.image.largeSrc }} 2x" src="{{ params.image.smallSrc }}" alt="{{ params.image.alt }}" loading="lazy">
|
|
15
|
-
|
|
16
|
-
<img class="ons-card__image ons-u-mb-s" height="100" width="303" srcset="{{ params.placeholderURL if params.placeholderURL is defined and params.placeholderURL }}/img/small/placeholder-card.png 1x, {{ params.placeholderURL if params.placeholderURL is defined and params.placeholderURL }}/img/large/placeholder-card.png 2x" src="{{ params.placeholderURL if params.placeholderURL is defined and params.placeholderURL }}/img/small/placeholder-card.png" alt="
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
7
|
+
<div class="ons-card" aria-describedBy="{{ params.textId }}">
|
|
8
|
+
|
|
9
|
+
{%- if params.image is defined and params.image -%}
|
|
10
|
+
{%- if params.url is defined and params.url -%}
|
|
11
|
+
<a href="{{ params.url }}" class="ons-card__link ons-u-db">
|
|
12
|
+
{%- endif -%}
|
|
13
|
+
{% if params.image.smallSrc is defined and params.image.smallSrc %}
|
|
14
|
+
<img class="ons-card__image ons-u-mb-s" height="200" width="303"{% if params.image.largeSrc is defined and params.image.largeSrc %} srcset="{{ params.image.smallSrc }} 1x, {{ params.image.largeSrc }} 2x"{% endif %} src="{{ params.image.smallSrc }}" alt="{{ params.image.alt }}" loading="lazy">
|
|
15
|
+
{% elif params.image == true or params.image.placeholderURL is defined %}
|
|
16
|
+
<img class="ons-card__image ons-u-mb-s" height="100" width="303" srcset="{{ params.image.placeholderURL if params.image.placeholderURL is defined and params.image.placeholderURL }}/img/small/placeholder-card.png 1x, {{ params.image.placeholderURL if params.image.placeholderURL is defined and params.image.placeholderURL }}/img/large/placeholder-card.png 2x" src="{{ params.image.placeholderURL if params.image.placeholderURL is defined and params.image.placeholderURL }}/img/small/placeholder-card.png" alt="" loading="lazy">
|
|
17
|
+
{% endif %}
|
|
18
|
+
|
|
19
|
+
<h{{ titleSize }} class="ons-card__title {{ params.titleClasses | default('ons-u-fs-m')}}" id="{{ params.id }}">
|
|
20
|
+
{{ params.title }}
|
|
21
|
+
</h{{ titleSize }}>
|
|
22
|
+
{%- if params.url is defined and params.url -%}
|
|
23
|
+
</a>
|
|
24
|
+
{%- endif -%}
|
|
24
25
|
|
|
25
26
|
{%- else -%}
|
|
26
27
|
|
|
27
|
-
<h{{ titleSize }} class="{{ params.titleClasses | default('ons-u-fs-m') }}" id="{{ params.id }}">
|
|
28
|
-
|
|
28
|
+
<h{{ titleSize }} class="ons-card__title {{ params.titleClasses | default('ons-u-fs-m') }}" id="{{ params.id }}">
|
|
29
|
+
{%- if params.url is defined and params.url -%}
|
|
30
|
+
<a class="ons-card__link" href="{{ params.url }}">
|
|
31
|
+
{%- endif -%}
|
|
32
|
+
{{ params.title }}
|
|
33
|
+
{%- if params.url is defined and params.url -%}
|
|
34
|
+
</a>
|
|
35
|
+
{%- endif -%}
|
|
29
36
|
</h{{ titleSize }}>
|
|
30
37
|
|
|
31
38
|
{%- endif -%}
|
|
@@ -0,0 +1,261 @@
|
|
|
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_CARD_WITHOUT_IMAGE = {
|
|
9
|
+
title: 'Example card title',
|
|
10
|
+
text: 'Example card text.',
|
|
11
|
+
textId: 'example-text-id',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const EXAMPLE_CARD_WITH_IMAGE = {
|
|
15
|
+
title: 'Example card title',
|
|
16
|
+
text: 'Example card text.',
|
|
17
|
+
textId: 'example-text-id',
|
|
18
|
+
image: {
|
|
19
|
+
smallSrc: 'example-small.png',
|
|
20
|
+
largeSrc: 'example-large.png',
|
|
21
|
+
alt: 'Example alt text',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE = {
|
|
26
|
+
title: 'Example card title',
|
|
27
|
+
text: 'Example card text.',
|
|
28
|
+
textId: 'example-text-id',
|
|
29
|
+
image: true,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE_WITH_PATH = {
|
|
33
|
+
title: 'Example card title',
|
|
34
|
+
text: 'Example card text.',
|
|
35
|
+
textId: 'example-text-id',
|
|
36
|
+
image: {
|
|
37
|
+
placeholderURL: '/placeholder-image-url',
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
describe('macro: card', () => {
|
|
42
|
+
describe('mode: without image', () => {
|
|
43
|
+
it('passes jest-axe checks', async () => {
|
|
44
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITHOUT_IMAGE));
|
|
45
|
+
|
|
46
|
+
const results = await axe($.html());
|
|
47
|
+
expect(results).toHaveNoViolations();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('has the provided `title` text', () => {
|
|
51
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITHOUT_IMAGE));
|
|
52
|
+
|
|
53
|
+
expect(
|
|
54
|
+
$('.ons-card__title')
|
|
55
|
+
.text()
|
|
56
|
+
.trim(),
|
|
57
|
+
).toBe('Example card title');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it.each([
|
|
61
|
+
[1, 'h1'],
|
|
62
|
+
[4, 'h4'],
|
|
63
|
+
])('has the correct element type for the provided `titleSize` (%i -> %s)', (titleSize, expectedTitleTag) => {
|
|
64
|
+
const $ = cheerio.load(
|
|
65
|
+
renderComponent('card', {
|
|
66
|
+
...EXAMPLE_CARD_WITHOUT_IMAGE,
|
|
67
|
+
titleSize,
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
expect(
|
|
72
|
+
$(`${expectedTitleTag}.ons-card__title`)
|
|
73
|
+
.text()
|
|
74
|
+
.trim(),
|
|
75
|
+
).toBe('Example card title');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('has the provided `text` accessible via the `textId` identifier', () => {
|
|
79
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITHOUT_IMAGE));
|
|
80
|
+
|
|
81
|
+
expect(
|
|
82
|
+
$('#example-text-id')
|
|
83
|
+
.text()
|
|
84
|
+
.trim(),
|
|
85
|
+
).toBe('Example card text.');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('renders the provided `itemsList` using the `list` component', () => {
|
|
89
|
+
const faker = templateFaker();
|
|
90
|
+
const listsSpy = faker.spy('lists');
|
|
91
|
+
|
|
92
|
+
faker.renderComponent('card', {
|
|
93
|
+
...EXAMPLE_CARD_WITHOUT_IMAGE,
|
|
94
|
+
itemsList: [{ text: 'Test item 1' }, { text: 'Test item 2' }],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(listsSpy.occurrences[0]).toEqual({
|
|
98
|
+
variants: 'dashed',
|
|
99
|
+
itemsList: [{ text: 'Test item 1' }, { text: 'Test item 2' }],
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('outputs a hyperlink with the provided `url`', () => {
|
|
104
|
+
const $ = cheerio.load(
|
|
105
|
+
renderComponent('card', {
|
|
106
|
+
...EXAMPLE_CARD_WITHOUT_IMAGE,
|
|
107
|
+
url: 'https://example.com',
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
expect($('.ons-card__link').attr('href')).toBe('https://example.com');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('mode: with image', () => {
|
|
116
|
+
it('passes jest-axe checks', async () => {
|
|
117
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_IMAGE));
|
|
118
|
+
|
|
119
|
+
const results = await axe($.html());
|
|
120
|
+
expect(results).toHaveNoViolations();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('has the provided `title` text', () => {
|
|
124
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_IMAGE));
|
|
125
|
+
|
|
126
|
+
expect(
|
|
127
|
+
$('.ons-card__title')
|
|
128
|
+
.text()
|
|
129
|
+
.trim(),
|
|
130
|
+
).toBe('Example card title');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it.each([
|
|
134
|
+
[1, 'h1'],
|
|
135
|
+
[4, 'h4'],
|
|
136
|
+
])('has the correct element type for the provided `titleSize` (%i -> %s)', (titleSize, expectedTitleTag) => {
|
|
137
|
+
const $ = cheerio.load(
|
|
138
|
+
renderComponent('card', {
|
|
139
|
+
...EXAMPLE_CARD_WITH_IMAGE,
|
|
140
|
+
titleSize,
|
|
141
|
+
}),
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
expect(
|
|
145
|
+
$(`${expectedTitleTag}.ons-card__title`)
|
|
146
|
+
.text()
|
|
147
|
+
.trim(),
|
|
148
|
+
).toBe('Example card title');
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('has the provided `text`', () => {
|
|
152
|
+
const $ = cheerio.load(
|
|
153
|
+
renderComponent('card', {
|
|
154
|
+
...EXAMPLE_CARD_WITH_IMAGE,
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
expect(
|
|
159
|
+
$('#example-text-id')
|
|
160
|
+
.text()
|
|
161
|
+
.trim(),
|
|
162
|
+
).toBe('Example card text.');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('outputs a hyperlink with the provided `url`', () => {
|
|
166
|
+
const $ = cheerio.load(
|
|
167
|
+
renderComponent('card', {
|
|
168
|
+
...EXAMPLE_CARD_WITH_IMAGE,
|
|
169
|
+
url: 'https://example.com',
|
|
170
|
+
}),
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
expect($('.ons-card__link').attr('href')).toBe('https://example.com');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
describe('with a custom image', () => {
|
|
177
|
+
it('outputs an `img` element', () => {
|
|
178
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_IMAGE));
|
|
179
|
+
|
|
180
|
+
expect($('.ons-card__image')[0].tagName).toBe('img');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('outputs an `img` element with the expected `srcset`', () => {
|
|
184
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_IMAGE));
|
|
185
|
+
|
|
186
|
+
expect($('.ons-card__image').attr('srcset')).toBe('example-small.png 1x, example-large.png 2x');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('outputs an `img` element with the expected `src`', () => {
|
|
190
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_IMAGE));
|
|
191
|
+
|
|
192
|
+
expect($('.ons-card__image').attr('src')).toBe('example-small.png');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('outputs an `img` element with the expected alt text', () => {
|
|
196
|
+
const $ = cheerio.load(
|
|
197
|
+
renderComponent('card', {
|
|
198
|
+
...EXAMPLE_CARD_WITH_IMAGE,
|
|
199
|
+
alt: 'Example alt text',
|
|
200
|
+
}),
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
expect($('.ons-card__image').attr('alt')).toBe('Example alt text');
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe('with a default placeholder image', () => {
|
|
208
|
+
it('outputs an `img` element', () => {
|
|
209
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE));
|
|
210
|
+
|
|
211
|
+
expect($('.ons-card__image')[0].tagName).toBe('img');
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('outputs an `img` element with the expected `srcset`', () => {
|
|
215
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE));
|
|
216
|
+
|
|
217
|
+
expect($('.ons-card__image').attr('srcset')).toBe('/img/small/placeholder-card.png 1x, /img/large/placeholder-card.png 2x');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('outputs an `img` element with the expected `src`', () => {
|
|
221
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE));
|
|
222
|
+
|
|
223
|
+
expect($('.ons-card__image').attr('src')).toBe('/img/small/placeholder-card.png');
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('outputs an `img` element with the expected empty alt text', () => {
|
|
227
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE));
|
|
228
|
+
|
|
229
|
+
expect($('.ons-card__image').attr('alt')).toBe('');
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe('with a default placeholder image with `placeholderURL`', () => {
|
|
234
|
+
it('outputs an `img` element', () => {
|
|
235
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE_WITH_PATH));
|
|
236
|
+
|
|
237
|
+
expect($('.ons-card__image')[0].tagName).toBe('img');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('outputs an `img` element with the expected `srcset`', () => {
|
|
241
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE_WITH_PATH));
|
|
242
|
+
|
|
243
|
+
expect($('.ons-card__image').attr('srcset')).toBe(
|
|
244
|
+
'/placeholder-image-url/img/small/placeholder-card.png 1x, /placeholder-image-url/img/large/placeholder-card.png 2x',
|
|
245
|
+
);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('outputs an `img` element with the expected `src`', () => {
|
|
249
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE_WITH_PATH));
|
|
250
|
+
|
|
251
|
+
expect($('.ons-card__image').attr('src')).toBe('/placeholder-image-url/img/small/placeholder-card.png');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('outputs an `img` element with the expected empty alt text', () => {
|
|
255
|
+
const $ = cheerio.load(renderComponent('card', EXAMPLE_CARD_WITH_PLACEHOLDER_IMAGE_WITH_PATH));
|
|
256
|
+
|
|
257
|
+
expect($('.ons-card__image').attr('alt')).toBe('');
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
});
|