@ons/design-system 73.0.3 → 73.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/components/accordion/_macro.njk +2 -0
  2. package/components/accordion/_macro.spec.js +39 -0
  3. package/components/accordion/accordion.js +2 -0
  4. package/components/accordion/example-accordion.njk +6 -1
  5. package/components/back-to-top/example-full-page-back-to-top.njk +2 -2
  6. package/components/button/example-button-new-window.njk +1 -0
  7. package/components/chart/_chart.scss +2 -2
  8. package/components/chart/_macro.spec.js +32 -0
  9. package/components/chart/annotations-options.js +1 -0
  10. package/components/chart/area-chart.js +3 -0
  11. package/components/chart/bar-chart.js +1 -0
  12. package/components/chart/chart-constants.js +2 -1
  13. package/components/chart/chart.js +8 -4
  14. package/components/chart/column-chart.js +3 -0
  15. package/components/chart/example-area-chart-with-axis-min-and-max-values.njk +1 -1
  16. package/components/chart/example-area-chart.njk +2 -2
  17. package/components/chart/example-clustered-column-chart.njk +1 -1
  18. package/components/chart/example-line-chart-with-annotations.njk +1 -1
  19. package/components/chart/example-line-chart-with-axis-min-and-max-values.njk +1 -1
  20. package/components/chart/example-line-chart-with-custom-reference-line-value.njk +1 -1
  21. package/components/chart/example-line-chart-with-label-format.njk +89 -0
  22. package/components/chart/example-line-chart-with-markers.njk +1 -37
  23. package/components/chart/example-line-chart-with-range-annotations-inside.njk +1 -1
  24. package/components/chart/example-line-chart-with-range-annotations-outside-left-right.njk +1 -1
  25. package/components/chart/example-line-chart-with-range-annotations-outside-top-bottom.njk +1 -1
  26. package/components/chart/example-line-chart-with-reference-line-annotations.njk +1 -1
  27. package/components/chart/example-line-chart.njk +1 -1
  28. package/components/chart/example-scatter-chart-with-axis-min-and-max-values.njk +1 -1
  29. package/components/chart/example-scatter-chart.njk +1 -1
  30. package/components/chart/example-stacked-column-chart.njk +26 -37
  31. package/components/chart/reference-line-annotations-options.js +1 -0
  32. package/components/chart/specific-chart-options.js +23 -1
  33. package/components/cookies-banner/_macro.njk +1 -3
  34. package/components/details-panel/_macro.njk +6 -6
  35. package/components/featured-article/example-featured-article-with-chart.njk +1 -1
  36. package/components/header/_macro.njk +64 -31
  37. package/components/header/_macro.spec.js +223 -0
  38. package/components/header/example-header-basic-with-search-and-language-DEPRECATED.njk +207 -0
  39. package/components/header/example-header-basic-with-search-and-language.njk +36 -27
  40. package/components/header/example-header-basic-with-search-button.njk +35 -27
  41. package/components/hero/_macro.njk +4 -1
  42. package/components/hero/_macro.spec.js +26 -0
  43. package/components/icon/_macro.njk +2 -2
  44. package/components/icon/_macro.spec.js +2 -2
  45. package/components/list/_list.scss +0 -3
  46. package/components/list/example-inline-list-with-social-icon-prefix.njk +2 -2
  47. package/components/panel/_panel.scss +5 -0
  48. package/components/radios/_macro.njk +1 -1
  49. package/components/related-content/example-related-content-social-media.njk +2 -2
  50. package/components/share-page/_macro.njk +6 -6
  51. package/components/share-page/_macro.spec.js +9 -9
  52. package/components/share-page/example-share-page.njk +1 -1
  53. package/components/skip-to-content/_macro.njk +1 -1
  54. package/components/skip-to-content/_skip.scss +0 -2
  55. package/components/table-of-contents/example-table-of-contents-grouped-with-single-list-item.njk +34 -0
  56. package/css/main.css +1 -1
  57. package/js/cookies-settings.js +5 -5
  58. package/layout/_template.njk +5 -5
  59. package/package.json +18 -12
  60. package/scripts/main.es5.js +5 -3
  61. package/scripts/main.js +2 -2
  62. package/scss/utilities/_highlight.scss +2 -1
  63. /package/favicons/{twitter.png → x.png} +0 -0
@@ -8,7 +8,12 @@ class SpecificChartOptions {
8
8
  this.config = config;
9
9
 
10
10
  this.options = {
11
- colors: this.theme === 'alternate' ? this.constants.alternateTheme : this.constants.primaryTheme,
11
+ colors:
12
+ this.theme === 'alternate'
13
+ ? this.constants.alternateTheme
14
+ : type == 'line'
15
+ ? this.constants.linePrimaryTheme
16
+ : this.constants.primaryTheme,
12
17
  chart: {
13
18
  type: type,
14
19
  marginTop: this.config.legend.enabled ? (type === 'boxplot' ? 50 : undefined) : 50,
@@ -41,6 +46,23 @@ class SpecificChartOptions {
41
46
  };
42
47
  }
43
48
 
49
+ limitSeriesToThemeLength = () => {
50
+ // Get the theme array from ChartConstants based on the theme name
51
+ const themeArray = this.theme === 'alternate' ? this.constants.alternateTheme : this.constants.primaryTheme;
52
+
53
+ // Limit the series to the theme array length
54
+ if (this.type !== 'scatter' && this.config.series.length > themeArray.length) {
55
+ this.config.series.length = themeArray.length;
56
+ }
57
+ };
58
+
59
+ limitSeriesForScatterChart = () => {
60
+ // Scatter charts only support up to 4 series for readability
61
+ if (this.config.series.length > 4) {
62
+ this.config.series.length = 4;
63
+ }
64
+ };
65
+
44
66
  getOptions = () => this.options;
45
67
 
46
68
  getMobileOptions = (xAxisTickInterval, yAxisTickInterval) => {
@@ -4,7 +4,6 @@
4
4
  {% if params.lang == 'cy' %}
5
5
  {% set ariaLabel = 'Cwcis' %}
6
6
  {% set serviceName = 'ons.gov.uk' %}
7
- {% set defaultCookiesLink = '/cwics' %}
8
7
  {% set statementTitle = 'Cwcis ar' %}
9
8
  {% set settingsLinkText = 'Gweld cwcis' %}
10
9
  {% set acceptButtonText = 'Derbyn cwcis ychwanegol' %}
@@ -20,7 +19,6 @@
20
19
  {% else %}
21
20
  {% set ariaLabel = 'Cookies banner' %}
22
21
  {% set serviceName = 'ons.gov.uk' %}
23
- {% set defaultCookiesLink = '/cookies' %}
24
22
  {% set statementTitle = 'Cookies on' %}
25
23
  {% set settingsLinkText = 'View cookies' %}
26
24
  {% set acceptButtonText = 'Accept additional cookies' %}
@@ -36,7 +34,7 @@
36
34
  {% endif %}
37
35
 
38
36
  {% if not isDesignSystemExample %}
39
- {% set settingsLinkUrl = params.settingsLinkUrl | default(defaultCookiesLink) %}
37
+ {% set settingsLinkUrl = params.settingsLinkUrl | default('/cookies') %}
40
38
  {% else %}
41
39
  {% set settingsLinkUrl = '#0' %}
42
40
  {% endif %}
@@ -13,11 +13,7 @@
13
13
  {{ openingTag | safe }}
14
14
  class="ons-details-panel__banner-title ons-u-fs-m ons-u-mb-2xs">{{ params.title }}{{ closingTag | safe }}
15
15
  <span class="ons-details-panel__banner-detail">
16
- <span class="ons-details-panel__banner-detail-title ons-u-mr-3xs">
17
- <span class="ons-details-panel__banner-detail-title--open"> {{ openText }} </span>
18
- <span class="ons-details-panel__banner-detail-title--close"> {{ closeText }} </span>
19
- </span>
20
- <span class="ons-details-panel__banner-detail-icon">
16
+ <span class="ons-details-panel__banner-detail-icon ons-u-mr-3xs">
21
17
  {% from "components/icon/_macro.njk" import onsIcon %}
22
18
  {{
23
19
  onsIcon({
@@ -25,11 +21,15 @@
25
21
  })
26
22
  }}
27
23
  </span>
24
+ <span class="ons-details-panel__banner-detail-title">
25
+ <span class="ons-details-panel__banner-detail-title--open"> {{ openText }} </span>
26
+ <span class="ons-details-panel__banner-detail-title--close"> {{ closeText }} </span>
27
+ </span>
28
28
  </span>
29
29
  </span>
30
30
  </span>
31
31
  </summary>
32
- <dl class="ons-container ons-details-panel__content ons-u-pt-xl ons-u-pb-3xl">
32
+ <dl class="ons-container ons-details-panel__content ons-u-p-l">
33
33
  {% for item in params.detailsItems %}
34
34
  <div class="ons-details-panel__item ons-u-pb-xl ons-u-mb-l ons-u-ml-2xs">
35
35
  <dt class="ons-details-panel__content-meta ons-u-mb-l@2xs@m">
@@ -18,7 +18,7 @@
18
18
  "chart": {
19
19
  "chartType": "line",
20
20
  "description": "Line chart showing the annual rate of inflation for the Consumer Prices Index including owner occupiers’ housing costs (CPIH) and its components.",
21
- "theme": "alternate",
21
+ "theme": "primary",
22
22
  "title": "Sales volumes and values saw moderate growth in July 2024",
23
23
  "subtitle": "Figure 6: Upward contribution from housing and household services (including energy) saw the annual CPIH inflation rate rise",
24
24
  "id": "id",
@@ -216,7 +216,7 @@
216
216
  </nav>
217
217
  {% endif %}
218
218
 
219
- {% if params.searchLinks %}
219
+ {% if params.search or params.searchLinks %}
220
220
  <div class="ons-header__links ons-grid__col ons-header__menu-link">
221
221
  {{
222
222
  onsButton({
@@ -225,8 +225,8 @@
225
225
  "variants": "search",
226
226
  "iconType": "search",
227
227
  "attributes": {
228
- "aria-label": params.searchLinks.searchButtonAriaLabel | default("Toggle search"),
229
- "aria-controls": params.searchLinks.id,
228
+ "aria-label": (params.search.toggleAriaLabel if params.search.toggleAriaLabel else params.searchLinks.searchButtonAriaLabel) | default("Toggle search"),
229
+ "aria-controls": params.search.id if params.search.id else params.searchLinks.id,
230
230
  "aria-expanded": "true",
231
231
  "aria-disabled": "true"
232
232
  }
@@ -235,56 +235,89 @@
235
235
  </div>
236
236
  {% endif %}
237
237
 
238
- {% if params.variants == "basic" and params.searchLinks %}
238
+ {% if params.variants == "basic" and (params.searchLinks or params.search) %}
239
239
  <nav
240
- class="ons-js-header-search ons-header-nav-search {{ params.searchLinks.classes }}"
241
- id="{{ params.searchLinks.id }}"
242
- aria-label="{{ params.searchLinks.searchNavigationAriaLabel | default('Search navigation') }}"
240
+ class="ons-js-header-search ons-header-nav-search {{ params.searchLinks.classes if params.searchLinks and params.searchLinks.classes else '' }}{{ params.search.classes if params.search and params.search.classes else '' }}"
241
+ id="{{ params.search.id if params.search else params.searchLinks.id }}"
242
+ aria-label="{{ (params.search.navAriaLabel if params.search else params.searchLinks.searchNavigationAriaLabel) | default('Search navigation') }}"
243
243
  aria-hidden="false"
244
244
  >
245
245
  <div class="ons-container">
246
- <div class="ons-header-nav-search__input">
246
+ <form
247
+ class="ons-header-nav-search__input"
248
+ method="get"
249
+ action="{{ params.search.form.action | default('') }}"
250
+ >
247
251
  {% from "components/input/_macro.njk" import onsInput %}
248
252
  {{
249
253
  onsInput({
250
254
  "id": 'search-field',
255
+ "name": params.search.form.inputName | default('q'),
251
256
  "width": 'full',
252
257
  "label": {
253
- "text": params.searchLinks.searchNavigationInputLabel | default('Search the ONS'),
258
+ "text": (params.search.form.inputLabel if params.search.form else params.searchLinks.searchNavigationInputLabel) | default('Search the ONS'),
254
259
  "id": "header-search-input-label"
255
260
  },
256
261
  "searchButton": {
257
262
  "visuallyHideButtonText": true,
258
- "text": params.searchLinks.searchNavigationButtonText | default('Search'),
263
+ "text": (params.search.form.buttonText if params.search.form else params.searchLinks.searchNavigationButtonText) | default('Search'),
259
264
  "iconType": 'search',
260
265
  'variant': 'header'
261
266
  }
262
267
  })
263
268
  }}
264
- </div>
269
+ </form>
265
270
  </div>
266
- {% if params.searchLinks %}
271
+ {% if params.search or params.searchLinks %}
267
272
  <div class="ons-container">
268
273
  <h2 class="ons-u-fs-r--b ons-u-mb-s ons-header-nav-search__heading">
269
- {{ params.searchLinks.heading }}
274
+ {{ params.search.links.heading if params.search.links else params.searchLinks.heading }}
270
275
  </h2>
271
276
  <ul class="ons-list ons-list--bare ons-list--inline">
272
- {% for item in params.searchLinks.itemsList %}
273
- {# Limiting the popular searches to 5 #}
274
- {% if loop.index <= 5 %}
275
- <li class="ons-list__item">
276
- {% if item.text %}
277
- {% if item.url %}
278
- <a href="{{ item.url }}" class="ons-u-fs-r ons-header-nav-search__text"
279
- >{{ item.text }}
280
- </a>
281
- {% else %}
282
- <p class="ons-u-fs-r ons-header-nav-search__text">{{ item.text }}</p>
277
+ {% if params.searchLinks %}
278
+ {% for item in params.searchLinks.itemsList %}
279
+ {# Limiting the popular searches to 5 #}
280
+ {% if loop.index <= 5 %}
281
+ <li class="ons-list__item">
282
+ {% if item.text %}
283
+ {% if item.url %}
284
+ <a
285
+ href="{{ item.url }}"
286
+ class="ons-u-fs-r ons-header-nav-search__text"
287
+ >{{ item.text }}
288
+ </a>
289
+ {% else %}
290
+ <p class="ons-u-fs-r ons-header-nav-search__text">
291
+ {{ item.text }}
292
+ </p>
293
+ {% endif %}
283
294
  {% endif %}
284
- {% endif %}
285
- </li>
286
- {% endif %}
287
- {% endfor %}
295
+ </li>
296
+ {% endif %}
297
+ {% endfor %}
298
+ {% endif %}
299
+ {% if params.search.links %}
300
+ {% for item in params.search.links.itemsList %}
301
+ {# Limiting the popular searches to 5 #}
302
+ {% if loop.index <= 5 %}
303
+ <li class="ons-list__item">
304
+ {% if item.text %}
305
+ {% if item.url %}
306
+ <a
307
+ href="{{ item.url }}"
308
+ class="ons-u-fs-r ons-header-nav-search__text"
309
+ >{{ item.text }}
310
+ </a>
311
+ {% else %}
312
+ <p class="ons-u-fs-r ons-header-nav-search__text">
313
+ {{ item.text }}
314
+ </p>
315
+ {% endif %}
316
+ {% endif %}
317
+ </li>
318
+ {% endif %}
319
+ {% endfor %}
320
+ {% endif %}
288
321
  </ul>
289
322
  </div>
290
323
  {% endif %}
@@ -294,7 +327,7 @@
294
327
  {% endif %}
295
328
  {% if params.language or params.serviceLinks %}
296
329
  <div
297
- class="ons-header__links ons-grid__col{{ ' ons-u-ml-auto' if not params.searchLinks and not params.menuLinks }}"
330
+ class="ons-header__links ons-grid__col{{ ' ons-u-ml-auto' if not (params.searchLinks or params.search) and not params.menuLinks }}"
298
331
  >
299
332
  {% if params.language %}
300
333
  <div class="ons-grid__col ons-col-auto{{ ' ons-u-mr-s ons-u-d-no@2xs@xs' if params.serviceLinks }}">
@@ -482,13 +515,13 @@
482
515
  <span class="ons-grid ons-u-ml-no ons-u-d-no@2xs@xs">
483
516
  {{
484
517
  onsButton({
485
- "text": params.searchLinks.searchNavigationButtonText | default('Search'),
518
+ "text": (params.search.form.buttonText if params.search.form.buttonText else searchLinks.searchNavigationButtonText) | default('Search'),
486
519
  "classes": "ons-btn--search ons-u-ml-2xs ons-u-d-no ons-js-toggle-search",
487
520
  "variants": ["small", "ghost"],
488
521
  "iconType": "search",
489
522
  "iconPosition": "only",
490
523
  "attributes": {
491
- "aria-label": params.searchLinks.searchNavigationButtonAriaLabel | default('Toggle search'),
524
+ "aria-label":(params.search.navButtonAriaLabel if params.search.navButtonAriaLabel else params.searchLinks.searchNavigationButtonAriaLabel) | default('Toggle search'),
492
525
  "aria-controls": "ons-site-search",
493
526
  "aria-expanded": "false"
494
527
  }
@@ -18,6 +18,7 @@ import {
18
18
  EXAMPLE_HEADER_NAVIGATION_WITH_SITESEARCHAUTOSUGGEST,
19
19
  EXAMPLE_HEADER_MENU_LINKS,
20
20
  EXAMPLE_HEADER_SEARCH_AND_MENU_LINKS,
21
+ EXAMPLE_HEADER_SEARCH,
21
22
  } from './_test-examples';
22
23
 
23
24
  describe('FOR: Macro: Header', () => {
@@ -812,6 +813,228 @@ describe('FOR: Macro: Header', () => {
812
813
  });
813
814
  });
814
815
  });
816
+
817
+ describe('GIVEN: Params: search', () => {
818
+ describe('WHEN: search is provided', () => {
819
+ const faker = templateFaker();
820
+ const buttonSpy = faker.spy('button', { suppressOutput: true });
821
+ faker.renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' });
822
+
823
+ test('THEN: renders search icon button', () => {
824
+ expect(buttonSpy.occurrences[0]).toEqual({
825
+ iconType: 'search',
826
+ classes: 'ons-u-fs-s--b ons-js-toggle-header-search ons-btn--close ons-btn--search-icon active disabled',
827
+ type: 'button',
828
+ variants: 'search',
829
+ attributes: {
830
+ 'aria-controls': 'search-id',
831
+ 'aria-expanded': 'true',
832
+ 'aria-label': 'Custom search button aria label',
833
+ 'aria-disabled': 'true',
834
+ },
835
+ });
836
+ });
837
+ });
838
+
839
+ describe('WHEN: links are provided in search', () => {
840
+ const $ = cheerio.load(renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' }));
841
+
842
+ test('THEN: renders items list', () => {
843
+ const itemsList = $('.ons-list--bare .ons-list__item').length;
844
+ expect(itemsList).toBeGreaterThan(0);
845
+ });
846
+
847
+ test('THEN: renders correct links for items list', () => {
848
+ const searchItemsLinks = mapAll($('.ons-list--bare .ons-list__item a'), (node) => node.attr('href'));
849
+ expect(searchItemsLinks).toEqual(['#1', '#2', '#3']);
850
+ });
851
+
852
+ test('THEN: renders correct text for items list', () => {
853
+ const searchItemsText = mapAll($('.ons-list--bare .ons-list__item a'), (node) => node.text().trim());
854
+ expect(searchItemsText).toEqual(['Popular Search 1', 'Popular Search 2', 'Popular Search 3']);
855
+ });
856
+ });
857
+
858
+ describe('WHEN: search parameter is missing', () => {
859
+ const $ = cheerio.load(renderComponent('header', EXAMPLE_HEADER_BASIC));
860
+
861
+ test('THEN: does not render search icon button', () => {
862
+ expect($('.ons-js-toggle-services').length).toBe(0);
863
+ });
864
+
865
+ test('THEN: does not render search input form', () => {
866
+ expect($('.ons-header-nav-search').length).toBe(0);
867
+ });
868
+
869
+ test('THEN: does not render items list', () => {
870
+ expect($('.ons-list--bare').length).toBe(0);
871
+ });
872
+ });
873
+
874
+ describe('WHEN: search is provided and the header variant is not basic', () => {
875
+ const $ = cheerio.load(renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'neutral' }));
876
+
877
+ test('THEN: does not render the search icon button', () => {
878
+ expect($('.ons-js-toggle-services').length).toBe(0);
879
+ });
880
+ });
881
+
882
+ describe('WHEN: heading parameter is provided', () => {
883
+ const $ = cheerio.load(renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' }));
884
+
885
+ test('THEN: it renders heading with provided text', () => {
886
+ expect($('.ons-header-nav-search__heading').text().trim()).toBe('Header Search');
887
+ });
888
+ });
889
+
890
+ describe('WHEN: id parameter is provided', () => {
891
+ const $ = cheerio.load(renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' }));
892
+
893
+ test('THEN: applies id to search links ', () => {
894
+ expect($('#search-id').length).toBe(1);
895
+ });
896
+ });
897
+
898
+ describe('WHEN: ariaLabel parameter is provided', () => {
899
+ const $ = cheerio.load(renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' }));
900
+
901
+ test('THEN: applies aria label to the search links', () => {
902
+ expect($('.ons-header-nav-search').attr('aria-label')).toBe('Header Search');
903
+ });
904
+ });
905
+
906
+ describe('WHEN: classes parameter is provided', () => {
907
+ const $ = cheerio.load(renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' }));
908
+
909
+ test('THEN: it renders classes with provided value', () => {
910
+ expect($('.ons-header-nav-search').hasClass('custom-class')).toBe(true);
911
+ });
912
+ });
913
+
914
+ describe('WHEN: using basic header variant and search is active & disabled by default before JS loads', () => {
915
+ const $ = cheerio.load(renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' }));
916
+ const $searchBtn = $('.ons-js-toggle-header-search');
917
+
918
+ test('THEN: adds the "active" class to the search toggle button', () => {
919
+ expect($searchBtn.hasClass('active')).toBe(true);
920
+ });
921
+
922
+ test('THEN: adds the "disabled" class to the search toggle button', () => {
923
+ expect($searchBtn.hasClass('disabled')).toBe(true);
924
+ });
925
+
926
+ test('THEN: sets aria-disabled="true" on the search toggle button', () => {
927
+ expect($searchBtn.attr('aria-disabled')).toBe('true');
928
+ });
929
+ });
930
+
931
+ describe('WHEN: search is provided with all custom properties', () => {
932
+ const faker = templateFaker();
933
+ const buttonSpy = faker.spy('button', { suppressOutput: true });
934
+ faker.renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' });
935
+ test('THEN: renders search icon button with custom aria-label', () => {
936
+ expect(buttonSpy.occurrences[0]).toBeDefined();
937
+ expect(buttonSpy.occurrences[0].attributes['aria-label']).toBe('Custom search button aria label');
938
+ });
939
+ });
940
+
941
+ describe('WHEN: toggleAriaLabel is not provided', () => {
942
+ const faker = templateFaker();
943
+ const buttonSpy = faker.spy('button', { suppressOutput: true });
944
+ faker.renderComponent('header', {
945
+ ...EXAMPLE_HEADER_SEARCH,
946
+ search: {
947
+ ...EXAMPLE_HEADER_SEARCH.links,
948
+ toggleAriaLabel: undefined,
949
+ },
950
+ variants: 'basic',
951
+ });
952
+ test('THEN: renders search icon button with default aria-label', () => {
953
+ expect(buttonSpy.occurrences[0]).toBeDefined();
954
+ expect(buttonSpy.occurrences[0].attributes['aria-label']).toBe('Toggle search');
955
+ });
956
+ });
957
+ describe('WHEN: navButtonAriaLabel is provided', () => {
958
+ const faker = templateFaker();
959
+ const buttonSpy = faker.spy('button', { suppressOutput: true });
960
+ faker.renderComponent('header', {
961
+ ...EXAMPLE_HEADER_SEARCH,
962
+ siteSearchAutosuggest: {},
963
+ });
964
+ test('THEN: renders search navigation button with custom aria-label', () => {
965
+ const found = buttonSpy.occurrences.find(
966
+ (btn) => btn.attributes && btn.attributes['aria-label'] === 'Custom search nav button aria label',
967
+ );
968
+ expect(found).toBeDefined();
969
+ });
970
+ });
971
+ describe('WHEN: navButtonAriaLabel is not provided', () => {
972
+ const faker = templateFaker();
973
+ const buttonSpy = faker.spy('button', { suppressOutput: true });
974
+ faker.renderComponent('header', {
975
+ ...EXAMPLE_HEADER_SEARCH,
976
+ search: {
977
+ ...EXAMPLE_HEADER_SEARCH.search,
978
+ navButtonAriaLabel: undefined,
979
+ },
980
+ siteSearchAutosuggest: {},
981
+ });
982
+ test('THEN: renders search navigation button with default aria-label', () => {
983
+ const found = buttonSpy.occurrences.find((btn) => btn.attributes && btn.attributes['aria-label'] === 'Toggle search');
984
+ expect(found).toBeDefined();
985
+ });
986
+ });
987
+
988
+ describe('WHEN: inputLabel is provided', () => {
989
+ const $ = cheerio.load(renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' }));
990
+ test('THEN: renders search input with custom label', () => {
991
+ expect($('#header-search-input-label').text().trim()).toBe('Custom search input label');
992
+ });
993
+ });
994
+ describe('WHEN: inputLabel is not provided', () => {
995
+ const $ = cheerio.load(
996
+ renderComponent('header', {
997
+ ...EXAMPLE_HEADER_SEARCH,
998
+ search: {
999
+ ...EXAMPLE_HEADER_SEARCH.search,
1000
+ form: { inputLabel: undefined },
1001
+ },
1002
+ variants: 'basic',
1003
+ }),
1004
+ );
1005
+ test('THEN: renders search input with default label', () => {
1006
+ expect($('#header-search-input-label').text().trim()).toBe('Search the ONS');
1007
+ });
1008
+ });
1009
+ describe('WHEN: buttonText is provided', () => {
1010
+ const $ = cheerio.load(renderComponent('header', { ...EXAMPLE_HEADER_SEARCH, variants: 'basic' }));
1011
+
1012
+ test('THEN: renders the visually hidden search navigation button text', () => {
1013
+ const $button = $('.ons-search__btn.ons-btn--header-search');
1014
+ const hiddenText = $button.find('.ons-u-vh').text().trim();
1015
+ expect(hiddenText).toBe(EXAMPLE_HEADER_SEARCH.search.form.buttonText);
1016
+ });
1017
+ });
1018
+ describe('WHEN: buttonText is not provided', () => {
1019
+ const $ = cheerio.load(
1020
+ renderComponent('header', {
1021
+ ...EXAMPLE_HEADER_SEARCH,
1022
+ search: {
1023
+ ...EXAMPLE_HEADER_SEARCH.search,
1024
+ form: { buttonText: undefined },
1025
+ },
1026
+ variants: 'basic',
1027
+ }),
1028
+ );
1029
+
1030
+ test('THEN: renders the default fallback search navigation button text', () => {
1031
+ const $button = $('.ons-search__btn.ons-btn--header-search');
1032
+ const hiddenText = $button.find('.ons-u-vh').text().trim();
1033
+ expect(hiddenText).toBe('Search');
1034
+ });
1035
+ });
1036
+ });
1037
+
815
1038
  describe('GIVEN: Params: searchLinks', () => {
816
1039
  describe('WHEN: searchLinks are provided', () => {
817
1040
  const faker = templateFaker();