@ons/design-system 70.0.16 → 70.0.17

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 CHANGED
@@ -44,6 +44,15 @@ yarn start
44
44
 
45
45
  Once the server has started, navigate to <http://localhost:3030>
46
46
 
47
+ ## Lighthouse Testing - local
48
+
49
+ This project uses [LHCI](https://www.npmjs.com/package/@lhci/cli).
50
+
51
+ ```bash
52
+ yarn global add @lhci/cli
53
+ yarn test-lighthouse
54
+ ```
55
+
47
56
  ## Testing - macros and scripts
48
57
 
49
58
  This project uses [jest](https://jestjs.io/docs/cli) and supports its command line options.
@@ -112,7 +121,7 @@ It is sometimes useful to adjust the following settings when writing tests or di
112
121
 
113
122
  ## Testing - Visual regression tests
114
123
 
115
- This project uses [Backstop JS](https://github.com/garris/BackstopJS) for visual regression testing. The tests run in Chrome headless using Pupeteer inside docker and run in three viewports; 1920 (desktop), 768 (tablet) and 375 (mobile). Reference images are stored in Git LFS and any approved changes will automatically be stored in Git LFS when pushed to the repository.
124
+ This project uses [Backstop JS](https://github.com/garris/BackstopJS) for visual regression testing. The tests run in Chrome headless using Puppeteer inside docker and run in three viewports; 1920 (desktop), 768 (tablet) and 375 (mobile). Reference images are stored in Git LFS and any approved changes will automatically be stored in Git LFS when pushed to the repository.
116
125
 
117
126
  The visual tests will run automatically on pull requests and the result will be available in the Github Action logs. If the tests fail, the process for viewing the failures and approving changes will need to be handled locally using the following workflow and commands.
118
127
 
@@ -5,7 +5,7 @@ import * as cheerio from 'cheerio';
5
5
  import axe from '../../tests/helpers/axe';
6
6
  import { renderComponent } from '../../tests/helpers/rendering';
7
7
 
8
- describe('FOR: access-code', () => {
8
+ describe('FOR: Macro: Access-code', () => {
9
9
  describe('GIVEN: Params: required', () => {
10
10
  describe('WHEN: all required params are provided', () => {
11
11
  const $ = cheerio.load(
@@ -24,7 +24,7 @@ describe('FOR: access-code', () => {
24
24
  test('THEN: autocomplete is disabled on text input', () => {
25
25
  expect($('input').attr('autocomplete')).toBe('off');
26
26
  });
27
- test('THEN: text input has automatic capitalisation', () => {
27
+ test('THEN: text input has autocapitalize attribute', () => {
28
28
  expect($('input').attr('autocapitalize')).toBe('characters');
29
29
  });
30
30
  });
@@ -4,64 +4,82 @@ import * as cheerio from 'cheerio';
4
4
 
5
5
  import axe from '../../tests/helpers/axe';
6
6
  import { renderComponent } from '../../tests/helpers/rendering';
7
-
8
- const EXAMPLE_ACCORDION_WITH_TWO_ITEMS = {
9
- id: 'accordion-identifier',
10
- itemsList: [
11
- {
12
- title: 'Title for item 1',
13
- content: 'Content for item 1',
14
- },
15
- {
16
- title: 'Title for item 2',
17
- content: 'Content for item 2',
18
- },
19
- ],
20
- };
21
-
22
- const EXAMPLE_ACCORDION = {
23
- ...EXAMPLE_ACCORDION_WITH_TWO_ITEMS,
24
- allButton: {
25
- open: 'Open label',
26
- close: 'Close label',
27
- },
28
- };
29
-
30
- describe('macro: accordion', () => {
31
- it('passes jest-axe checks', async () => {
32
- const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION));
33
-
34
- const results = await axe($.html());
35
- expect(results).toHaveNoViolations();
7
+ import { EXAMPLE_ACCORDION } from './_test_examples';
8
+
9
+ describe('FOR: Macro: Accordion', () => {
10
+ describe('GIVEN: Params: required', () => {
11
+ describe('WHEN: all required params are provided', () => {
12
+ const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION));
13
+ test('THEN: jest-axe checks pass', async () => {
14
+ const results = await axe($.html());
15
+ expect(results).toHaveNoViolations();
16
+ });
17
+ });
36
18
  });
37
-
38
- it('has the provided `id` attribute', () => {
39
- const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION_WITH_TWO_ITEMS));
40
-
41
- expect($('.ons-accordion').attr('id')).toBe('accordion-identifier');
19
+ describe('GIVEN: Params: required and allButton', () => {
20
+ describe('WHEN: required and allButton params are provided', () => {
21
+ const $ = cheerio.load(
22
+ renderComponent('accordion', {
23
+ ...EXAMPLE_ACCORDION,
24
+ allButton: {
25
+ open: 'Open label',
26
+ close: 'Close label',
27
+ },
28
+ }),
29
+ );
30
+ test('THEN: jest-axe checks pass', async () => {
31
+ const results = await axe($.html());
32
+ expect(results).toHaveNoViolations();
33
+ });
34
+ });
42
35
  });
43
-
44
- it('has additionally provided style classes', () => {
45
- const $ = cheerio.load(
46
- renderComponent('accordion', {
47
- ...EXAMPLE_ACCORDION_WITH_TWO_ITEMS,
48
- classes: 'extra-class another-extra-class',
49
- }),
50
- );
51
-
52
- expect($('.ons-accordion').hasClass('extra-class')).toBe(true);
53
- expect($('.ons-accordion').hasClass('another-extra-class')).toBe(true);
36
+ describe('GIVEN: Params: id', () => {
37
+ describe('WHEN: id is provided', () => {
38
+ const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION));
39
+ test('THEN: renders with provided id', () => {
40
+ expect($('.ons-accordion').attr('id')).toBe('accordion-identifier');
41
+ });
42
+ });
54
43
  });
55
-
56
- describe('item', () => {
57
- it('has provided title text', () => {
58
- const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION_WITH_TWO_ITEMS));
59
-
60
- const titleText = $('.ons-details__title').first().text().trim();
61
- expect(titleText).toBe('Title for item 1');
44
+ describe('GIVEN: Params: classes', () => {
45
+ describe('WHEN: additional style classes are provided', () => {
46
+ const $ = cheerio.load(
47
+ renderComponent('accordion', {
48
+ ...EXAMPLE_ACCORDION,
49
+ classes: 'extra-class another-extra-class',
50
+ }),
51
+ );
52
+ test('THEN: renders with provided classes', () => {
53
+ expect($('.ons-accordion').hasClass('extra-class')).toBe(true);
54
+ expect($('.ons-accordion').hasClass('another-extra-class')).toBe(true);
55
+ });
62
56
  });
63
-
64
- it('has title with provided tag override', () => {
57
+ });
58
+ describe('GIVEN: Params: itemsList: AccordionItem', () => {
59
+ describe('WHEN: title is provided', () => {
60
+ const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION));
61
+ test('THEN: renders title with provided text', () => {
62
+ const titleText = $('.ons-details__title').first().text().trim();
63
+ expect(titleText).toBe('Title for item 1');
64
+ });
65
+ });
66
+ describe('WHEN: titleTag is not provided', () => {
67
+ const $ = cheerio.load(
68
+ renderComponent('accordion', {
69
+ itemsList: [
70
+ {
71
+ title: 'Title for item 1',
72
+ content: 'Content for item 1',
73
+ },
74
+ ],
75
+ }),
76
+ );
77
+ test('THEN: item title renders with default heading tag', () => {
78
+ const titleTag = $('.ons-details__title')[0].tagName;
79
+ expect(titleTag).toBe('h2');
80
+ });
81
+ });
82
+ describe('WHEN: titleTag is provided', () => {
65
83
  const $ = cheerio.load(
66
84
  renderComponent('accordion', {
67
85
  itemsList: [
@@ -73,19 +91,19 @@ describe('macro: accordion', () => {
73
91
  ],
74
92
  }),
75
93
  );
76
-
77
- const titleTag = $('.ons-details__title')[0].tagName;
78
- expect(titleTag).toBe('h5');
94
+ test('THEN: item title renders with provided heading tag', () => {
95
+ const titleTag = $('.ons-details__title')[0].tagName;
96
+ expect(titleTag).toBe('h5');
97
+ });
79
98
  });
80
-
81
- it('has provided content text', () => {
82
- const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION_WITH_TWO_ITEMS));
83
-
84
- const titleText = $('.ons-details__content').first().text().trim();
85
- expect(titleText).toBe('Content for item 1');
99
+ describe('WHEN: content is provided', () => {
100
+ const $ = cheerio.load(renderComponent('accordion', EXAMPLE_ACCORDION));
101
+ test('THEN: item content renders with provided text', () => {
102
+ const titleText = $('.ons-details__content').first().text().trim();
103
+ expect(titleText).toBe('Content for item 1');
104
+ });
86
105
  });
87
-
88
- it('has additionally provided `attributes`', () => {
106
+ describe('WHEN: attributes are provided', () => {
89
107
  const $ = cheerio.load(
90
108
  renderComponent('accordion', {
91
109
  itemsList: [
@@ -99,12 +117,12 @@ describe('macro: accordion', () => {
99
117
  ],
100
118
  }),
101
119
  );
102
-
103
- expect($('.ons-details').attr('a')).toBe('123');
104
- expect($('.ons-details').attr('b')).toBe('456');
120
+ test('THEN: item renders with provided HTML attributes', () => {
121
+ expect($('.ons-details').attr('a')).toBe('123');
122
+ expect($('.ons-details').attr('b')).toBe('456');
123
+ });
105
124
  });
106
-
107
- it('has additionally provided `headingAttributes`', () => {
125
+ describe('WHEN: headingAttributes are provided', () => {
108
126
  const $ = cheerio.load(
109
127
  renderComponent('accordion', {
110
128
  itemsList: [
@@ -118,12 +136,12 @@ describe('macro: accordion', () => {
118
136
  ],
119
137
  }),
120
138
  );
121
-
122
- expect($('.ons-details__heading').attr('a')).toBe('123');
123
- expect($('.ons-details__heading').attr('b')).toBe('456');
139
+ test('THEN: item header renders with provided HTML attributes', () => {
140
+ expect($('.ons-details__heading').attr('a')).toBe('123');
141
+ expect($('.ons-details__heading').attr('b')).toBe('456');
142
+ });
124
143
  });
125
-
126
- it('has additionally provided `contentAttributes`', () => {
144
+ describe('WHEN: contentAttributes are provided', () => {
127
145
  const $ = cheerio.load(
128
146
  renderComponent('accordion', {
129
147
  itemsList: [
@@ -138,31 +156,37 @@ describe('macro: accordion', () => {
138
156
  ],
139
157
  }),
140
158
  );
141
-
142
- expect($('.ons-details__content').attr('a')).toBe('123');
143
- expect($('.ons-details__content').attr('b')).toBe('456');
159
+ test('THEN: item content renders with provided HTML attributes', () => {
160
+ expect($('.ons-details__content').attr('a')).toBe('123');
161
+ expect($('.ons-details__content').attr('b')).toBe('456');
162
+ });
144
163
  });
145
164
  });
146
-
147
- describe('toggle all button', () => {
148
- it('outputs a button with the expected class', () => {
165
+ describe('GIVEN: Params: allButton: AccordionButton', () => {
166
+ describe('WHEN: required open/close params are provided', () => {
149
167
  const $ = cheerio.load(
150
168
  renderComponent('accordion', {
151
- ...EXAMPLE_ACCORDION_WITH_TWO_ITEMS,
169
+ ...EXAMPLE_ACCORDION,
152
170
  allButton: {
153
171
  open: 'Open label',
154
172
  close: 'Close label',
155
173
  },
156
174
  }),
157
175
  );
158
-
159
- expect($('button.ons-accordion__toggle-all').length).toBe(1);
176
+ test('THEN: renders button with expected class', () => {
177
+ expect($('button.ons-accordion__toggle-all').length).toBe(1);
178
+ });
179
+ test('THEN: renders button with provided open text', () => {
180
+ expect($('.ons-accordion__toggle-all-inner').text()).toBe('Open label');
181
+ });
182
+ test('THEN: renders button with provided close text', () => {
183
+ expect($('button.ons-accordion__toggle-all').attr('data-close-all')).toBe('Close label');
184
+ });
160
185
  });
161
-
162
- it('has additionally provided `attributes`', () => {
186
+ describe('WHEN: attributes are provided', () => {
163
187
  const $ = cheerio.load(
164
188
  renderComponent('accordion', {
165
- ...EXAMPLE_ACCORDION_WITH_TWO_ITEMS,
189
+ ...EXAMPLE_ACCORDION,
166
190
  allButton: {
167
191
  open: 'Open label',
168
192
  close: 'Close label',
@@ -173,9 +197,56 @@ describe('macro: accordion', () => {
173
197
  },
174
198
  }),
175
199
  );
176
-
177
- expect($('button.ons-accordion__toggle-all').attr('a')).toBe('123');
178
- expect($('button.ons-accordion__toggle-all').attr('b')).toBe('456');
200
+ test('THEN: renders button with additional attributes provided', () => {
201
+ expect($('button.ons-accordion__toggle-all').attr('a')).toBe('123');
202
+ expect($('button.ons-accordion__toggle-all').attr('b')).toBe('456');
203
+ });
204
+ });
205
+ });
206
+ describe('GIVEN: Params: saveState', () => {
207
+ describe('WHEN: saveState param is not provided', () => {
208
+ const $ = cheerio.load(
209
+ renderComponent('accordion', {
210
+ ...EXAMPLE_ACCORDION,
211
+ }),
212
+ );
213
+ test('THEN: renders without saveState attribute', () => {
214
+ expect($('.ons-details--accordion').attr('saveState')).toBe(undefined);
215
+ });
216
+ });
217
+ describe('WHEN: saveState param is set to true', () => {
218
+ const $ = cheerio.load(
219
+ renderComponent('accordion', {
220
+ ...EXAMPLE_ACCORDION,
221
+ saveState: true,
222
+ }),
223
+ );
224
+ test('THEN: renders with saveState attribute', () => {
225
+ expect($('.ons-details--accordion').attr('saveState'));
226
+ });
227
+ });
228
+ });
229
+ describe('GIVEN: Params: open', () => {
230
+ describe('WHEN: open param is not provided', () => {
231
+ const $ = cheerio.load(
232
+ renderComponent('accordion', {
233
+ ...EXAMPLE_ACCORDION,
234
+ }),
235
+ );
236
+ test('THEN: renders with accordion items closed on page load', () => {
237
+ expect($('.ons-details--accordion').attr('open')).toBe(undefined);
238
+ });
239
+ });
240
+ describe('WHEN: open param is set to true', () => {
241
+ const $ = cheerio.load(
242
+ renderComponent('accordion', {
243
+ ...EXAMPLE_ACCORDION,
244
+ open: true,
245
+ }),
246
+ );
247
+ test('THEN: renders with accordion items open on page load', () => {
248
+ expect($('.ons-details--accordion').attr('open'));
249
+ });
179
250
  });
180
251
  });
181
252
  });
@@ -0,0 +1,13 @@
1
+ export const EXAMPLE_ACCORDION = {
2
+ id: 'accordion-identifier',
3
+ itemsList: [
4
+ {
5
+ title: 'Title for item 1',
6
+ content: 'Content for item 1',
7
+ },
8
+ {
9
+ title: 'Title for item 2',
10
+ content: 'Content for item 2',
11
+ },
12
+ ],
13
+ };
@@ -5,7 +5,7 @@ import * as cheerio from 'cheerio';
5
5
  import axe from '../../tests/helpers/axe';
6
6
  import { renderComponent } from '../../tests/helpers/rendering';
7
7
 
8
- describe('FOR: Back-to-top', () => {
8
+ describe('FOR: Macro: Back-to-top', () => {
9
9
  describe('GIVEN: Params: default', () => {
10
10
  describe('WHEN: params are at default', () => {
11
11
  const $ = cheerio.load(renderComponent('back-to-top'));
@@ -5,125 +5,131 @@ import * as cheerio from 'cheerio';
5
5
  import axe from '../../tests/helpers/axe';
6
6
  import { mapAll } from '../../tests/helpers/cheerio';
7
7
  import { renderComponent, templateFaker } from '../../tests/helpers/rendering';
8
-
9
- const EXAMPLE_BREADCRUMBS_MINIMAL = {
10
- itemsList: [
11
- {
12
- url: 'https://example.com/',
13
- text: 'Home',
14
- },
15
- {
16
- url: 'https://example.com/guide/',
17
- text: 'Guide',
18
- },
19
- ],
20
- };
21
-
22
- const EXAMPLE_BREADCRUMBS = {
23
- classes: 'extra-class another-extra-class',
24
- ariaLabel: 'Breadcrumbs label',
25
- id: 'example-breadcrumbs',
26
- itemsList: [
27
- {
28
- itemClasses: 'item-extra-class item-another-extra-class',
29
- linkClasses: 'link-extra-class link-another-extra-class',
30
- url: 'https://example.com/',
31
- text: 'Home',
32
- attributes: {
33
- 'data-a': '123',
34
- 'data-b': '456',
35
- },
36
- id: 'first-breadcrumb',
37
- },
38
- {
39
- url: 'https://example.com/guide/',
40
- text: 'Guide',
41
- id: 'second-breadcrumb',
42
- attributes: {
43
- 'data-a': '789',
44
- 'data-b': 'ABC',
45
- },
46
- },
47
- ],
48
- };
49
-
50
- describe('macro: breadcrumbs', () => {
51
- it('passes jest-axe checks', async () => {
52
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS));
53
-
54
- const results = await axe($.html());
55
- expect(results).toHaveNoViolations();
56
- });
57
-
58
- it('has additionally provided style classes', () => {
59
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS));
60
-
61
- expect($('.ons-breadcrumbs').hasClass('extra-class')).toBe(true);
62
- expect($('.ons-breadcrumbs').hasClass('another-extra-class')).toBe(true);
63
- });
64
-
65
- it('has a default `aria-label` of "Breadcrumbs"', () => {
66
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_MINIMAL));
67
-
68
- expect($('.ons-breadcrumbs').attr('aria-label')).toBe('Breadcrumbs');
69
- });
70
-
71
- it('has the provided `ariaLabel` for `aria-label`', () => {
72
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS));
73
-
74
- expect($('.ons-breadcrumbs').attr('aria-label')).toBe('Breadcrumbs label');
75
- });
76
-
77
- it('has the provided `id`', () => {
78
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS));
79
-
80
- expect($('.ons-breadcrumbs').attr('id')).toBe('example-breadcrumbs');
8
+ import { EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS, EXAMPLE_BREADCRUMBS_ALL_PARAMS } from './_test_examples';
9
+
10
+ describe('FOR: Macro: Breadcrumbs', () => {
11
+ describe('GIVEN: Params: required', () => {
12
+ describe('WHEN: required params are provided', () => {
13
+ const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS));
14
+ test('THEN: jest-axe tests pass', async () => {
15
+ const results = await axe($.html());
16
+ expect(results).toHaveNoViolations();
17
+ });
18
+ const faker = templateFaker();
19
+ const iconsSpy = faker.spy('icon');
20
+ faker.renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS);
21
+ test('THEN: renders chevron icon next to item', () => {
22
+ const iconTypes = iconsSpy.occurrences.map((occurrence) => occurrence.iconType);
23
+ expect(iconTypes).toEqual(['chevron']);
24
+ });
25
+ });
81
26
  });
82
-
83
- it('has additionally provided style classes on `item` element', () => {
84
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS));
85
-
86
- expect($('.ons-breadcrumbs__item:first').hasClass('item-extra-class')).toBe(true);
87
- expect($('.ons-breadcrumbs__item:first').hasClass('item-another-extra-class')).toBe(true);
27
+ describe('GIVEN: Params: all', () => {
28
+ describe('WHEN: all Params are provided', () => {
29
+ const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_ALL_PARAMS));
30
+ test('THEN: jest-axe tests pass', async () => {
31
+ const results = await axe($.html());
32
+ expect(results).toHaveNoViolations();
33
+ });
34
+ const faker = templateFaker();
35
+ const iconsSpy = faker.spy('icon');
36
+ faker.renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_ALL_PARAMS);
37
+ test('THEN: renders chevron icon next to each item', () => {
38
+ const iconTypes = iconsSpy.occurrences.map((occurrence) => occurrence.iconType);
39
+ expect(iconTypes).toEqual(['chevron', 'chevron']);
40
+ });
41
+ });
88
42
  });
89
-
90
- it('has additionally provided style classes on `link` element', () => {
91
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS));
92
-
93
- expect($('.ons-breadcrumbs__link:first').hasClass('link-extra-class')).toBe(true);
94
- expect($('.ons-breadcrumbs__link:first').hasClass('link-another-extra-class')).toBe(true);
43
+ describe('GIVEN: Params: classes', () => {
44
+ describe('WHEN: additional classes are provided', () => {
45
+ const $ = cheerio.load(
46
+ renderComponent('breadcrumbs', {
47
+ ...EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS,
48
+ classes: 'extra-class another-extra-class',
49
+ }),
50
+ );
51
+ test('THEN: renders with correct additional classes', () => {
52
+ expect($('.ons-breadcrumbs').hasClass('extra-class')).toBe(true);
53
+ expect($('.ons-breadcrumbs').hasClass('another-extra-class')).toBe(true);
54
+ });
55
+ });
95
56
  });
96
-
97
- it('has provided `url` on `link` elements', () => {
98
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS));
99
-
100
- const urls = mapAll($('.ons-breadcrumbs__link'), (node) => node.attr('href'));
101
- expect(urls).toEqual(['https://example.com/', 'https://example.com/guide/']);
57
+ describe('GIVEN: Params: ariaLabel', () => {
58
+ describe('WHEN: ariaLabel is not provided', () => {
59
+ const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS));
60
+ test('THEN: renders with default aria-label of "Breadcrumbs"', () => {
61
+ expect($('.ons-breadcrumbs').attr('aria-label')).toBe('Breadcrumbs');
62
+ });
63
+ });
64
+ describe('WHEN: ariaLabel is provided', () => {
65
+ const $ = cheerio.load(
66
+ renderComponent('breadcrumbs', {
67
+ ...EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS,
68
+ ariaLabel: 'Breadcrumbs label',
69
+ }),
70
+ );
71
+ test('THEN: renders with provided aria-label', () => {
72
+ expect($('.ons-breadcrumbs').attr('aria-label')).toBe('Breadcrumbs label');
73
+ });
74
+ });
102
75
  });
103
-
104
- it('has provided `text` on `link` elements', () => {
105
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS));
106
-
107
- const labels = mapAll($('.ons-breadcrumbs__link'), (node) => node.text().trim());
108
- expect(labels).toEqual(['Home', 'Guide']);
109
- });
110
-
111
- it('has provided `attributes` on `link` elements', () => {
112
- const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS));
113
-
114
- const testValuesA = mapAll($('.ons-breadcrumbs__link'), (node) => node.attr('data-a'));
115
- expect(testValuesA).toEqual(['123', '789']);
116
- const testValuesB = mapAll($('.ons-breadcrumbs__link'), (node) => node.attr('data-b'));
117
- expect(testValuesB).toEqual(['456', 'ABC']);
76
+ describe('GIVEN: Params: id', () => {
77
+ describe('WHEN: id is provided', () => {
78
+ const $ = cheerio.load(
79
+ renderComponent('breadcrumbs', {
80
+ ...EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS,
81
+ id: 'example-breadcrumbs',
82
+ }),
83
+ );
84
+ test('THEN: renders with provided id', () => {
85
+ expect($('.ons-breadcrumbs').attr('id')).toBe('example-breadcrumbs');
86
+ });
87
+ });
118
88
  });
119
-
120
- it('has a "chevron" icon for each breadcrumb item', () => {
121
- const faker = templateFaker();
122
- const iconsSpy = faker.spy('icon');
123
-
124
- faker.renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_MINIMAL);
125
-
126
- const iconTypes = iconsSpy.occurrences.map((occurrence) => occurrence.iconType);
127
- expect(iconTypes).toEqual(['chevron', 'chevron']);
89
+ describe('GIVEN: Params: itemsList (multiple)', () => {
90
+ describe('WHEN: itemClasses param is provided', () => {
91
+ const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_ALL_PARAMS));
92
+ test('THEN: renders item with provided style classes', () => {
93
+ expect($('.ons-breadcrumbs__item:first').hasClass('item-extra-class')).toBe(true);
94
+ expect($('.ons-breadcrumbs__item:first').hasClass('item-another-extra-class')).toBe(true);
95
+ });
96
+ });
97
+ describe('WHEN: linkClasses param is provided', () => {
98
+ const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_ALL_PARAMS));
99
+ test('THEN: renders link with provided style classes', () => {
100
+ expect($('.ons-breadcrumbs__link').hasClass('link-extra-class')).toBe(true);
101
+ expect($('.ons-breadcrumbs__link').hasClass('link-another-extra-class')).toBe(true);
102
+ });
103
+ });
104
+ describe('WHEN: id param is provided', () => {
105
+ const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_ALL_PARAMS));
106
+ test('THEN: renders items with provided id', () => {
107
+ const ids = mapAll($('.ons-breadcrumbs__link'), (node) => node.attr('id'));
108
+ expect(ids).toEqual(['first-breadcrumb', 'second-breadcrumb']);
109
+ });
110
+ });
111
+ describe('WHEN: url param is provided', () => {
112
+ const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_ALL_PARAMS));
113
+ test('THEN: renders items with provided url link', () => {
114
+ const urls = mapAll($('.ons-breadcrumbs__link'), (node) => node.attr('href'));
115
+ expect(urls).toEqual(['https://example.com/', 'https://example.com/guide/']);
116
+ });
117
+ });
118
+ describe('WHEN: text param is provided', () => {
119
+ const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_ALL_PARAMS));
120
+ test('THEN: renders item links with provided text', () => {
121
+ const labels = mapAll($('.ons-breadcrumbs__link'), (node) => node.text().trim());
122
+ expect(labels).toEqual(['Home', 'Guide']);
123
+ });
124
+ });
125
+ describe('WHEN: attributes param is provided', () => {
126
+ const $ = cheerio.load(renderComponent('breadcrumbs', EXAMPLE_BREADCRUMBS_ALL_PARAMS));
127
+ test('THEN: renders items with provided attributes', () => {
128
+ const testValuesA = mapAll($('.ons-breadcrumbs__link'), (node) => node.attr('data-a'));
129
+ expect(testValuesA).toEqual(['123', '789']);
130
+ const testValuesB = mapAll($('.ons-breadcrumbs__link'), (node) => node.attr('data-b'));
131
+ expect(testValuesB).toEqual(['456', 'ABC']);
132
+ });
133
+ });
128
134
  });
129
135
  });
@@ -0,0 +1,36 @@
1
+ export const EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS = {
2
+ itemsList: [
3
+ {
4
+ url: 'https://example.com/',
5
+ text: 'Home',
6
+ },
7
+ ],
8
+ };
9
+
10
+ export const EXAMPLE_BREADCRUMBS_ALL_PARAMS = {
11
+ classes: 'extra-class another-extra-class',
12
+ ariaLabel: 'Breadcrumbs label',
13
+ id: 'example-breadcrumbs',
14
+ itemsList: [
15
+ {
16
+ itemClasses: 'item-extra-class item-another-extra-class',
17
+ linkClasses: 'link-extra-class link-another-extra-class',
18
+ url: 'https://example.com/',
19
+ text: 'Home',
20
+ attributes: {
21
+ 'data-a': '123',
22
+ 'data-b': '456',
23
+ },
24
+ id: 'first-breadcrumb',
25
+ },
26
+ {
27
+ url: 'https://example.com/guide/',
28
+ text: 'Guide',
29
+ id: 'second-breadcrumb',
30
+ attributes: {
31
+ 'data-a': '789',
32
+ 'data-b': 'ABC',
33
+ },
34
+ },
35
+ ],
36
+ };
@@ -5,7 +5,7 @@ import * as cheerio from 'cheerio';
5
5
  import axe from '../../tests/helpers/axe';
6
6
  import { renderComponent } from '../../tests/helpers/rendering';
7
7
 
8
- describe('FOR: browser-banner', () => {
8
+ describe('FOR: Macro: Browser-banner', () => {
9
9
  describe('GIVEN: Params: default', () => {
10
10
  describe('WHEN: params are at default state', () => {
11
11
  const $ = cheerio.load(renderComponent('browser-banner', {}));
@@ -72,7 +72,7 @@
72
72
  {% else %}
73
73
  type="{{ buttonType }}"
74
74
  {% endif %}
75
- class="ons-btn{{ ' ' + params.classes if params.classes else '' }}{% if params.variants and params.variants is not string %}{% for variant in params.variants %}{{ ' ' }}ons-btn--{{ variant }}{% endfor %}{% else %}{{ ' ' }}ons-btn--{{ params.variants }}{% endif %}{{ ' ons-btn--link ons-js-submit-btn' if params.url }}{{ variantClasses }}"
75
+ class="ons-btn{{ ' ' + params.classes if params.classes else '' }}{% if params.variants and params.variants is not string %}{% for variant in params.variants %}{{ ' ' }}ons-btn--{{ variant }}{% endfor %}{% elif params.variants %}{{ ' ' }}ons-btn--{{ params.variants }}{% endif %}{{ ' ons-btn--link ons-js-submit-btn' if params.url }}{{ variantClasses }}"
76
76
  {% if params.id %}id="{{ params.id }}"{% endif %}
77
77
  {% if params.value and tag != "a" %}value="{{ params.value }}"{% endif %}
78
78
  {% if params.name and tag != "a" %}name="{{ params.name }}"{% endif %}
@@ -111,7 +111,7 @@
111
111
  {%- endif -%}
112
112
  </span>
113
113
  {% if params.url and params.newWindow %}
114
- <span class="ons-btn__new-window-description ons-u-vh"> ({{ params.newWindowDescription | default("opens in a new tab") }})</span>
114
+ <span class="ons-btn__new-window-description ons-u-vh">({{ params.newWindowDescription | default("opens in a new tab") }})</span>
115
115
  {% endif %}
116
116
  {% if params.buttonContext %}
117
117
  <span class="ons-btn__context ons-u-vh">{{ params.buttonContext }}</span>
@@ -393,7 +393,7 @@ describe('macro: button', () => {
393
393
  }),
394
394
  );
395
395
 
396
- expect($('.ons-btn__new-window-description').text()).toBe(' (opens in a new tab)');
396
+ expect($('.ons-btn__new-window-description').text()).toBe('(opens in a new tab)');
397
397
  });
398
398
 
399
399
  it('has a custom new window description when `newWindow` is `true` and `newWindowDescription` is provided', () => {
@@ -405,7 +405,7 @@ describe('macro: button', () => {
405
405
  }),
406
406
  );
407
407
 
408
- expect($('.ons-btn__new-window-description').text()).toBe(' (custom opens in a new window text)');
408
+ expect($('.ons-btn__new-window-description').text()).toBe('(custom opens in a new window text)');
409
409
  });
410
410
 
411
411
  it('has the `download` attribute when `variants` contains "download"', () => {
@@ -16,7 +16,7 @@ import {
16
16
  EXAMPLE_HEADER_NAVIGATION_WITH_SITESEARCHAUTOSUGGEST,
17
17
  } from './_test-examples';
18
18
 
19
- describe('FOR: Header', () => {
19
+ describe('FOR: Macro: Header', () => {
20
20
  describe('GIVEN: Params: none', () => {
21
21
  describe('WHEN: All params are at default state', () => {
22
22
  const $ = cheerio.load(
@@ -1,6 +1,6 @@
1
1
  {% from "components/text-indent/_macro.njk" import onsTextIndent %}
2
2
  {{-
3
3
  onsTextIndent({
4
- text: '<p>Telephone: 0800 141 2021<br>Monday to Friday, 8 am to 7pm<br>Saturday, 8am to 4pm</p>'
4
+ "text": '<p>Telephone: 0800 141 2021<br>Monday to Friday, 8 am to 7pm<br>Saturday, 8am to 4pm</p>'
5
5
  })
6
6
  -}}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ons/design-system",
3
3
  "description": "ONS Design System built CSS, JS, and Nunjucks templates",
4
- "version": "70.0.16",
4
+ "version": "70.0.17",
5
5
  "main": "index.js",
6
6
  "license": "MIT",
7
7
  "author": {
@@ -15,6 +15,7 @@
15
15
  "test:no-build": "TEST_PORT=3020 TEST_WITH_PUPPETEER=1 jest '.*\\.spec\\.js'",
16
16
  "test:with-log": "yarn test --no-color 2>test.log",
17
17
  "test:start-server": "TEST_PORT=3020 gulp start-dev-server",
18
+ "test-lighthouse": "yarn build && node ./lighthouse/lighthouse-get-urls.js && lhci autorun --config=./lighthouse/lighthouserc.js",
18
19
  "build": "yarn && yarn tidy-clean && NODE_ENV=production gulp build",
19
20
  "build-serve": "yarn build && gulp start-dev-server",
20
21
  "npm-bundle": "NODE_ENV=production yarn tidy-clean && NODE_ENV=production gulp build-package && babel-node ci/generate-npm-package.js",
@@ -95,7 +96,7 @@
95
96
  "gulp-sourcemaps": "^3.0.0",
96
97
  "gulp-terser": "^2.0.1",
97
98
  "http-server": "^14.1.1",
98
- "husky": "^8.0.3",
99
+ "husky": "^9.1.6",
99
100
  "jest": "^29.6.1",
100
101
  "jest-axe": "^8.0.0",
101
102
  "jest-environment-jsdom": "^29.6.1",