@eeacms/volto-eea-design-system 1.50.2 → 1.60.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/CHANGELOG.md CHANGED
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ ### [1.60.0](https://github.com/eea/volto-eea-design-system/compare/1.50.2...1.60.0) - 17 April 2026
8
+
9
+ #### :house: Documentation changes
10
+
11
+ - docs: Update README [Alin Voinea - [`06e6ce7`](https://github.com/eea/volto-eea-design-system/commit/06e6ce7553bb50dea0d000f990f19c568e658b9f)]
12
+
13
+ #### :hammer_and_wrench: Others
14
+
15
+ - update readme [Miu Razvan - [`268086f`](https://github.com/eea/volto-eea-design-system/commit/268086fa17f9f68283dc7528ddbcd71105b676da)]
16
+ - Release 1.60.0 [Alin Voinea - [`c74e3ac`](https://github.com/eea/volto-eea-design-system/commit/c74e3acb79cce153067984a234401e3d16ac0b05)]
17
+ - update version [Miu Razvan - [`5753c9f`](https://github.com/eea/volto-eea-design-system/commit/5753c9f98c80a8699889a55a3fe1abecf3853b77)]
18
+ - fix tests [Miu Razvan - [`32b5e42`](https://github.com/eea/volto-eea-design-system/commit/32b5e42c6f458f7391f930165852700daa758790)]
19
+ - fix tests [Miu Razvan - [`dca166a`](https://github.com/eea/volto-eea-design-system/commit/dca166aa44a9bc3c123a17e78333b850ef401fb6)]
20
+ - fix tests [Miu Razvan - [`0e876ca`](https://github.com/eea/volto-eea-design-system/commit/0e876caf4e172b84dfbc30a16c58009ee4481d94)]
21
+ - fix tests [Miu Razvan - [`86f657a`](https://github.com/eea/volto-eea-design-system/commit/86f657a70a357a412257e9d8cb63f9050ca718e4)]
22
+ - Make use of eea_settings [Miu Razvan - [`78ab3c5`](https://github.com/eea/volto-eea-design-system/commit/78ab3c59a4a7232b09812b3967ddd2b93cdd7fad)]
23
+ - Bump version + add upgrade step [Miu Razvan - [`a1dbbd5`](https://github.com/eea/volto-eea-design-system/commit/a1dbbd557f66174f05ce87ed21073aecefa1f507)]
7
24
  ### [1.50.2](https://github.com/eea/volto-eea-design-system/compare/1.50.1...1.50.2) - 9 April 2026
8
25
 
9
26
  #### :bug: Bug Fixes
package/README.md CHANGED
@@ -25,6 +25,10 @@ This package provides the following features:
25
25
  2. A repository for the design system source files and mockups
26
26
  3. A website to showcase the design system
27
27
 
28
+ ## Upgrade
29
+
30
+ - Version `^1.60.0` requires `^eea.volto.policy@12.0` to allow customizing the header search box.
31
+
28
32
  ### Try the design system website
29
33
 
30
34
  Checkout the docs found within the [website](https://github.com/eea/volto-eea-design-system/blob/develop/website/README.md) folder
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-design-system",
3
- "version": "1.50.2",
3
+ "version": "1.60.0",
4
4
  "description": "@eeacms/volto-eea-design-system: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -5,11 +5,13 @@
5
5
 
6
6
  import React from 'react'; // , { Component }
7
7
  import { useHistory } from 'react-router-dom';
8
+ import { useSelector } from 'react-redux';
8
9
  import cx from 'classnames';
9
10
  import { Container, Image, Menu, Grid, Dropdown } from 'semantic-ui-react'; // Dropdown,
10
11
 
11
12
  import closeIcon from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/close-line.svg';
12
- import searchIcon from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/ai-search.svg';
13
+ import searchSVG from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/search-line.svg';
14
+ import aiSearchIcon from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/ai-search.svg';
13
15
  import burgerIcon from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/menu-line.svg';
14
16
 
15
17
  import HeaderSearchPopUp from './HeaderSearchPopUp';
@@ -159,6 +161,11 @@ const Main = ({
159
161
  const [burger, setBurger] = React.useState('');
160
162
  const searchInputRef = React.useRef(null);
161
163
  const [isClient, setIsClient] = React.useState();
164
+ const headerSettings = useSelector(
165
+ (state) => state.eeaSettings?.data?.header || {},
166
+ );
167
+
168
+ const searchIcon = headerSettings.useAISearchIcon ? aiSearchIcon : searchSVG;
162
169
 
163
170
  const itemsLayouts =
164
171
  menuItemsLayouts || config.settings?.menuItemsLayouts || {};
@@ -2,9 +2,15 @@ import React from 'react';
2
2
  import { createMemoryHistory } from 'history';
3
3
  import { Router } from 'react-router-dom';
4
4
  import { render, fireEvent, act } from '@testing-library/react';
5
+ import { Provider } from 'react-redux';
6
+ import { createStore } from 'redux';
5
7
  import { Default } from './Header.stories';
6
8
  import '@testing-library/jest-dom';
7
9
 
10
+ const mockStore = createStore(() => ({
11
+ eeaSettings: { data: { header: {} } },
12
+ }));
13
+
8
14
  global.ResizeObserver = require('resize-observer-polyfill');
9
15
 
10
16
  const history = createMemoryHistory();
@@ -129,9 +135,11 @@ describe('Default component', () => {
129
135
 
130
136
  it('renders the default with correct number of cards', () => {
131
137
  const { container, getByText } = render(
132
- <Router history={history}>
133
- <Default {...args} />
134
- </Router>,
138
+ <Provider store={mockStore}>
139
+ <Router history={history}>
140
+ <Default {...args} />
141
+ </Router>
142
+ </Provider>,
135
143
  );
136
144
  const dropdown = container.querySelector('.official-union .content');
137
145
  fireEvent.click(dropdown);
@@ -4,8 +4,29 @@ import '@testing-library/jest-dom';
4
4
 
5
5
  import { createMemoryHistory } from 'history';
6
6
  import { Router } from 'react-router-dom';
7
+ import { Provider } from 'react-redux';
7
8
  import '@testing-library/jest-dom';
8
9
 
10
+ const mockState = {
11
+ eeaSettings: {
12
+ data: {
13
+ header: {
14
+ useAISearchIcon: false,
15
+ },
16
+ },
17
+ },
18
+ };
19
+
20
+ const mockStore = {
21
+ getState: () => mockState,
22
+ subscribe: () => () => {},
23
+ dispatch: () => {},
24
+ };
25
+
26
+ const renderWithProvider = (component) => {
27
+ return render(<Provider store={mockStore}>{component}</Provider>);
28
+ };
29
+
9
30
  // Mock subcomponents that pull in ESM helpers not transformed by Jest here
10
31
  jest.doMock('./HeaderSearchPopUp', () => () => null);
11
32
  jest.doMock('./HeaderMenuPopUp', () => () => null);
@@ -26,16 +47,16 @@ describe('Header component', () => {
26
47
  });
27
48
 
28
49
  it('renders without crashing', () => {
29
- render(<Header />);
50
+ renderWithProvider(<Header />);
30
51
  });
31
52
 
32
53
  it('renders children correctly', () => {
33
- render(<Header>Test Children</Header>);
54
+ renderWithProvider(<Header>Test Children</Header>);
34
55
  expect(screen.getByText('Test Children')).toBeInTheDocument();
35
56
  });
36
57
 
37
58
  it('renders without crashing', () => {
38
- render(
59
+ renderWithProvider(
39
60
  <Header>
40
61
  <Header.TopHeader>
41
62
  <Header.TopItem>
@@ -83,7 +104,7 @@ describe('Header component', () => {
83
104
  });
84
105
 
85
106
  it('renders without crashing', () => {
86
- render(
107
+ renderWithProvider(
87
108
  <Header>
88
109
  <Header.TopHeader>
89
110
  <Header.TopItem>
@@ -129,7 +150,7 @@ describe('Header component', () => {
129
150
  });
130
151
 
131
152
  it('renders without crashing', () => {
132
- const { getByText, getAllByText, container } = render(
153
+ const { getByText, getAllByText, container } = renderWithProvider(
133
154
  <Router history={history}>
134
155
  <Header>
135
156
  <Header.TopHeader>
@@ -427,7 +448,7 @@ test('marks only the best-matching top-level item active (sibling collision case
427
448
  },
428
449
  ];
429
450
 
430
- const { container, getByText } = render(
451
+ const { container, getByText } = renderWithProvider(
431
452
  <Router history={history}>
432
453
  <Header>
433
454
  <Header.Main
@@ -476,7 +497,7 @@ test('exact match wins: parent item active only on its own URL', async () => {
476
497
  },
477
498
  ];
478
499
 
479
- const { container, getByText } = render(
500
+ const { container, getByText } = renderWithProvider(
480
501
  <Router history={history}>
481
502
  <Header>
482
503
  <Header.Main
@@ -515,7 +536,7 @@ test('mobile burger menu interactions', async () => {
515
536
  },
516
537
  ];
517
538
 
518
- const { container } = render(
539
+ const { container } = renderWithProvider(
519
540
  <Router history={history}>
520
541
  <Header>
521
542
  <Header.Main
@@ -559,7 +580,7 @@ test('search interactions and state management', async () => {
559
580
  },
560
581
  ];
561
582
 
562
- const { container } = render(
583
+ const { container } = renderWithProvider(
563
584
  <Router history={history}>
564
585
  <Header>
565
586
  <Header.Main
@@ -603,7 +624,7 @@ test('escape key handling', async () => {
603
624
  },
604
625
  ];
605
626
 
606
- const { container } = render(
627
+ const { container } = renderWithProvider(
607
628
  <Router history={history}>
608
629
  <Header>
609
630
  <Header.Main
@@ -650,7 +671,7 @@ test('multilingual pathname handling', async () => {
650
671
  },
651
672
  ];
652
673
 
653
- const { rerender } = render(
674
+ const { rerender } = renderWithProvider(
654
675
  <Router history={history}>
655
676
  <Header>
656
677
  <Header.Main
@@ -674,25 +695,27 @@ test('multilingual pathname handling', async () => {
674
695
 
675
696
  // Test with empty multilingual path
676
697
  rerender(
677
- <Router history={history}>
678
- <Header>
679
- <Header.Main
680
- pathname="/en/"
681
- isMultilingual={true}
682
- menuItems={menuItems}
683
- renderGlobalMenuItem={(item) => (
684
- <a href={item.url} title={item.title}>
685
- {item.title}
686
- </a>
687
- )}
688
- renderMenuItem={(item, options) => (
689
- <a href={item.url || '/'} {...(options || {})}>
690
- {item.title}
691
- </a>
692
- )}
693
- />
694
- </Header>
695
- </Router>,
698
+ <Provider store={mockStore}>
699
+ <Router history={history}>
700
+ <Header>
701
+ <Header.Main
702
+ pathname="/en/"
703
+ isMultilingual={true}
704
+ menuItems={menuItems}
705
+ renderGlobalMenuItem={(item) => (
706
+ <a href={item.url} title={item.title}>
707
+ {item.title}
708
+ </a>
709
+ )}
710
+ renderMenuItem={(item, options) => (
711
+ <a href={item.url || '/'} {...(options || {})}>
712
+ {item.title}
713
+ </a>
714
+ )}
715
+ />
716
+ </Header>
717
+ </Router>
718
+ </Provider>,
696
719
  );
697
720
  });
698
721
 
@@ -707,11 +730,11 @@ test('menu click outside behavior with different active states', async () => {
707
730
  },
708
731
  ];
709
732
 
710
- const { container } = render(
733
+ const { container } = renderWithProvider(
711
734
  <Router history={history}>
712
735
  <Header>
713
736
  <Header.Main
714
- pathname="/different-path"
737
+ pathname="/test"
715
738
  menuItems={menuItems}
716
739
  renderGlobalMenuItem={(item) => (
717
740
  <a href={item.url} title={item.title}>
@@ -1,9 +1,13 @@
1
1
  import React, { useEffect } from 'react';
2
- import { Container, Input, List } from 'semantic-ui-react';
2
+ import { useSelector } from 'react-redux';
3
+ import { Container, Input, List, Image } from 'semantic-ui-react';
3
4
  import { withRouter, Link } from 'react-router-dom';
4
5
  import { useClickOutside } from '@eeacms/volto-eea-design-system/helpers';
5
6
  import { handleEnterKeyPress } from '@eeacms/volto-eea-design-system/helpers';
6
7
 
8
+ import searchSVG from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/search-line.svg';
9
+ import aiSearchIcon from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/ai-search.svg';
10
+
7
11
  const getRandomItems = (arr, max) => {
8
12
  return (
9
13
  arr?.slice(0, max).map(function () {
@@ -12,36 +16,57 @@ const getRandomItems = (arr, max) => {
12
16
  );
13
17
  };
14
18
 
19
+ function ActionItem({ action }) {
20
+ if (action.type === 'info') {
21
+ return <div>{action.content}</div>;
22
+ }
23
+ if (action.type === 'button-link') {
24
+ return (
25
+ <a
26
+ href={action.url}
27
+ className="ui button white inverted"
28
+ title={action.title}
29
+ >
30
+ {action.title}
31
+ </a>
32
+ );
33
+ }
34
+ return null;
35
+ }
36
+
15
37
  function HeaderSearchPopUp({
16
38
  history,
17
- location,
18
39
  onClose,
19
40
  searchInputRef,
20
41
  headerSearchBox,
21
42
  triggerRefs = [],
22
43
  }) {
23
44
  const nodeRef = React.useRef();
24
- const headerSearchViews = headerSearchBox || [];
25
- const defaultView = headerSearchViews.filter((v) => v.isDefault);
26
- const localView = headerSearchViews.filter((v) =>
27
- location.pathname.match(v.matchpath ? v.matchpath : v.path),
28
- );
29
- const activeView = localView.length > 0 ? localView[0] : defaultView[0];
45
+
46
+ const searchInput =
47
+ headerSearchBox.filter((v) => v.type === 'search-input')[0] || {};
48
+ const actions =
49
+ headerSearchBox.filter((v) => ['info', 'button-link'].includes(v.type)) ||
50
+ [];
30
51
 
31
52
  const {
32
53
  path = '',
33
- buttonTitle,
34
- buttonUrl,
35
- description,
36
54
  placeholder = 'Search',
37
- searchSuggestions,
38
- } = activeView || {};
39
- const { suggestionsTitle, suggestions, maxToShow } = searchSuggestions || {};
55
+ suggestionsTitle,
56
+ maxToShow,
57
+ suggestions,
58
+ } = searchInput;
40
59
 
41
60
  const [visibleSuggestions, setVisibileSuggestions] = React.useState(
42
61
  getRandomItems(suggestions, maxToShow),
43
62
  );
44
63
 
64
+ const headerSettings = useSelector(
65
+ (state) => state.eeaSettings?.data?.header || {},
66
+ );
67
+
68
+ const searchIcon = headerSettings.useAISearchIcon ? aiSearchIcon : searchSVG;
69
+
45
70
  useEffect(() => {
46
71
  setVisibileSuggestions(getRandomItems(suggestions, maxToShow));
47
72
  }, [maxToShow, suggestions]);
@@ -77,18 +102,27 @@ function HeaderSearchPopUp({
77
102
  ref={searchInputRef}
78
103
  className="icon search"
79
104
  action={{
80
- className: 'icon ri-search-line',
105
+ className: 'icon',
81
106
  'aria-label': 'Submit search',
82
107
  onClick: onSubmit,
83
108
  onKeyDown: (event) => {
84
109
  handleEnterKeyPress(event, onSubmit);
85
110
  },
111
+ children: (
112
+ <Image
113
+ src={searchIcon}
114
+ alt="Global search"
115
+ height={45}
116
+ width={45}
117
+ className="header-search-icon"
118
+ />
119
+ ),
86
120
  }}
87
121
  placeholder={placeholder}
88
122
  fluid
89
123
  />
90
124
  </form>
91
- {searchSuggestions && suggestions.length > 0 && (
125
+ {suggestions?.length > 0 && (
92
126
  <div className="search-suggestions">
93
127
  {suggestionsTitle && <h4>{suggestionsTitle}</h4>}
94
128
 
@@ -109,17 +143,12 @@ function HeaderSearchPopUp({
109
143
  </div>
110
144
  )}
111
145
  </Container>
112
- {buttonTitle && (
146
+ {actions?.length > 0 && (
113
147
  <div className="advanced-search">
114
148
  <Container>
115
- <div>{description}</div>
116
- <a
117
- href={buttonUrl || defaultView[0].path}
118
- className="ui button white inverted"
119
- title="Advanced search"
120
- >
121
- {buttonTitle}
122
- </a>
149
+ {actions.map((action, i) => (
150
+ <ActionItem key={i} action={action} />
151
+ ))}
123
152
  </Container>
124
153
  </div>
125
154
  )}
@@ -2,41 +2,53 @@ import React from 'react';
2
2
  import { render, screen, fireEvent } from '@testing-library/react';
3
3
  import { createMemoryHistory } from 'history';
4
4
  import { Router } from 'react-router-dom';
5
+ import { Provider } from 'react-redux';
5
6
  import HeaderSearchPopUp from './HeaderSearchPopUp';
6
7
  import '@testing-library/jest-dom';
7
8
 
9
+ const mockState = {
10
+ eeaSettings: {
11
+ data: {
12
+ header: {
13
+ useAISearchIcon: false,
14
+ },
15
+ },
16
+ },
17
+ };
18
+
19
+ const mockStore = {
20
+ getState: () => mockState,
21
+ subscribe: () => () => {},
22
+ dispatch: () => {},
23
+ };
24
+
8
25
  describe('HeaderSearchPopUp', () => {
9
26
  let history;
10
27
  const mockOnClose = jest.fn();
11
28
  const sampleHeaderSearchBox = [
12
29
  {
30
+ type: 'search-input',
13
31
  path: '/search',
14
- buttonTitle: 'Advanced Search',
15
- buttonUrl: '/advanced-search',
16
- description: 'Sample description',
17
32
  placeholder: 'Search',
18
- searchSuggestions: {
19
- suggestionsTitle: 'Suggestions Title',
20
- suggestions: ['suggestion 1', 'suggestion 2', 'suggestion 3'],
21
- maxToShow: 3,
22
- },
23
- isDefault: true,
33
+ suggestionsTitle: 'Suggestions Title',
34
+ suggestions: ['suggestion 1', 'suggestion 2', 'suggestion 3'],
35
+ maxToShow: 3,
36
+ },
37
+ {
38
+ type: 'button-link',
39
+ title: 'Advanced Search',
40
+ url: '/advanced-search',
24
41
  },
25
42
  ];
26
43
 
27
44
  const sampleHeaderSearchBoxWithMatchpath = [
28
45
  {
46
+ type: 'search-input',
29
47
  matchpath: '/search',
30
- buttonTitle: 'Advanced Search',
31
- buttonUrl: undefined,
32
- description: 'Sample description',
33
48
  placeholder: 'Search',
34
- searchSuggestions: {
35
- suggestionsTitle: 'Suggestions Title',
36
- suggestions: ['suggestion 1', 'suggestion 2', 'suggestion 3'],
37
- maxToShow: 3,
38
- },
39
- isDefault: true,
49
+ suggestionsTitle: 'Suggestions Title',
50
+ suggestions: ['suggestion 1', 'suggestion 2', 'suggestion 3'],
51
+ maxToShow: 3,
40
52
  },
41
53
  ];
42
54
 
@@ -50,26 +62,30 @@ describe('HeaderSearchPopUp', () => {
50
62
 
51
63
  it('should render HeaderSearchPopUp', () => {
52
64
  render(
53
- <Router history={history}>
54
- <HeaderSearchPopUp
55
- headerSearchBox={sampleHeaderSearchBox}
56
- onClose={mockOnClose}
57
- triggerRefs={[]}
58
- />
59
- </Router>,
65
+ <Provider store={mockStore}>
66
+ <Router history={history}>
67
+ <HeaderSearchPopUp
68
+ headerSearchBox={sampleHeaderSearchBox}
69
+ onClose={mockOnClose}
70
+ triggerRefs={[]}
71
+ />
72
+ </Router>
73
+ </Provider>,
60
74
  );
61
75
  expect(screen.getByPlaceholderText('Search')).toBeInTheDocument();
62
76
  });
63
77
 
64
78
  it('should update search text on change', () => {
65
79
  render(
66
- <Router history={history}>
67
- <HeaderSearchPopUp
68
- headerSearchBox={sampleHeaderSearchBox}
69
- onClose={mockOnClose}
70
- triggerRefs={[]}
71
- />
72
- </Router>,
80
+ <Provider store={mockStore}>
81
+ <Router history={history}>
82
+ <HeaderSearchPopUp
83
+ headerSearchBox={sampleHeaderSearchBox}
84
+ onClose={mockOnClose}
85
+ triggerRefs={[]}
86
+ />
87
+ </Router>
88
+ </Provider>,
73
89
  );
74
90
  const input = screen.getByPlaceholderText('Search');
75
91
  fireEvent.change(input, { target: { value: 'New text' } });
@@ -80,32 +96,35 @@ describe('HeaderSearchPopUp', () => {
80
96
  window.searchContext = { resetSearch: jest.fn() };
81
97
 
82
98
  const { container } = render(
83
- <Router history={history}>
84
- <HeaderSearchPopUp
85
- headerSearchBox={sampleHeaderSearchBox}
86
- onClose={mockOnClose}
87
- triggerRefs={[]}
88
- />
89
- </Router>,
99
+ <Provider store={mockStore}>
100
+ <Router history={history}>
101
+ <HeaderSearchPopUp
102
+ headerSearchBox={sampleHeaderSearchBox}
103
+ onClose={mockOnClose}
104
+ triggerRefs={[]}
105
+ />
106
+ </Router>
107
+ </Provider>,
90
108
  );
91
109
  const input = screen.getByPlaceholderText('Search');
92
110
  fireEvent.change(input, { target: { value: 'Search text' } });
93
111
  fireEvent.submit(container.querySelector('form'));
94
112
  fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
95
113
  expect(history.location.pathname).toBe('/search');
96
- // expect(history.location.search).toBe('?q=Search text');
97
114
  });
98
115
 
99
116
  it('should navigate to the suggestion when a suggestion is clicked', () => {
100
117
  window.searchContext = { resetSearch: jest.fn() };
101
118
 
102
119
  render(
103
- <Router history={history}>
104
- <HeaderSearchPopUp
105
- headerSearchBox={sampleHeaderSearchBoxWithMatchpath}
106
- onClose={mockOnClose}
107
- />
108
- </Router>,
120
+ <Provider store={mockStore}>
121
+ <Router history={history}>
122
+ <HeaderSearchPopUp
123
+ headerSearchBox={sampleHeaderSearchBoxWithMatchpath}
124
+ onClose={mockOnClose}
125
+ />
126
+ </Router>
127
+ </Provider>,
109
128
  );
110
129
  fireEvent.click(screen.getByText('suggestion 1'));
111
130
  expect(history.location.pathname).toBe('/');
@@ -114,13 +133,15 @@ describe('HeaderSearchPopUp', () => {
114
133
 
115
134
  it('should handle keydown events on search action button', () => {
116
135
  const { container } = render(
117
- <Router history={history}>
118
- <HeaderSearchPopUp
119
- headerSearchBox={sampleHeaderSearchBox}
120
- onClose={mockOnClose}
121
- triggerRefs={[]}
122
- />
123
- </Router>,
136
+ <Provider store={mockStore}>
137
+ <Router history={history}>
138
+ <HeaderSearchPopUp
139
+ headerSearchBox={sampleHeaderSearchBox}
140
+ onClose={mockOnClose}
141
+ triggerRefs={[]}
142
+ />
143
+ </Router>
144
+ </Provider>,
124
145
  );
125
146
 
126
147
  const searchActionButton = container.querySelector(
@@ -128,25 +149,23 @@ describe('HeaderSearchPopUp', () => {
128
149
  );
129
150
  expect(searchActionButton).toBeInTheDocument();
130
151
 
131
- // Test Enter key press on search action button
132
152
  fireEvent.keyDown(searchActionButton, { key: 'Enter', code: 'Enter' });
133
-
134
- // Test other key press (should not trigger action)
135
153
  fireEvent.keyDown(searchActionButton, { key: 'Tab', code: 'Tab' });
136
154
  });
137
155
 
138
156
  it('should handle search without searchContext', () => {
139
- // Remove searchContext to test the fallback
140
157
  delete window.searchContext;
141
158
 
142
159
  const { container } = render(
143
- <Router history={history}>
144
- <HeaderSearchPopUp
145
- headerSearchBox={sampleHeaderSearchBox}
146
- onClose={mockOnClose}
147
- triggerRefs={[]}
148
- />
149
- </Router>,
160
+ <Provider store={mockStore}>
161
+ <Router history={history}>
162
+ <HeaderSearchPopUp
163
+ headerSearchBox={sampleHeaderSearchBox}
164
+ onClose={mockOnClose}
165
+ triggerRefs={[]}
166
+ />
167
+ </Router>
168
+ </Provider>,
150
169
  );
151
170
 
152
171
  const input = screen.getByPlaceholderText('Search');
@@ -157,16 +176,17 @@ describe('HeaderSearchPopUp', () => {
157
176
  });
158
177
 
159
178
  it('should handle suggestion click without searchContext', () => {
160
- // Remove searchContext to test the fallback
161
179
  delete window.searchContext;
162
180
 
163
181
  render(
164
- <Router history={history}>
165
- <HeaderSearchPopUp
166
- headerSearchBox={sampleHeaderSearchBox}
167
- onClose={mockOnClose}
168
- />
169
- </Router>,
182
+ <Provider store={mockStore}>
183
+ <Router history={history}>
184
+ <HeaderSearchPopUp
185
+ headerSearchBox={sampleHeaderSearchBox}
186
+ onClose={mockOnClose}
187
+ />
188
+ </Router>
189
+ </Provider>,
170
190
  );
171
191
 
172
192
  fireEvent.click(screen.getByText('suggestion 1'));
@@ -176,23 +196,27 @@ describe('HeaderSearchPopUp', () => {
176
196
  it('should render without search suggestions', () => {
177
197
  const headerSearchBoxNoSuggestions = [
178
198
  {
199
+ type: 'search-input',
179
200
  path: '/search',
180
- buttonTitle: 'Advanced Search',
181
- buttonUrl: '/advanced-search',
182
- description: 'Sample description',
183
201
  placeholder: 'Search',
184
- isDefault: true,
202
+ },
203
+ {
204
+ type: 'button-link',
205
+ title: 'Advanced Search',
206
+ url: '/advanced-search',
185
207
  },
186
208
  ];
187
209
 
188
210
  render(
189
- <Router history={history}>
190
- <HeaderSearchPopUp
191
- headerSearchBox={headerSearchBoxNoSuggestions}
192
- onClose={mockOnClose}
193
- triggerRefs={[]}
194
- />
195
- </Router>,
211
+ <Provider store={mockStore}>
212
+ <Router history={history}>
213
+ <HeaderSearchPopUp
214
+ headerSearchBox={headerSearchBoxNoSuggestions}
215
+ onClose={mockOnClose}
216
+ triggerRefs={[]}
217
+ />
218
+ </Router>
219
+ </Provider>,
196
220
  );
197
221
 
198
222
  expect(screen.getByPlaceholderText('Search')).toBeInTheDocument();
@@ -202,28 +226,25 @@ describe('HeaderSearchPopUp', () => {
202
226
  it('should render with empty suggestions array', () => {
203
227
  const headerSearchBoxEmptySuggestions = [
204
228
  {
229
+ type: 'search-input',
205
230
  path: '/search',
206
- buttonTitle: 'Advanced Search',
207
- buttonUrl: '/advanced-search',
208
- description: 'Sample description',
209
231
  placeholder: 'Search',
210
- searchSuggestions: {
211
- suggestionsTitle: 'Suggestions Title',
212
- suggestions: [],
213
- maxToShow: 3,
214
- },
215
- isDefault: true,
232
+ suggestionsTitle: 'Suggestions Title',
233
+ suggestions: [],
234
+ maxToShow: 3,
216
235
  },
217
236
  ];
218
237
 
219
238
  render(
220
- <Router history={history}>
221
- <HeaderSearchPopUp
222
- headerSearchBox={headerSearchBoxEmptySuggestions}
223
- onClose={mockOnClose}
224
- triggerRefs={[]}
225
- />
226
- </Router>,
239
+ <Provider store={mockStore}>
240
+ <Router history={history}>
241
+ <HeaderSearchPopUp
242
+ headerSearchBox={headerSearchBoxEmptySuggestions}
243
+ onClose={mockOnClose}
244
+ triggerRefs={[]}
245
+ />
246
+ </Router>
247
+ </Provider>,
227
248
  );
228
249
 
229
250
  expect(screen.getByPlaceholderText('Search')).toBeInTheDocument();
@@ -1,6 +1,7 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" height="20px" viewBox="0 -960 960 960" width="20px">
2
- <path
3
- d="M740-560q-1 0-8-6-16-61-60.5-105.5T566-732q-2-1-6-8 0-2 6-8 61-16 105.5-60.5T732-914q1-2 8-6 2 0 8 6 17 61 61 105.5T914-748q2 0 6 8 0 1-6 8-61 16-105.5 60.5T748-566q0 2-8 6Zm44 440L532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q29 0 57 6t53 18l-10 87q-22-15-47-23t-53-8q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400q66 0 115.5-42.5T557-555l72 50q-7 22-17.5 41T588-428l252 252-56 56Z"
4
- fill="rgba(255,255,255,1)">
5
- </path>
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <svg fill="currentColor" height="20" viewBox="0 -960 960 960" width="20" version="1.1"
3
+ xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
4
+ <path
5
+ d="m 743.91749,-527.97997 q -1.19965,0 -9.59723,-7.19791 -19.19445,-73.17883 -72.57899,-126.56339 -53.38456,-53.38454 -126.56339,-72.57899 -2.39931,-1.19966 -7.19791,-9.59723 0,-2.3993 7.19791,-9.59722 73.17883,-19.19444 126.56339,-72.579 53.38454,-53.38456 72.57899,-126.56338 1.19966,-2.39931 9.59723,-7.19792 2.3993,0 9.59722,7.19792 20.39409,73.17882 73.17882,126.56338 52.78474,53.38456 125.96356,72.579 2.39931,0 7.19792,9.59722 0,1.19965 -7.19792,9.59723 -73.17882,19.19445 -126.56338,72.57899 -53.38456,53.38456 -72.579,126.56339 0,2.39931 -9.59722,7.19791 z M 796.70222,-0.13268868 494.38968,-302.44522 q -35.98958,28.79167 -82.77604,45.58681 -46.78647,16.79514 -99.5712,16.79514 -130.76217,0 -221.335957,-90.5738 -90.57379432,-90.57378 -90.57379432,-221.33595 0,-130.76217 90.57379432,-221.33597 90.573787,-90.57379 221.335957,-90.57379 34.78993,0 68.38021,7.19792 33.59029,7.19792 63.58161,21.59376 l -11.99653,104.36979 q -26.39236,-17.99479 -56.38368,-27.59202 -29.99133,-9.59722 -63.58161,-9.59722 -89.97396,0 -152.95574,62.98177 -62.981779,62.98179 -62.981779,152.95576 0,89.97396 62.981779,152.95574 62.98178,62.98178 152.95574,62.98178 79.1771,0 138.55991,-50.98526 59.38283,-50.98523 73.77866,-134.96094 l 86.375,59.98264 q -8.39756,26.39236 -20.99392,49.18577 -12.59636,22.7934 -28.19184,43.18751 l 302.31253,302.312529 z"
6
+ fill="rgba(255,255,255,1)" style="stroke-width:1" />
6
7
  </svg>