@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,180 @@
|
|
|
1
|
+
import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
|
|
2
|
+
|
|
3
|
+
const EXAMPLE_RADIOS_PARAMS = {
|
|
4
|
+
name: 'contact-preference',
|
|
5
|
+
clearRadios: {
|
|
6
|
+
text: 'Clear selection',
|
|
7
|
+
url: '/',
|
|
8
|
+
ariaClearText: 'You can clear your answer by clicking the clear selection button under the radio buttons',
|
|
9
|
+
ariaClearedText: 'You have cleared your answer',
|
|
10
|
+
},
|
|
11
|
+
legend: 'How would you like us to contact you?',
|
|
12
|
+
legendClasses: 'ons-u-vh',
|
|
13
|
+
radios: [
|
|
14
|
+
{
|
|
15
|
+
id: 'email',
|
|
16
|
+
value: 'email',
|
|
17
|
+
label: {
|
|
18
|
+
text: 'Email',
|
|
19
|
+
},
|
|
20
|
+
other: {
|
|
21
|
+
id: 'email-other',
|
|
22
|
+
type: 'email',
|
|
23
|
+
label: {
|
|
24
|
+
text: 'Enter your email address',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'phone',
|
|
30
|
+
value: 'phone',
|
|
31
|
+
label: {
|
|
32
|
+
text: 'Phone',
|
|
33
|
+
},
|
|
34
|
+
other: {
|
|
35
|
+
id: 'tel-other',
|
|
36
|
+
type: 'tel',
|
|
37
|
+
label: {
|
|
38
|
+
text: 'Enter your phone number',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: 'text',
|
|
44
|
+
value: 'Open input test',
|
|
45
|
+
label: {
|
|
46
|
+
text: 'Text',
|
|
47
|
+
},
|
|
48
|
+
other: {
|
|
49
|
+
id: 'text-other',
|
|
50
|
+
type: 'text',
|
|
51
|
+
open: true,
|
|
52
|
+
label: {
|
|
53
|
+
text: 'Enter something else',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
describe('script: radios', () => {
|
|
61
|
+
beforeEach(async () => {
|
|
62
|
+
await setTestPage('/test', renderComponent('radios', EXAMPLE_RADIOS_PARAMS));
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('radios with other options should be given aria-expanded attributes', async () => {
|
|
66
|
+
const ariaExpandedOption1 = await page.$eval('#email', node => node.getAttribute('aria-expanded'));
|
|
67
|
+
expect(ariaExpandedOption1).toBe('false');
|
|
68
|
+
const ariaExpandedOption2 = await page.$eval('#phone', node => node.getAttribute('aria-expanded'));
|
|
69
|
+
expect(ariaExpandedOption2).toBe('false');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('radios with "open" other options should not be given aria-expanded attributes', async () => {
|
|
73
|
+
const hasAriaExpandedOption3 = await page.$eval('#text', node => node.hasAttribute('aria-expanded'));
|
|
74
|
+
expect(hasAriaExpandedOption3).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('a radio checked', () => {
|
|
78
|
+
beforeEach(async () => {
|
|
79
|
+
await page.click('#email');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('then the checked radio aria-expanded attribute should be set to true', async () => {
|
|
83
|
+
const ariaExpandedOption1 = await page.$eval('#email', node => node.getAttribute('aria-expanded'));
|
|
84
|
+
expect(ariaExpandedOption1).toBe('true');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('then the unchecked radio aria-expanded attribute should be set to false', async () => {
|
|
88
|
+
const ariaExpandedOption2 = await page.$eval('#phone', node => node.getAttribute('aria-expanded'));
|
|
89
|
+
expect(ariaExpandedOption2).toBe('false');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('then the unchecked radio aria-expanded attribute of "open" radio should not be set', async () => {
|
|
93
|
+
const hasAriaExpanded = await page.$eval('#text', node => node.hasAttribute('aria-expanded'));
|
|
94
|
+
expect(hasAriaExpanded).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('then the clear button should be visible', async () => {
|
|
98
|
+
const isHidden = await page.$eval('.ons-js-clear-btn', node => node.classList.contains('ons-u-db-no-js_enabled'));
|
|
99
|
+
expect(isHidden).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('then the aria live message should announce that the answer can be cleared', async () => {
|
|
103
|
+
const alertText = await page.$eval('.ons-js-clear-radio-alert', node => node.innerHTML);
|
|
104
|
+
expect(alertText).toBe('You can clear your answer by clicking the clear selection button under the radio buttons');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('and the radio selection is changed', () => {
|
|
108
|
+
beforeEach(async () => {
|
|
109
|
+
await page.click('#phone');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('then the checked radio aria-expanded attribute should be set to true', async () => {
|
|
113
|
+
const ariaExpandedOption2 = await page.$eval('#phone', node => node.getAttribute('aria-expanded'));
|
|
114
|
+
expect(ariaExpandedOption2).toBe('true');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('then the unchecked radio aria-expanded attribute should be set to false', async () => {
|
|
118
|
+
const ariaExpandedOption1 = await page.$eval('#email', node => node.getAttribute('aria-expanded'));
|
|
119
|
+
expect(ariaExpandedOption1).toBe('false');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('then the unchecked radio aria-expanded attribute of "open" radio should not be set', async () => {
|
|
123
|
+
const hasAriaExpanded = await page.$eval('#text', node => node.hasAttribute('aria-expanded'));
|
|
124
|
+
expect(hasAriaExpanded).toBe(false);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('the clear button is clicked', () => {
|
|
130
|
+
beforeEach(async () => {
|
|
131
|
+
await page.$eval('.ons-js-clear-btn', node => node.click());
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('then the clear button should not be visible', async () => {
|
|
135
|
+
const isHidden = await page.$eval('.ons-js-clear-btn', node => node.classList.contains('ons-u-db-no-js_enabled'));
|
|
136
|
+
expect(isHidden).toBe(true);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('then the aria live message should announce that the answer has been cleared', async () => {
|
|
140
|
+
const alertText = await page.$eval('.ons-js-clear-radio-alert', node => node.innerHTML);
|
|
141
|
+
expect(alertText).toBe('You have cleared your answer');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('then all radios should not be checked', async () => {
|
|
145
|
+
const checkedRadios = await page.$$eval('.ons-js-radio', nodes => nodes.map(node => node.checked));
|
|
146
|
+
expect(checkedRadios).not.toContain(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('then all other input fields should be empty', async () => {
|
|
150
|
+
const emailOtherValue = await page.$eval('#email-other', node => node.value);
|
|
151
|
+
expect(emailOtherValue).toBe('');
|
|
152
|
+
const telOtherValue = await page.$eval('#tel-other', node => node.value);
|
|
153
|
+
expect(telOtherValue).toBe('');
|
|
154
|
+
const textOtherValue = await page.$eval('#text-other', node => node.value);
|
|
155
|
+
expect(textOtherValue).toBe('');
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe('there is a visible input which is focused', () => {
|
|
160
|
+
beforeEach(async () => {
|
|
161
|
+
await page.focus('#text-other');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('then the radio button should be checked', async () => {
|
|
165
|
+
const isRadioChecked = await page.$eval('#text', node => node.checked);
|
|
166
|
+
expect(isRadioChecked).toBe(true);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('there is a visible input and the radio is checked', () => {
|
|
171
|
+
beforeEach(async () => {
|
|
172
|
+
await page.click('#text');
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('then the input should have a tab index of 0', async () => {
|
|
176
|
+
const tabIndex = await page.$eval('#text-other', node => node.getAttribute('tabindex'));
|
|
177
|
+
expect(tabIndex).toBe('0');
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
@@ -1,45 +1,38 @@
|
|
|
1
1
|
{% macro onsRelatedContent(params) %}
|
|
2
2
|
|
|
3
|
-
{%
|
|
4
|
-
|
|
5
|
-
{%
|
|
6
|
-
{% set classes = ' ' + params.classes %}
|
|
7
|
-
{% endif %}
|
|
3
|
+
{% if params is defined and params and params.classes is defined and params.classes %}
|
|
4
|
+
{% set classes = ' ' + params.classes %}
|
|
5
|
+
{% endif %}
|
|
8
6
|
|
|
9
7
|
<aside class="ons-related-content{{ classes }}" aria-label="{{ params.ariaLabel | default("Related content") }}">
|
|
10
8
|
|
|
11
9
|
<div class="ons-related-content__body">
|
|
12
|
-
|
|
13
10
|
{% if params.rows is defined and params.rows %}
|
|
14
|
-
|
|
15
11
|
{% for row in params.rows %}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
{% from "components/related-content/_section-macro.njk" import onsRelatedContentSection %}
|
|
13
|
+
{% call onsRelatedContentSection(
|
|
14
|
+
{
|
|
15
|
+
"title": row.title,
|
|
16
|
+
"id": row.id
|
|
17
|
+
}
|
|
18
|
+
) %}
|
|
20
19
|
<nav class="ons-related-content__navigation" aria-labelledby="{{ row.id }}">
|
|
20
|
+
{% from "components/lists/_macro.njk" import onsList %}
|
|
21
21
|
{{
|
|
22
22
|
onsList({
|
|
23
23
|
"variants": 'bare',
|
|
24
|
+
"iconType": row.iconType,
|
|
24
25
|
"iconPosition": row.iconPosition,
|
|
25
26
|
"iconSize": row.iconSize,
|
|
26
27
|
"itemsList": row.itemsList
|
|
27
28
|
})
|
|
28
29
|
}}
|
|
29
30
|
</nav>
|
|
30
|
-
|
|
31
|
+
{% endcall %}
|
|
31
32
|
{% endfor %}
|
|
32
|
-
|
|
33
33
|
{% else %}
|
|
34
|
-
|
|
35
|
-
<h2 class="ons-related-content__title ons-u-fs-r--b ons-u-mb-xs">{{ params.title }}</h2>
|
|
36
|
-
|
|
37
|
-
<div class="ons-related-content__body">
|
|
38
|
-
{{ (params.body if params else "") | safe }}{{ caller() if caller }}
|
|
39
|
-
</div>
|
|
40
|
-
|
|
34
|
+
{{ caller() if caller }}
|
|
41
35
|
{% endif %}
|
|
42
|
-
|
|
43
36
|
</div>
|
|
44
37
|
|
|
45
38
|
</aside>
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/** @jest-environment jsdom */
|
|
2
|
+
|
|
3
|
+
import * as cheerio from 'cheerio';
|
|
4
|
+
|
|
5
|
+
import axe from '../../tests/helpers/axe';
|
|
6
|
+
import { mapAll } from '../../tests/helpers/cheerio';
|
|
7
|
+
import { renderComponent, templateFaker } from '../../tests/helpers/rendering';
|
|
8
|
+
|
|
9
|
+
const EXAMPLE_RELATED_CONTENT_GENERAL = {
|
|
10
|
+
title: 'Related information',
|
|
11
|
+
id: 'related-general-content',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const EXAMPLE_RELATED_CONTENT_LINKS = {
|
|
15
|
+
rows: [
|
|
16
|
+
{
|
|
17
|
+
id: 'related-articles',
|
|
18
|
+
title: 'Related articles',
|
|
19
|
+
iconPosition: 'before',
|
|
20
|
+
iconSize: 'xl',
|
|
21
|
+
itemsList: [
|
|
22
|
+
{ text: 'First', url: '/article/first' },
|
|
23
|
+
{ text: 'Second', url: '/article/second' },
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'related-links',
|
|
28
|
+
title: 'Related links',
|
|
29
|
+
iconPosition: 'after',
|
|
30
|
+
iconSize: 'xxl',
|
|
31
|
+
itemsList: [
|
|
32
|
+
{ text: 'A', url: '/article/a' },
|
|
33
|
+
{ text: 'B', url: '/article/b' },
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
describe('macro: related-content', () => {
|
|
40
|
+
describe.each([
|
|
41
|
+
['general content', EXAMPLE_RELATED_CONTENT_GENERAL],
|
|
42
|
+
['list of links', EXAMPLE_RELATED_CONTENT_LINKS],
|
|
43
|
+
])('mode: %s', (_, params) => {
|
|
44
|
+
it('passes jest-axe checks', async () => {
|
|
45
|
+
const $ = cheerio.load(renderComponent('related-content', params));
|
|
46
|
+
|
|
47
|
+
const results = await axe($.html());
|
|
48
|
+
expect(results).toHaveNoViolations();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('has a default `aria-label` of "Related content"', () => {
|
|
52
|
+
const $ = cheerio.load(renderComponent('related-content', params));
|
|
53
|
+
|
|
54
|
+
expect($('.ons-related-content').attr('aria-label')).toBe('Related content');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('has the provided `aria-label`', () => {
|
|
58
|
+
const $ = cheerio.load(
|
|
59
|
+
renderComponent('related-content', {
|
|
60
|
+
...params,
|
|
61
|
+
ariaLabel: 'Related articles',
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
expect($('.ons-related-content').attr('aria-label')).toBe('Related articles');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('has additionally provided style classes', () => {
|
|
69
|
+
const $ = cheerio.load(
|
|
70
|
+
renderComponent('related-content', {
|
|
71
|
+
...params,
|
|
72
|
+
classes: 'extra-class another-extra-class',
|
|
73
|
+
}),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
expect($('.ons-related-content').hasClass('extra-class')).toBe(true);
|
|
77
|
+
expect($('.ons-related-content').hasClass('another-extra-class')).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('mode: general content', () => {
|
|
82
|
+
it('calls with content', () => {
|
|
83
|
+
const $ = cheerio.load(renderComponent('related-content', { EXAMPLE_RELATED_CONTENT_GENERAL }, 'Example content...'));
|
|
84
|
+
|
|
85
|
+
const content = $('.ons-related-content__body')
|
|
86
|
+
.text()
|
|
87
|
+
.trim();
|
|
88
|
+
expect(content).toEqual(expect.stringContaining('Example content...'));
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('mode: list of links', () => {
|
|
93
|
+
it('renders the expected output using the related-content/section macro', () => {
|
|
94
|
+
const faker = templateFaker();
|
|
95
|
+
const sectionSpy = faker.spy('related-content/section');
|
|
96
|
+
|
|
97
|
+
faker.renderComponent('related-content', EXAMPLE_RELATED_CONTENT_LINKS);
|
|
98
|
+
|
|
99
|
+
expect(sectionSpy.occurrences[0]).toHaveProperty('title', 'Related articles');
|
|
100
|
+
expect(sectionSpy.occurrences[0]).toHaveProperty('id', 'related-articles');
|
|
101
|
+
expect(sectionSpy.occurrences[1]).toHaveProperty('title', 'Related links');
|
|
102
|
+
expect(sectionSpy.occurrences[1]).toHaveProperty('id', 'related-links');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('has the `aria-labelledby` attribute for each section of links', () => {
|
|
106
|
+
const $ = cheerio.load(renderComponent('related-content', EXAMPLE_RELATED_CONTENT_LINKS));
|
|
107
|
+
|
|
108
|
+
const values = mapAll($('.ons-related-content__navigation'), node => node.attr('aria-labelledby'));
|
|
109
|
+
expect(values).toEqual(['related-articles', 'related-links']);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('renders the expected list items using the list macro', () => {
|
|
113
|
+
const faker = templateFaker();
|
|
114
|
+
const listsSpy = faker.spy('lists');
|
|
115
|
+
|
|
116
|
+
faker.renderComponent('related-content', EXAMPLE_RELATED_CONTENT_LINKS);
|
|
117
|
+
|
|
118
|
+
expect(listsSpy.occurrences[0]).toHaveProperty('iconPosition', 'before');
|
|
119
|
+
expect(listsSpy.occurrences[0]).toHaveProperty('iconSize', 'xl');
|
|
120
|
+
expect(listsSpy.occurrences[0]).toHaveProperty('itemsList', [
|
|
121
|
+
{ text: 'First', url: '/article/first' },
|
|
122
|
+
{ text: 'Second', url: '/article/second' },
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
expect(listsSpy.occurrences[1]).toHaveProperty('iconPosition', 'after');
|
|
126
|
+
expect(listsSpy.occurrences[1]).toHaveProperty('iconSize', 'xxl');
|
|
127
|
+
expect(listsSpy.occurrences[1]).toHaveProperty('itemsList', [
|
|
128
|
+
{ text: 'A', url: '/article/a' },
|
|
129
|
+
{ text: 'B', url: '/article/b' },
|
|
130
|
+
]);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{% macro onsRelatedContentSection(params) %}
|
|
2
|
+
<div class="ons-related-content__section">
|
|
3
|
+
{% if params.title %}
|
|
4
|
+
<h2 class="ons-related-content__title ons-u-fs-r--b ons-u-mb-xs" {% if params.id %}id="{{ params.id }}"{% endif %}>{{ params.title }}</h2>
|
|
5
|
+
{% endif %}
|
|
6
|
+
<div class="ons-related-content__content">
|
|
7
|
+
{{ caller() if caller }}
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
{% endmacro %}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** @jest-environment jsdom */
|
|
2
|
+
|
|
3
|
+
import * as cheerio from 'cheerio';
|
|
4
|
+
|
|
5
|
+
import axe from '../../tests/helpers/axe';
|
|
6
|
+
import { renderComponent } from '../../tests/helpers/rendering';
|
|
7
|
+
|
|
8
|
+
const EXAMPLE_RELATED_SECTION_CONTENT = {
|
|
9
|
+
title: 'Related information',
|
|
10
|
+
id: 'related-general-content',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
describe('macro: related-content/section', () => {
|
|
14
|
+
it('passes jest-axe checks', async () => {
|
|
15
|
+
const $ = cheerio.load(renderComponent('related-content/section', EXAMPLE_RELATED_SECTION_CONTENT));
|
|
16
|
+
|
|
17
|
+
const results = await axe($.html());
|
|
18
|
+
expect(results).toHaveNoViolations();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('has the provided `title` text', () => {
|
|
22
|
+
const $ = cheerio.load(renderComponent('related-content/section', EXAMPLE_RELATED_SECTION_CONTENT));
|
|
23
|
+
expect(
|
|
24
|
+
$('.ons-related-content__title')
|
|
25
|
+
.text()
|
|
26
|
+
.trim(),
|
|
27
|
+
).toEqual('Related information');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('has the `id` attribute for the title', () => {
|
|
31
|
+
const $ = cheerio.load(renderComponent('related-content/section', EXAMPLE_RELATED_SECTION_CONTENT));
|
|
32
|
+
expect($('#related-general-content').length).toBe(1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('has the provided content', () => {
|
|
36
|
+
const $ = cheerio.load(renderComponent('related-content/section', { EXAMPLE_RELATED_SECTION_CONTENT }, 'Example content...'));
|
|
37
|
+
|
|
38
|
+
const content = $('.ons-related-content__content')
|
|
39
|
+
.text()
|
|
40
|
+
.trim();
|
|
41
|
+
expect(content).toEqual(expect.stringContaining('Example content...'));
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
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_RELATIONSHIPS = {
|
|
9
|
+
playback: "Amanda Bloggs is Joe Bloggs' <em>…</em>",
|
|
10
|
+
name: 'relationship',
|
|
11
|
+
dontWrap: true,
|
|
12
|
+
legendIsQuestionTitle: true,
|
|
13
|
+
radios: [
|
|
14
|
+
{
|
|
15
|
+
id: 'grandparent',
|
|
16
|
+
value: 'grandparent',
|
|
17
|
+
label: {
|
|
18
|
+
text: 'Grandparent',
|
|
19
|
+
},
|
|
20
|
+
attributes: {
|
|
21
|
+
'data-title': 'Thinking of Joe Bloggs, Amanda Bloggs is their <em>grandparents</em>',
|
|
22
|
+
'data-playback': "Amanda Bloggs is Joe Bloggs' <em>grandparents</em>",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: 'other-relation',
|
|
27
|
+
value: 'other-relation',
|
|
28
|
+
label: {
|
|
29
|
+
text: 'Other relation',
|
|
30
|
+
},
|
|
31
|
+
attributes: {
|
|
32
|
+
'data-title': 'Thinking of Joe Bloggs, Amanda Bloggs is their <em>other relation</em>',
|
|
33
|
+
'data-playback': "Amanda Bloggs is Joe Bloggs' <em>other relation</em>",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'unrelated',
|
|
38
|
+
value: 'unrelated',
|
|
39
|
+
label: {
|
|
40
|
+
text: 'Unrelated',
|
|
41
|
+
description: 'Including foster child',
|
|
42
|
+
},
|
|
43
|
+
attributes: {
|
|
44
|
+
'data-title': 'Thinking of Joe Bloggs, Amanda Bloggs is <em>unrelated</em> to Joe Bloggs',
|
|
45
|
+
'data-playback': 'Amanda Bloggs is <em>unrelated</em> to Joe Bloggs',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
describe('macro: relationships', () => {
|
|
52
|
+
it('passes jest-axe checks', async () => {
|
|
53
|
+
const $ = cheerio.load(renderComponent('relationships', EXAMPLE_RELATIONSHIPS));
|
|
54
|
+
|
|
55
|
+
const results = await axe($.html());
|
|
56
|
+
expect(results).toHaveNoViolations();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('has the expected `id` attribute', () => {
|
|
60
|
+
const $ = cheerio.load(
|
|
61
|
+
renderComponent('relationships', {
|
|
62
|
+
...EXAMPLE_RELATIONSHIPS,
|
|
63
|
+
id: 'example-relationships',
|
|
64
|
+
}),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
expect($('.ons-relationships').attr('id')).toBe('example-relationships');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('has additionally provided style classes', () => {
|
|
71
|
+
const $ = cheerio.load(
|
|
72
|
+
renderComponent('relationships', {
|
|
73
|
+
...EXAMPLE_RELATIONSHIPS,
|
|
74
|
+
classes: 'extra-class another-extra-class',
|
|
75
|
+
}),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
expect($('.ons-relationships').hasClass('extra-class')).toBe(true);
|
|
79
|
+
expect($('.ons-relationships').hasClass('another-extra-class')).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('has the provided `playback` text', () => {
|
|
83
|
+
const $ = cheerio.load(renderComponent('relationships', EXAMPLE_RELATIONSHIPS));
|
|
84
|
+
|
|
85
|
+
const playbackContent = $('.ons-relationships__playback')
|
|
86
|
+
.html()
|
|
87
|
+
.trim();
|
|
88
|
+
expect(playbackContent).toBe("Amanda Bloggs is Joe Bloggs' <em>…</em>");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('has playback paragraph hidden initially', async () => {
|
|
92
|
+
const $ = cheerio.load(renderComponent('relationships', EXAMPLE_RELATIONSHIPS));
|
|
93
|
+
|
|
94
|
+
expect($('.ons-relationships__playback').hasClass('ons-u-d-no')).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('renders the expected radio items the radios macro', () => {
|
|
98
|
+
const faker = templateFaker();
|
|
99
|
+
const radiosSpy = faker.spy('radios');
|
|
100
|
+
|
|
101
|
+
faker.renderComponent('relationships', EXAMPLE_RELATIONSHIPS);
|
|
102
|
+
|
|
103
|
+
expect(radiosSpy.occurrences[0]).toHaveProperty('name', 'relationship');
|
|
104
|
+
expect(radiosSpy.occurrences[0]).toHaveProperty('dontWrap', true);
|
|
105
|
+
expect(radiosSpy.occurrences[0]).toHaveProperty('legendIsQuestionTitle', true);
|
|
106
|
+
expect(radiosSpy.occurrences[0]).toHaveProperty('radios', EXAMPLE_RELATIONSHIPS.radios);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
|
|
2
|
+
|
|
3
|
+
const EXAMPLE_RELATIONSHIPS = {
|
|
4
|
+
dontWrap: true,
|
|
5
|
+
playback: "Amanda Bloggs is Joe Bloggs' <em>…</em>",
|
|
6
|
+
name: 'relationship',
|
|
7
|
+
radios: [
|
|
8
|
+
{
|
|
9
|
+
id: 'grandparent',
|
|
10
|
+
value: 'grandparent',
|
|
11
|
+
label: {
|
|
12
|
+
text: 'Grandparent',
|
|
13
|
+
},
|
|
14
|
+
attributes: {
|
|
15
|
+
'data-title': 'Thinking of Joe Bloggs, Amanda Bloggs is their <em>grandparents</em>',
|
|
16
|
+
'data-playback': "Amanda Bloggs is Joe Bloggs' <em>grandparents</em>",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 'other-relation',
|
|
21
|
+
value: 'other-relation',
|
|
22
|
+
label: {
|
|
23
|
+
text: 'Other relation',
|
|
24
|
+
},
|
|
25
|
+
attributes: {
|
|
26
|
+
'data-title': 'Thinking of Joe Bloggs, Amanda Bloggs is their <em>other relation</em>',
|
|
27
|
+
'data-playback': "Amanda Bloggs is Joe Bloggs' <em>other relation</em>",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'unrelated',
|
|
32
|
+
value: 'unrelated',
|
|
33
|
+
label: {
|
|
34
|
+
text: 'Unrelated',
|
|
35
|
+
description: 'Including foster child',
|
|
36
|
+
},
|
|
37
|
+
attributes: {
|
|
38
|
+
'data-title': 'Thinking of Joe Bloggs, Amanda Bloggs is <em>unrelated</em> to Joe Bloggs',
|
|
39
|
+
'data-playback': 'Amanda Bloggs is <em>unrelated</em> to Joe Bloggs',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
describe('script: relationships', () => {
|
|
46
|
+
beforeEach(async () => {
|
|
47
|
+
await setTestPage(
|
|
48
|
+
'/test',
|
|
49
|
+
renderComponent(
|
|
50
|
+
'question',
|
|
51
|
+
{
|
|
52
|
+
title: 'Thinking of Joe Bloggs, Amanda Bloggs is their <em>…</em>',
|
|
53
|
+
readDescriptionFirst: true,
|
|
54
|
+
legendIsQuestionTitle: true,
|
|
55
|
+
legendTitleClasses: 'ons-js-relationships-legend',
|
|
56
|
+
},
|
|
57
|
+
[renderComponent('relationships', EXAMPLE_RELATIONSHIPS)],
|
|
58
|
+
),
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('when the component initialises', () => {
|
|
63
|
+
it('then the playback paragraph should become visible', async () => {
|
|
64
|
+
const hasHideClass = await page.$eval('.ons-relationships__playback', node => node.classList.contains('ons-u-d-no'));
|
|
65
|
+
expect(hasHideClass).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('when the user selects a relationship', () => {
|
|
70
|
+
beforeEach(async () => {
|
|
71
|
+
await page.click('#other-relation');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('the question title should be changed to reflect the relationship', async () => {
|
|
75
|
+
const headingText = await page.$eval('h1', element => element.innerHTML);
|
|
76
|
+
expect(headingText.trim()).toBe('Thinking of Joe Bloggs, Amanda Bloggs is their <em>other relation</em>');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('the playback should be changed to reflect the relationship', async () => {
|
|
80
|
+
const playbackText = await page.$eval('.ons-relationships__playback', element => element.innerHTML);
|
|
81
|
+
expect(playbackText.trim()).toBe("Amanda Bloggs is Joe Bloggs' <em>other relation</em>");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{% macro onsReply(params) %}
|
|
2
2
|
{% from "components/textarea/_macro.njk" import onsTextarea %}
|
|
3
3
|
{% from "components/button/_macro.njk" import onsButton %}
|
|
4
|
-
<div class="ons-js-reply">
|
|
4
|
+
<div class="ons-reply ons-js-reply">
|
|
5
5
|
{{
|
|
6
6
|
onsTextarea({
|
|
7
7
|
"id": params.textarea.id,
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
}}
|
|
24
24
|
</div>
|
|
25
25
|
<div class="ons-grid__col ons-u-ml-m">
|
|
26
|
-
<a href="{{ params.closeLinkUrl }}">{{ params.closeLinkText }}</a>
|
|
26
|
+
<a class="ons-reply__link" href="{{ params.closeLinkUrl }}">{{ params.closeLinkText }}</a>
|
|
27
27
|
</div>
|
|
28
28
|
</div>
|
|
29
29
|
</div>
|