@ons/design-system 50.0.0 → 52.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/_macro.njk +5 -5
- 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.spec.js +60 -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/_macro.njk +12 -49
- package/components/footer/_macro.spec.js +549 -0
- package/components/header/_macro.njk +3 -3
- package/components/header/_macro.spec.js +562 -0
- package/components/hero/_hero.scss +0 -3
- package/components/hero/_macro.njk +4 -4
- package/components/hero/_macro.spec.js +224 -0
- package/components/icons/_macro.njk +15 -15
- 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/_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.spec.js +129 -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.js +0 -16
- 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 +6 -6
- package/components/navigation/_macro.spec.js +327 -0
- 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 +1 -0
- package/components/related-content/_macro.spec.js +142 -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 +2 -2
- 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 +1 -1
- package/css/main.css +1 -1
- package/js/cookies-settings.spec.js +154 -0
- package/package.json +10 -23
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +2 -2
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
|
|
2
|
+
|
|
3
|
+
const SCREEN_READER_TIMEOUT_DELAY = 300;
|
|
4
|
+
|
|
5
|
+
const EXAMPLE_MUTUALLY_EXCLUSIVE_TEXTAREA_PARAMS = {
|
|
6
|
+
id: 'feedback',
|
|
7
|
+
name: 'feedback',
|
|
8
|
+
width: '30',
|
|
9
|
+
legend: 'What do you think of this service?',
|
|
10
|
+
label: {
|
|
11
|
+
text: 'Enter your feedback',
|
|
12
|
+
description: 'For example describe any difficulties you experienced in the use of this service',
|
|
13
|
+
},
|
|
14
|
+
charCheckLimit: {
|
|
15
|
+
limit: 200,
|
|
16
|
+
charCountSingular: 'You have {x} character remaining',
|
|
17
|
+
charCountPlural: 'You have {x} characters remaining',
|
|
18
|
+
},
|
|
19
|
+
mutuallyExclusive: {
|
|
20
|
+
or: 'Or',
|
|
21
|
+
deselectMessage: 'Selecting this will clear your feedback',
|
|
22
|
+
deselectGroupAdjective: 'cleared',
|
|
23
|
+
deselectExclusiveOptionAdjective: 'deselected',
|
|
24
|
+
exclusiveOptions: [
|
|
25
|
+
{
|
|
26
|
+
id: 'feedback-exclusive-option',
|
|
27
|
+
name: 'no-feedback',
|
|
28
|
+
value: 'no-feedback',
|
|
29
|
+
label: {
|
|
30
|
+
text: 'I dont want to provide feedback',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const FAKE_TEXTAREA_INPUT = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
|
|
38
|
+
|
|
39
|
+
describe('script: mutually-exclusive', () => {
|
|
40
|
+
describe('textarea', () => {
|
|
41
|
+
beforeEach(async () => {
|
|
42
|
+
await setTestPage('/test', renderComponent('textarea', EXAMPLE_MUTUALLY_EXCLUSIVE_TEXTAREA_PARAMS));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('Given the user populated the textarea', () => {
|
|
46
|
+
beforeEach(async () => {
|
|
47
|
+
await page.type('#feedback', FAKE_TEXTAREA_INPUT);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('when the user clicks the mutually exclusive option', () => {
|
|
51
|
+
beforeEach(async () => {
|
|
52
|
+
await page.click('#feedback-exclusive-option');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('then the mutually exclusive option should be checked', async () => {
|
|
56
|
+
const isChecked = await page.$eval('#feedback-exclusive-option', node => node.checked);
|
|
57
|
+
expect(isChecked).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('then the textarea should be cleared', async () => {
|
|
61
|
+
const textareaValue = await page.$eval('#feedback', node => node.value);
|
|
62
|
+
expect(textareaValue).toBe('');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('then the characters remaining readout should be reset', async () => {
|
|
66
|
+
const limitText = await page.$eval('#feedback-lim-remaining', node => node.textContent);
|
|
67
|
+
expect(limitText).toBe('You have 200 characters remaining');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('then the aria alert should tell the user that the textarea has been cleared', async () => {
|
|
71
|
+
await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
|
|
72
|
+
|
|
73
|
+
const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
|
|
74
|
+
expect(alertText).toBe('Enter your feedback cleared.');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('Given the user has checked the mutually exclusive exclusiveOption', () => {
|
|
80
|
+
beforeEach(async () => {
|
|
81
|
+
await page.click('#feedback-exclusive-option');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('when the user populates the textarea', () => {
|
|
85
|
+
beforeEach(async () => {
|
|
86
|
+
await page.type('#feedback', FAKE_TEXTAREA_INPUT);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('then the exclusive option should be unchecked', async () => {
|
|
90
|
+
const isChecked = await page.$eval('#feedback-exclusive-option', node => node.checked);
|
|
91
|
+
expect(isChecked).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('then the aria alert should tell the user that the exclusive option has been unchecked', async () => {
|
|
95
|
+
await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
|
|
96
|
+
|
|
97
|
+
const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
|
|
98
|
+
expect(alertText).toBe('I dont want to provide feedback deselected.');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe('Given the user has not populated the textarea or checked the exclusive option', () => {
|
|
104
|
+
describe('when the user populates the textarea', () => {
|
|
105
|
+
beforeEach(async () => {
|
|
106
|
+
await page.type('#feedback', FAKE_TEXTAREA_INPUT);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('then the aria alert shouldnt say anything', async () => {
|
|
110
|
+
await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
|
|
111
|
+
|
|
112
|
+
const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
|
|
113
|
+
expect(alertText).toBe('');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('when the user clicks the mutually exclusive option', () => {
|
|
118
|
+
beforeEach(async () => {
|
|
119
|
+
await page.click('#feedback-exclusive-option');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('then the aria alert shouldnt say anything', async () => {
|
|
123
|
+
await page.waitForTimeout(SCREEN_READER_TIMEOUT_DELAY);
|
|
124
|
+
|
|
125
|
+
const alertText = await page.$eval('.ons-js-exclusive-alert', node => node.textContent);
|
|
126
|
+
expect(alertText).toBe('');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
}) }}
|
|
32
32
|
</div>
|
|
33
33
|
{% endif %}
|
|
34
|
-
<nav class="ons-navigation ons-js-navigation" id="{{ params.id }}" aria-label="{{ params.ariaLabel | default("Main menu") }}" data-analytics="header-navigation">
|
|
34
|
+
<nav class="ons-navigation ons-navigation--main ons-js-navigation" id="{{ params.id }}" aria-label="{{ params.ariaLabel | default("Main menu") }}" data-analytics="header-navigation">
|
|
35
35
|
<ul class="ons-navigation__list">
|
|
36
36
|
{% for item in (params.itemsList if params.itemsList is iterable else params.itemsList.items()) %}
|
|
37
37
|
<li class="ons-navigation__item {{ item.classes }}{{ ' ons-navigation__item--active' if (item.url == params.currentPath) or (item.url != (params.siteBasePath | default('/')) and item.url in params.currentPath) }}">
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
<div class="ons-container ons-container--gutterless@xxs@l{{ ' ons-container--full-width' if params.fullWidth }}{{ ' ons-container--wide' if params.wide }}">
|
|
48
48
|
<ul class="ons-navigation__list ons-navigation__list">
|
|
49
49
|
{% for item in (params.subNavigation.itemsList if params.subNavigation.itemsList is iterable else params.subNavigation.itemsList.items()) %}
|
|
50
|
-
<li class="ons-navigation__item
|
|
50
|
+
<li class="ons-navigation__item {{ item.classes }}{{ ' ons-navigation__item--active' if (item.url == params.subNavigation.currentPath) or (item.url != (params.subNavigation.siteBasePath | default('/')) and item.url in params.subNavigation.currentPath) }}">
|
|
51
51
|
<a class="ons-navigation__link ons-navigation__link" href="{{ item.url }}" {% if item.id is defined and item.id %}id="{{ item.id }}" {% endif %}>{{ item.title }}</a>
|
|
52
52
|
</li>
|
|
53
53
|
{% endfor %}
|
|
@@ -66,19 +66,19 @@
|
|
|
66
66
|
"aria-expanded": "false"
|
|
67
67
|
}
|
|
68
68
|
}) }}
|
|
69
|
-
<nav class="ons-navigation ons-navigation--sub-mobile ons-u-d-no
|
|
69
|
+
<nav class="ons-navigation ons-navigation--sub-mobile ons-u-d-no ons-js-secondary-nav ons-u-mt-xs" id="{{ params.subNavigation.id }}--mobile" aria-hidden="true" aria-label="{{ params.subNavigation.ariaLabel | default("Section menu") }}" data-analytics="header-section-navigation">
|
|
70
70
|
<div class="ons-container ons-container--gutterless@xxs@l{{ ' ons-container--full-width' if params.fullWidth }}{{ ' ons-container--wide' if params.wide }}">
|
|
71
|
-
<ul class="ons-navigation__list">
|
|
71
|
+
<ul class="ons-navigation__list ons-navigation__list--parent">
|
|
72
72
|
<li class="ons-navigation__item">
|
|
73
73
|
<a class="ons-navigation__link" href="{{ params.subNavigation.overviewURL }}">{{ params.subNavigation.overviewText | default('Overview') }}</a>
|
|
74
74
|
</li>
|
|
75
75
|
{% for item in (params.subNavigation.itemsList if params.subNavigation.itemsList is iterable else params.subNavigation.itemsList.items()) %}
|
|
76
76
|
<li class="ons-navigation__item {{ ' ons-navigation__item--active' if (item.url == params.subNavigation.currentPath) or (item.url != (params.subNavigation.siteBasePath | default('/')) and item.url in params.subNavigation.currentPath) }}">
|
|
77
|
-
<a class="ons-navigation__link" href="{{ item.url }}" {% if item.id is defined and item.id %}id="{{ item.id }}" {% endif %}>{{ item.title }}</a>
|
|
77
|
+
<a class="ons-navigation__link" href="{{ item.url }}" {% if item.id is defined and item.id %}id="{{ item.id }}--mobile" {% endif %}>{{ item.title }}</a>
|
|
78
78
|
{% if item.sections %}
|
|
79
79
|
{% for section in item.sections %}
|
|
80
80
|
{% if section.sectionTitle %}<h3 class="ons-navigation__list-header">{{ section.sectionTitle }}</h3>{% endif %}
|
|
81
|
-
<ul class="ons-navigation__list ons-list--dashed ons-u-ml-s ons-u-mt-xs">
|
|
81
|
+
<ul class="ons-navigation__list ons-navigation__list--child ons-list--dashed ons-u-ml-s ons-u-mt-xs">
|
|
82
82
|
{% for child in section.children %}
|
|
83
83
|
<li class="ons-navigation__item ons-list__item {{ ' ons-navigation__item--active' if (child.url == params.subNavigation.currentPath) or (child.url != (params.subNavigation.sitsiteBasePatheBasePath | default('/')) and child.url in params.subNavigation.currentPath) }}">
|
|
84
84
|
<a class="ons-navigation__link ons-navigation__link--section" href="{{ child.url }}" {% if child.id is defined and child.id %}id="{{ child.id }}" {% endif %}>{{ child.title }}</a>
|
|
@@ -0,0 +1,327 @@
|
|
|
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
|
+
import { mapAll } from '../../tests/helpers/cheerio';
|
|
8
|
+
|
|
9
|
+
const PARAMS = {
|
|
10
|
+
id: 'main-nav',
|
|
11
|
+
ariaLabel: 'Main menu',
|
|
12
|
+
currentPath: '#1',
|
|
13
|
+
currentPageTitle: 'Main nav item 2',
|
|
14
|
+
itemsList: [
|
|
15
|
+
{
|
|
16
|
+
title: 'Main nav item 1',
|
|
17
|
+
url: '#0',
|
|
18
|
+
classes: 'custom-class-main-item-1',
|
|
19
|
+
id: 'main-item-1',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
title: 'Main nav item 2',
|
|
23
|
+
url: '#1',
|
|
24
|
+
classes: 'custom-class-main-item-2',
|
|
25
|
+
id: 'main-item-2',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
subNavigation: {
|
|
29
|
+
id: 'sub-nav',
|
|
30
|
+
overviewURL: '#overview',
|
|
31
|
+
overviewText: 'Overview',
|
|
32
|
+
ariaLabel: 'Section menu',
|
|
33
|
+
currentPath: '#1',
|
|
34
|
+
itemsList: [
|
|
35
|
+
{
|
|
36
|
+
title: 'Sub nav item 1',
|
|
37
|
+
url: '#0',
|
|
38
|
+
classes: 'custom-class-sub-item-1',
|
|
39
|
+
id: 'sub-item-1',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
title: 'Sub nav item 2',
|
|
43
|
+
url: '#1',
|
|
44
|
+
classes: 'custom-class-sub-item-2',
|
|
45
|
+
id: 'sub-item-2',
|
|
46
|
+
sections: [
|
|
47
|
+
{
|
|
48
|
+
sectionTitle: 'Section 1',
|
|
49
|
+
children: [
|
|
50
|
+
{
|
|
51
|
+
title: 'Child item 1',
|
|
52
|
+
url: '#0',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
title: 'Child item 2',
|
|
56
|
+
url: '#1',
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const SITE_SEARCH_AUTOSUGGEST = {
|
|
67
|
+
label: 'Search the design system',
|
|
68
|
+
instructions:
|
|
69
|
+
"Use up and down keys to navigate results once you've typed more than two characters. Use the enter key to select a result. Touch device users, explore by touch or with swipe gestures.",
|
|
70
|
+
ariaYouHaveSelected: 'You have selected',
|
|
71
|
+
ariaMinChars: 'Enter 3 or more characters for results.',
|
|
72
|
+
ariaResultsLabel: 'Search results',
|
|
73
|
+
ariaOneResult: 'There is one result available.',
|
|
74
|
+
ariaNResults: 'There are {n} results available.',
|
|
75
|
+
ariaLimitedResults: 'Results have been limited to 10 results. Type more characters to improve your search',
|
|
76
|
+
moreResults: 'Continue entering to improve results',
|
|
77
|
+
resultsTitle: 'Search results',
|
|
78
|
+
autosuggestData: '/search-index.json',
|
|
79
|
+
noResults: 'No results found',
|
|
80
|
+
typeMore: 'Continue entering to get results',
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
describe('macro: navigation', () => {
|
|
84
|
+
describe('level: container', () => {
|
|
85
|
+
it('passes jest-axe checks', async () => {
|
|
86
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
87
|
+
|
|
88
|
+
const results = await axe($.html());
|
|
89
|
+
expect(results).toHaveNoViolations();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('has the correct container if `fullWidth`', () => {
|
|
93
|
+
const $ = cheerio.load(renderComponent('navigation', { ...PARAMS, fullWidth: true }));
|
|
94
|
+
|
|
95
|
+
expect($('.ons-container').hasClass('ons-container--full-width')).toBe(true);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('has the correct container if `wide`', () => {
|
|
99
|
+
const $ = cheerio.load(renderComponent('navigation', { ...PARAMS, wide: true }));
|
|
100
|
+
|
|
101
|
+
expect($('.ons-container').hasClass('ons-container--wide')).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('has the search autosuggest with correct output', () => {
|
|
105
|
+
const faker = templateFaker();
|
|
106
|
+
const autosuggestSpy = faker.spy('autosuggest', { suppressOutput: true });
|
|
107
|
+
|
|
108
|
+
faker.renderComponent('navigation', {
|
|
109
|
+
...PARAMS,
|
|
110
|
+
siteSearchAutosuggest: {
|
|
111
|
+
...SITE_SEARCH_AUTOSUGGEST,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
expect(autosuggestSpy.occurrences[0]).toEqual({
|
|
116
|
+
...SITE_SEARCH_AUTOSUGGEST,
|
|
117
|
+
accessiblePlaceholder: true,
|
|
118
|
+
autocomplete: 'off',
|
|
119
|
+
id: 'ons-site-search',
|
|
120
|
+
containerClasses: 'ons-autosuggest-input--header',
|
|
121
|
+
classes: 'ons-input--ghost ons-input-search ons-input-search--icon',
|
|
122
|
+
label: {
|
|
123
|
+
text: 'Search the design system',
|
|
124
|
+
id: 'ons-site-search-label',
|
|
125
|
+
classes: 'ons-label--white ons-u-pl-m',
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('level: main navigation', () => {
|
|
132
|
+
it('has the provided `id` attribute', () => {
|
|
133
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
134
|
+
|
|
135
|
+
expect($('.ons-navigation--main').attr('id')).toBe('main-nav');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('has the provided `aria-label` attribute', () => {
|
|
139
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
140
|
+
|
|
141
|
+
expect($('.ons-navigation--main').attr('aria-label')).toBe('Main menu');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('has the correct link href for each list item', () => {
|
|
145
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
146
|
+
|
|
147
|
+
const values = mapAll($('.ons-navigation--main .ons-navigation__link'), node => node.attr('href'));
|
|
148
|
+
expect(values).toEqual(['#0', '#1']);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('has the correct link text for each list item', () => {
|
|
152
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
153
|
+
|
|
154
|
+
const values = mapAll($('.ons-navigation--main .ons-navigation__link'), node => node.text().trim());
|
|
155
|
+
expect(values).toEqual(['Main nav item 1', 'Main nav item 2']);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('has the provided custom class for each list item', () => {
|
|
159
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
160
|
+
|
|
161
|
+
expect($('.ons-navigation--main .ons-navigation__list > .ons-navigation__item').hasClass('custom-class-main-item-1')).toBe(true);
|
|
162
|
+
expect($('.ons-navigation--main .ons-navigation__list .ons-navigation__item:last-child').hasClass('custom-class-main-item-2')).toBe(
|
|
163
|
+
true,
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('has the provided id for each list item', () => {
|
|
168
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
169
|
+
|
|
170
|
+
expect($('.ons-navigation--main .ons-navigation__list > .ons-navigation__item .ons-navigation__link').attr('id')).toBe('main-item-1');
|
|
171
|
+
expect($('.ons-navigation--main .ons-navigation__list .ons-navigation__item:last-child .ons-navigation__link').attr('id')).toBe(
|
|
172
|
+
'main-item-2',
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('has the active class on the correct item', () => {
|
|
177
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
178
|
+
|
|
179
|
+
expect(
|
|
180
|
+
$('.ons-navigation--main .ons-navigation__list .ons-navigation__item:last-child').hasClass('ons-navigation__item--active'),
|
|
181
|
+
).toBe(true);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('level: sub navigation', () => {
|
|
186
|
+
it('renders a button with expected parameters', () => {
|
|
187
|
+
const faker = templateFaker();
|
|
188
|
+
const buttonSpy = faker.spy('button', { suppressOutput: true });
|
|
189
|
+
|
|
190
|
+
faker.renderComponent('navigation', PARAMS);
|
|
191
|
+
|
|
192
|
+
expect(buttonSpy.occurrences).toContainEqual({
|
|
193
|
+
text: 'Main nav item 2',
|
|
194
|
+
classes: 'ons-u-d-no ons-js-sub-navigation-button ons-btn--dropdown',
|
|
195
|
+
buttonStyle: 'mobile',
|
|
196
|
+
attributes: {
|
|
197
|
+
'aria-label': 'Toggle section navigation',
|
|
198
|
+
'aria-controls': 'sub-nav',
|
|
199
|
+
'aria-haspopup': 'true',
|
|
200
|
+
'aria-expanded': 'false',
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('has the provided `id` attribute', () => {
|
|
206
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
207
|
+
|
|
208
|
+
expect($('.ons-navigation--sub').attr('id')).toBe('sub-nav');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('has the provided `aria-label` attribute', () => {
|
|
212
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
213
|
+
|
|
214
|
+
expect($('.ons-navigation--sub').attr('aria-label')).toBe('Section menu');
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('has the correct link href for each list item', () => {
|
|
218
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
219
|
+
|
|
220
|
+
const values = mapAll($('.ons-navigation--sub .ons-navigation__link'), node => node.attr('href'));
|
|
221
|
+
expect(values).toEqual(['#0', '#1']);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('has the correct link text for each list item', () => {
|
|
225
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
226
|
+
|
|
227
|
+
const values = mapAll($('.ons-navigation--sub .ons-navigation__link'), node => node.text().trim());
|
|
228
|
+
expect(values).toEqual(['Sub nav item 1', 'Sub nav item 2']);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('has the provided custom class for each list item', () => {
|
|
232
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
233
|
+
|
|
234
|
+
expect($('.ons-navigation--sub .ons-navigation__list > .ons-navigation__item').hasClass('custom-class-sub-item-1')).toBe(true);
|
|
235
|
+
expect($('.ons-navigation--sub .ons-navigation__list .ons-navigation__item:last-child').hasClass('custom-class-sub-item-2')).toBe(
|
|
236
|
+
true,
|
|
237
|
+
);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('has the provided id for each list item', () => {
|
|
241
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
242
|
+
|
|
243
|
+
expect($('.ons-navigation--sub .ons-navigation__list > .ons-navigation__item .ons-navigation__link').attr('id')).toBe('sub-item-1');
|
|
244
|
+
expect($('.ons-navigation--sub .ons-navigation__list .ons-navigation__item:last-child .ons-navigation__link').attr('id')).toBe(
|
|
245
|
+
'sub-item-2',
|
|
246
|
+
);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('has the active class on the correct item', () => {
|
|
250
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
251
|
+
|
|
252
|
+
expect(
|
|
253
|
+
$('.ons-navigation--sub .ons-navigation__list .ons-navigation__item:last-child').hasClass('ons-navigation__item--active'),
|
|
254
|
+
).toBe(true);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe('level: sub navigation mobile', () => {
|
|
259
|
+
it('has the provided `id` attribute', () => {
|
|
260
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
261
|
+
|
|
262
|
+
expect($('.ons-navigation--sub-mobile').attr('id')).toBe('sub-nav--mobile');
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('has the provided `aria-label` attribute', () => {
|
|
266
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
267
|
+
|
|
268
|
+
expect($('.ons-navigation--sub-mobile').attr('aria-label')).toBe('Section menu');
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('has the correct link href for each list item', () => {
|
|
272
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
273
|
+
|
|
274
|
+
const values = mapAll(
|
|
275
|
+
$('.ons-navigation__list--parent > li a').not('.ons-navigation__list--parent li .ons-navigation__list--child a'),
|
|
276
|
+
node => node.attr('href'),
|
|
277
|
+
);
|
|
278
|
+
expect(values).toEqual(['#overview', '#0', '#1']);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('has the correct link text for each list item', () => {
|
|
282
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
283
|
+
|
|
284
|
+
const values = mapAll(
|
|
285
|
+
$('.ons-navigation__list--parent > li a').not('.ons-navigation__list--parent li .ons-navigation__list--child a'),
|
|
286
|
+
node => node.text().trim(),
|
|
287
|
+
);
|
|
288
|
+
expect(values).toEqual(['Overview', 'Sub nav item 1', 'Sub nav item 2']);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('has the active class on the correct item', () => {
|
|
292
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
293
|
+
|
|
294
|
+
expect(
|
|
295
|
+
$('.ons-navigation--sub-mobile .ons-navigation__list .ons-navigation__item:last-child').hasClass('ons-navigation__item--active'),
|
|
296
|
+
).toBe(true);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('has the correct text for the child section title', () => {
|
|
300
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
301
|
+
|
|
302
|
+
expect($('.ons-navigation__list-header').text()).toBe('Section 1');
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('has the correct link href for each child list item', () => {
|
|
306
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
307
|
+
|
|
308
|
+
const values = mapAll($('.ons-navigation__list--child > li a'), node => node.attr('href'));
|
|
309
|
+
expect(values).toEqual(['#0', '#1']);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('has the correct link text for each child list item', () => {
|
|
313
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
314
|
+
|
|
315
|
+
const values = mapAll($('.ons-navigation__list--child > li a'), node => node.text().trim());
|
|
316
|
+
expect(values).toEqual(['Child item 1', 'Child item 2']);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('has the active class on the correct child item', () => {
|
|
320
|
+
const $ = cheerio.load(renderComponent('navigation', PARAMS));
|
|
321
|
+
|
|
322
|
+
expect(
|
|
323
|
+
$('.ons-navigation--sub-mobile .ons-navigation__list .ons-navigation__item:last-child').hasClass('ons-navigation__item--active'),
|
|
324
|
+
).toBe(true);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
});
|
|
@@ -5,7 +5,7 @@ domready(async () => {
|
|
|
5
5
|
const navigationEl = document.querySelector('.ons-js-navigation');
|
|
6
6
|
const navigationHideClass = 'ons-u-d-no@xxs@l';
|
|
7
7
|
const toggleSubNavigationBtn = document.querySelector('.ons-js-sub-navigation-button');
|
|
8
|
-
const subNavigationEl = document.querySelector('.
|
|
8
|
+
const subNavigationEl = document.querySelector('.ons-js-secondary-nav');
|
|
9
9
|
const subNavigationHideClass = 'ons-u-d-no';
|
|
10
10
|
const toggleSearchBtn = document.querySelector('.ons-js-toggle-search');
|
|
11
11
|
const searchEl = document.querySelector('.ons-js-navigation-search');
|