@eeacms/volto-eea-design-system 1.16.0 → 1.18.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/CHANGELOG.md +57 -0
  2. package/docker-compose.yml +5 -1
  3. package/locales/en/LC_MESSAGES/volto.po +14 -0
  4. package/package.json +1 -1
  5. package/src/helpers/index.js +4 -4
  6. package/src/helpers/useClickOutside.test.js +63 -0
  7. package/src/helpers/useFirstVisited.test.js +54 -0
  8. package/src/ui/Accordion/Accordion.stories.js +3 -1
  9. package/src/ui/Accordion/Accordion.stories.test.js +45 -0
  10. package/src/ui/Banner/Banner.test.jsx +292 -0
  11. package/src/ui/CallToAction/CallToAction.stories.test.jsx +69 -0
  12. package/src/ui/Card/Card.stories.test.jsx +78 -0
  13. package/src/ui/Card/IconCard/IconCard.stories.test.jsx +64 -0
  14. package/src/ui/Card/RelatedContent/RelatedContent.jsx +1 -1
  15. package/src/ui/Card/RelatedContent/RelatedContent.stories.jsx +2 -2
  16. package/src/ui/Card/RelatedContent/RelatedContent.stories.test.jsx +65 -0
  17. package/src/ui/Confirm/Confirm.stories.test.js +27 -0
  18. package/src/ui/ContextNavigation/ContextNavigation.stories.test.jsx +170 -0
  19. package/src/ui/Divider/Divider.stories.test.jsx +44 -0
  20. package/src/ui/DownloadLabeledIcon/DownloadLabeledIcon.stories.test.jsx +24 -0
  21. package/src/ui/Footer/Description.test.jsx +11 -0
  22. package/src/ui/Footer/Footer.stories.test.js +131 -0
  23. package/src/ui/Footer/Social.test.jsx +11 -0
  24. package/src/ui/Form/Button/Button.stories.test.jsx +55 -0
  25. package/src/ui/Form/Checkbox.stories.test.js +79 -0
  26. package/src/ui/Form/Dropdown.stories.test.js +24 -0
  27. package/src/ui/Form/Radio.stories.test.js +55 -0
  28. package/src/ui/Form/Textarea.stories.test.js +41 -0
  29. package/src/ui/Form/input.stories.test.js +52 -0
  30. package/src/ui/Grid/ComponentGrid.stories.test.js +21 -0
  31. package/src/ui/Header/Header.stories.test.js +158 -0
  32. package/src/ui/Header/Header.test.jsx +293 -0
  33. package/src/ui/Header/HeaderMenuPopUp.js +12 -4
  34. package/src/ui/Header/HeaderSearchPopUp.test.js +114 -0
  35. package/src/ui/Hero/Hero.stories.test.jsx +67 -0
  36. package/src/ui/InpageNavigation/InpageNavigation.stories.test.jsx +10 -0
  37. package/src/ui/InpageNavigation/InpageNavigation.test.jsx +87 -0
  38. package/src/ui/Item/Item.stories.test.js +39 -0
  39. package/src/ui/Item/ItemGroupWithIcons.stories.test.js +119 -0
  40. package/src/ui/Label/Label.stories.test.js +76 -0
  41. package/src/ui/LabeledIconGroup/LabeledIconGroup.stories.test.jsx +19 -0
  42. package/src/ui/LanguageLabeledIcon/LanguageLabeledIcon.jsx +3 -2
  43. package/src/ui/LanguageLabeledIcon/LanguangeLabeledIcon.test.jsx +60 -0
  44. package/src/ui/Loader/Loader.stories.test.jsx +30 -0
  45. package/src/ui/Logo/Logo.stories.test.jsx +81 -0
  46. package/src/ui/Media/Image.stories.test.js +35 -0
  47. package/src/ui/Message/Message.stories.test.js +44 -0
  48. package/src/ui/Modal/Modal.stories.test.js +45 -0
  49. package/src/ui/Popup/Popup.jsx +24 -17
  50. package/src/ui/Popup/Popup.test.jsx +60 -0
  51. package/src/ui/Progress/Progress.stories.test.js +30 -0
  52. package/src/ui/Quote/Testimonial/Testimonial.stories.test.jsx +18 -0
  53. package/src/ui/Statistic/Statistic.stories.test.js +93 -0
  54. package/src/ui/Table/Table.stories.js +8 -0
  55. package/src/ui/Table/Table.stories.test.js +54 -0
  56. package/src/ui/Timeline/Timeline.stories.test.jsx +43 -0
  57. package/src/ui/index.js +21 -41
  58. package/theme/themes/eea/assets/images/Footer/Extras/footer-visual.svg +1 -2065
  59. package/theme/themes/eea/extras/banner.less +3 -3
  60. package/theme/themes/eea/modules/accordion.overrides +36 -11
  61. package/theme/themes/eea/modules/accordion.variables +2 -0
  62. package/theme/themes/eea/views/item.overrides +21 -0
  63. package/src/i18n.js +0 -180
@@ -0,0 +1,119 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import {
4
+ FlexGroup,
5
+ DefaultGroup,
6
+ DefaultItem,
7
+ } from './ItemGroupWithIcons.stories';
8
+ import '@testing-library/jest-dom/extend-expect';
9
+
10
+ describe('FlexGroup component', () => {
11
+ it('renders correctly', () => {
12
+ const { container, queryAllByText } = render(
13
+ <FlexGroup {...FlexGroup.args} />,
14
+ );
15
+
16
+ expect(
17
+ container.querySelector('.ui.unstackable.items.row.flex-items-wrapper'),
18
+ ).toBeInTheDocument();
19
+ expect(
20
+ container.querySelector('img[src="globe-eco.svg"]'),
21
+ ).toBeInTheDocument();
22
+ expect(
23
+ container.querySelector('img[src="sustainable.svg"]'),
24
+ ).toBeInTheDocument();
25
+ expect(
26
+ container.querySelector('img[src="data-analytics.svg"]'),
27
+ ).toBeInTheDocument();
28
+ expect(
29
+ container.querySelector('img[src="network.svg"]'),
30
+ ).toBeInTheDocument();
31
+ expect(
32
+ container.querySelector('img[src="globe-eco.svg"]'),
33
+ ).toBeInTheDocument();
34
+ expect(
35
+ container.querySelector('img[src="knowledge.svg"]'),
36
+ ).toBeInTheDocument();
37
+
38
+ FlexGroup.args.Items.forEach((item) => {
39
+ expect(queryAllByText(item.description)).not.toBeNull();
40
+ });
41
+ });
42
+ });
43
+
44
+ describe('DefaultGroup component', () => {
45
+ it('renders correctly', () => {
46
+ const { container, queryAllByText } = render(
47
+ <DefaultGroup {...DefaultGroup.args} stackable={true} />,
48
+ );
49
+
50
+ expect(
51
+ container.querySelector('.ui.unstackable.items.row'),
52
+ ).toBeInTheDocument();
53
+ expect(
54
+ container.querySelector('img[src="globe-eco.svg"]'),
55
+ ).toBeInTheDocument();
56
+ expect(
57
+ container.querySelector('img[src="sustainable.svg"]'),
58
+ ).toBeInTheDocument();
59
+ expect(
60
+ container.querySelector('img[src="data-analytics.svg"]'),
61
+ ).toBeInTheDocument();
62
+ expect(
63
+ container.querySelector('img[src="network.svg"]'),
64
+ ).toBeInTheDocument();
65
+ expect(
66
+ container.querySelector('img[src="globe-eco.svg"]'),
67
+ ).toBeInTheDocument();
68
+ expect(
69
+ container.querySelector('img[src="knowledge.svg"]'),
70
+ ).toBeInTheDocument();
71
+
72
+ DefaultGroup.args.ColumnLeft.forEach((item) => {
73
+ expect(queryAllByText(item.description)).not.toBeNull();
74
+ });
75
+ DefaultGroup.args.ColumnRight.forEach((item) => {
76
+ expect(queryAllByText(item.description)).not.toBeNull();
77
+ });
78
+ });
79
+ });
80
+
81
+ describe('DefaultGroup component', () => {
82
+ it('renders correctly', () => {
83
+ const { container, queryAllByText } = render(
84
+ <DefaultGroup {...DefaultGroup.args} mediaType={'icon'} />,
85
+ );
86
+
87
+ expect(
88
+ container.querySelector('.icon.medium.ri-earth-line.secondary'),
89
+ ).toBeInTheDocument();
90
+ expect(
91
+ container.querySelector('.icon.medium.ri-leaf-line.secondary'),
92
+ ).toBeInTheDocument();
93
+ expect(
94
+ container.querySelector('.icon.medium.ri-pie-chart-line.secondary'),
95
+ ).toBeInTheDocument();
96
+ expect(
97
+ container.querySelector('.icon.medium.ri-pin-distance-line.secondary'),
98
+ ).toBeInTheDocument();
99
+ expect(
100
+ container.querySelector('.icon.medium.ri-line-chart-line.secondary'),
101
+ ).toBeInTheDocument();
102
+
103
+ DefaultGroup.args.ColumnLeft.forEach((item) => {
104
+ expect(queryAllByText(item.description)).not.toBeNull();
105
+ });
106
+ DefaultGroup.args.ColumnRight.forEach((item) => {
107
+ expect(queryAllByText(item.description)).not.toBeNull();
108
+ });
109
+ });
110
+ });
111
+
112
+ describe('DefaultItem component', () => {
113
+ it('renders correctly', () => {
114
+ const { container } = render(<DefaultItem {...DefaultItem.args} />);
115
+ expect(
116
+ container.querySelector('.ui.unstackable.items.row'),
117
+ ).toBeInTheDocument();
118
+ });
119
+ });
@@ -0,0 +1,76 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { Default, Basic, Corner, Ribbon } from './Label.stories';
4
+ import '@testing-library/jest-dom/extend-expect';
5
+
6
+ describe('Basic component', () => {
7
+ it('renders correctly', () => {
8
+ const { getByText } = render(<Basic {...Basic.args} />);
9
+ expect(getByText(Basic.args.content)).toBeInTheDocument();
10
+ });
11
+
12
+ it('renders correctly', () => {
13
+ const { getByText } = render(<Basic {...Basic.args} importance={true} />);
14
+ expect(getByText(Basic.args.content)).toBeInTheDocument();
15
+ });
16
+ });
17
+
18
+ describe('Corner component', () => {
19
+ it('renders correctly', () => {
20
+ const { container } = render(<Corner {...Corner.args} />);
21
+ expect(
22
+ container.querySelector(
23
+ 'img[src="https://react.semantic-ui.com/images/wireframe/image.png"]',
24
+ ),
25
+ ).toBeInTheDocument();
26
+ });
27
+
28
+ it('renders correctly', () => {
29
+ const { container } = render(<Corner importance={true} />);
30
+ expect(
31
+ container.querySelector(
32
+ 'img[src="https://react.semantic-ui.com/images/wireframe/image.png"]',
33
+ ),
34
+ ).toBeInTheDocument();
35
+ });
36
+ });
37
+
38
+ describe('Ribbon component', () => {
39
+ it('renders correctly', () => {
40
+ const { container, getByText } = render(<Ribbon {...Ribbon.args} />);
41
+ expect(getByText('Ribbon Label')).toBeInTheDocument();
42
+ expect(container.querySelector('.ribbon.label')).toBeInTheDocument();
43
+ expect(
44
+ container.querySelector(
45
+ 'img[src="https://react.semantic-ui.com/images/wireframe/paragraph.png"]',
46
+ ),
47
+ ).toBeInTheDocument();
48
+ });
49
+
50
+ it('renders correctly', () => {
51
+ const { container, getByText } = render(
52
+ <Ribbon {...Ribbon.args} importance={true} />,
53
+ );
54
+ expect(getByText('Ribbon Label')).toBeInTheDocument();
55
+ expect(container.querySelector('.ribbon.label')).toBeInTheDocument();
56
+ expect(
57
+ container.querySelector(
58
+ 'img[src="https://react.semantic-ui.com/images/wireframe/paragraph.png"]',
59
+ ),
60
+ ).toBeInTheDocument();
61
+ });
62
+ });
63
+
64
+ describe('Default component', () => {
65
+ it('renders correctly', () => {
66
+ const { getByText } = render(<Default {...Default.args} />);
67
+ expect(getByText(Default.args.content)).toBeInTheDocument();
68
+ });
69
+
70
+ it('renders correctly', () => {
71
+ const { getByText } = render(
72
+ <Default {...Default.args} importance={true} />,
73
+ );
74
+ expect(getByText(Default.args.content)).toBeInTheDocument();
75
+ });
76
+ });
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { Default } from './LabeledIconGroup.stories';
4
+ import '@testing-library/jest-dom/extend-expect';
5
+
6
+ describe('Default component', () => {
7
+ it('renders corectly', () => {
8
+ const { container, getByText } = render(<Default {...Default.args} />);
9
+
10
+ expect(container.querySelector('.ri-share-box-fill')).toBeInTheDocument();
11
+ expect(getByText('Open in new Tab')).toBeInTheDocument();
12
+
13
+ expect(container.querySelector('.ri-download-2-fill')).toBeInTheDocument();
14
+ expect(getByText('Download')).toBeInTheDocument();
15
+
16
+ expect(container.querySelector('.ri-global-line')).toBeInTheDocument();
17
+ expect(getByText('Language')).toBeInTheDocument();
18
+ });
19
+ });
@@ -1,5 +1,6 @@
1
1
  import React, { useState, useContext, createContext } from 'react';
2
2
  import { Popup } from 'semantic-ui-react';
3
+ import noop from 'lodash/noop';
3
4
 
4
5
  const LanguageContext = createContext();
5
6
 
@@ -59,7 +60,7 @@ const Dropdown = ({ children, ...rest }) => {
59
60
  <li key={index}>
60
61
  <div
61
62
  onClick={() => context.setLanguage(item.code.toUpperCase())}
62
- onKeyDown={() => context.setHidden(!context.hidden)}
63
+ onKeyDown={noop}
63
64
  role="button"
64
65
  tabIndex={0}
65
66
  >
@@ -73,7 +74,7 @@ const Dropdown = ({ children, ...rest }) => {
73
74
  <li key={index}>
74
75
  <div
75
76
  onClick={() => context.setLanguage(item.code.toUpperCase())}
76
- onKeyDown={() => context.setHidden(!context.hidden)}
77
+ onKeyDown={noop}
77
78
  role="button"
78
79
  tabIndex={0}
79
80
  >
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import { render, fireEvent } from '@testing-library/react';
3
+ import LanguageLabeledIcon from './LanguageLabeledIcon';
4
+ import '@testing-library/jest-dom/extend-expect';
5
+
6
+ jest.mock('semantic-ui-react', () => {
7
+ return {
8
+ Popup: ({ trigger, content }) => <div>{content}</div>,
9
+ };
10
+ });
11
+
12
+ const items = [
13
+ {
14
+ code: 'en',
15
+ name: 'English',
16
+ },
17
+ {
18
+ code: 'ro',
19
+ name: 'Romania',
20
+ },
21
+ ];
22
+
23
+ describe('LanguageLabeledIcon component', () => {
24
+ it('renders corectly', () => {
25
+ render(<LanguageLabeledIcon />);
26
+ });
27
+
28
+ it('renders languages dropdown', () => {
29
+ const { getByText } = render(
30
+ <>
31
+ <LanguageLabeledIcon>
32
+ <LanguageLabeledIcon.Dropdown items={items} />
33
+ <LanguageLabeledIcon.Label>
34
+ <p>Test</p>
35
+ </LanguageLabeledIcon.Label>
36
+ </LanguageLabeledIcon>
37
+ </>,
38
+ );
39
+
40
+ expect(getByText('English')).toBeInTheDocument();
41
+ expect(getByText('Romania')).toBeInTheDocument();
42
+ expect(getByText('Test')).toBeInTheDocument();
43
+
44
+ fireEvent.click(getByText('EN'));
45
+ fireEvent.click(getByText('RO'));
46
+ });
47
+
48
+ it('renders languages dropdown', () => {
49
+ const { getByText } = render(
50
+ <>
51
+ <LanguageLabeledIcon>
52
+ <LanguageLabeledIcon.Icon icon={'testIcon'} />
53
+ </LanguageLabeledIcon>
54
+ </>,
55
+ );
56
+
57
+ expect(getByText('EN')).toBeInTheDocument();
58
+ expect(getByText('testIcon')).toBeInTheDocument();
59
+ });
60
+ });
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { FullPageLoader, Default } from './Loader.stories';
4
+ import '@testing-library/jest-dom/extend-expect';
5
+
6
+ describe('FullPageLoader component', () => {
7
+ it('renders corectly', () => {
8
+ const { container, getByText } = render(
9
+ <FullPageLoader {...FullPageLoader.args} />,
10
+ );
11
+
12
+ expect(container.querySelector('.dimmer .loader')).toBeInTheDocument();
13
+ expect(getByText(FullPageLoader.args.content)).toBeInTheDocument();
14
+ expect(
15
+ container.querySelector(
16
+ 'img[src="https://react.semantic-ui.com/images/wireframe/short-paragraph.png"]',
17
+ ),
18
+ ).toBeInTheDocument();
19
+ });
20
+ });
21
+
22
+ describe('Default component', () => {
23
+ it('renders corectly', () => {
24
+ const { container } = render(<Default {...Default.args} />);
25
+
26
+ expect(
27
+ container.querySelector(`.${Default.args.size}.active`),
28
+ ).toBeInTheDocument();
29
+ });
30
+ });
@@ -0,0 +1,81 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { Logo } from './Logo.stories';
4
+ import { createMemoryHistory } from 'history';
5
+ import { Router } from 'react-router-dom';
6
+ import '@testing-library/jest-dom/extend-expect';
7
+
8
+ describe('FluidGrid component', () => {
9
+ let history;
10
+ beforeEach(() => {
11
+ history = createMemoryHistory();
12
+ });
13
+ it('renders the correct logo', () => {
14
+ const { container } = render(
15
+ <Router history={history}>
16
+ <Logo {...Logo.args} />
17
+ </Router>,
18
+ );
19
+
20
+ expect(
21
+ container.querySelector(`a[href="/${Logo.args.url}"]`),
22
+ ).toBeInTheDocument();
23
+ });
24
+
25
+ it('renders the correct logo', () => {
26
+ const { container } = render(
27
+ <Router history={history}>
28
+ <Logo
29
+ {...Logo.args}
30
+ site={'Biodiversity Information System for Europe'}
31
+ />
32
+ </Router>,
33
+ );
34
+
35
+ expect(
36
+ container.querySelector(`a[href="/https://biodiversity.europa.eu/"]`),
37
+ ).toBeInTheDocument();
38
+ });
39
+
40
+ it('renders the correct logo', () => {
41
+ const { container } = render(
42
+ <Router history={history}>
43
+ <Logo
44
+ {...Logo.args}
45
+ site={'Marine Water Information System for Europe'}
46
+ />
47
+ </Router>,
48
+ );
49
+
50
+ expect(
51
+ container.querySelector(`a[href="/https://water.europa.eu/marine"]`),
52
+ ).toBeInTheDocument();
53
+ });
54
+
55
+ it('renders the correct logo', () => {
56
+ const { container } = render(
57
+ <Router history={history}>
58
+ <Logo {...Logo.args} site={'Forest Information System for Europe'} />
59
+ </Router>,
60
+ );
61
+
62
+ expect(
63
+ container.querySelector(`a[href="/https://forest.eea.europa.eu/"]`),
64
+ ).toBeInTheDocument();
65
+ });
66
+
67
+ it('renders the correct logo', () => {
68
+ const { container } = render(
69
+ <Router history={history}>
70
+ <Logo
71
+ {...Logo.args}
72
+ site={'Fresh Water Information System for Europe'}
73
+ />
74
+ </Router>,
75
+ );
76
+
77
+ expect(
78
+ container.querySelector(`a[href="/https://water.europa.eu/freshwater"]`),
79
+ ).toBeInTheDocument();
80
+ });
81
+ });
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { Playground, Link, Default } from './Image.stories';
4
+ import '@testing-library/jest-dom/extend-expect';
5
+
6
+ describe('Playground component', () => {
7
+ it('renders correctly', () => {
8
+ const { container } = render(<Playground {...Playground.args} />);
9
+
10
+ expect(
11
+ container.querySelector('img[alt="playground image"]'),
12
+ ).toBeInTheDocument();
13
+ });
14
+ });
15
+
16
+ describe('Link component', () => {
17
+ it('renders correctly', () => {
18
+ const { container } = render(<Link {...Link.args} />);
19
+
20
+ expect(
21
+ container.querySelector(`a[href="${Link.args.href}"]`),
22
+ ).toBeInTheDocument();
23
+ expect(
24
+ container.querySelector('img[alt="link image"]'),
25
+ ).toBeInTheDocument();
26
+ });
27
+ });
28
+
29
+ describe('Default component', () => {
30
+ it('renders correctly', () => {
31
+ const { container } = render(<Default {...Default.args} />);
32
+
33
+ expect(container.querySelector('img[alt="image"]')).toBeInTheDocument();
34
+ });
35
+ });
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { Info, Error, Warning, Success, Default } from './Message.stories';
4
+ import '@testing-library/jest-dom/extend-expect';
5
+
6
+ describe('Info component', () => {
7
+ it('renders a Message component', () => {
8
+ const { getByText } = render(<Info {...Info.args} />);
9
+ expect(getByText(Info.args.header)).toBeInTheDocument();
10
+ expect(getByText(Info.args.content)).toBeInTheDocument();
11
+ });
12
+ });
13
+
14
+ describe('Error component', () => {
15
+ it('renders a Message component', () => {
16
+ const { getByText } = render(<Error {...Error.args} />);
17
+ expect(getByText(Error.args.header)).toBeInTheDocument();
18
+ expect(getByText(Error.args.content)).toBeInTheDocument();
19
+ });
20
+ });
21
+
22
+ describe('Warning component', () => {
23
+ it('renders a Message component', () => {
24
+ const { getByText } = render(<Warning {...Warning.args} />);
25
+ expect(getByText(Warning.args.header)).toBeInTheDocument();
26
+ expect(getByText(Warning.args.content)).toBeInTheDocument();
27
+ });
28
+ });
29
+
30
+ describe('Success component', () => {
31
+ it('renders a Message component', () => {
32
+ const { getByText } = render(<Success {...Success.args} />);
33
+ expect(getByText(Success.args.header)).toBeInTheDocument();
34
+ expect(getByText(Success.args.content)).toBeInTheDocument();
35
+ });
36
+ });
37
+
38
+ describe('Default component', () => {
39
+ it('renders a Message component', () => {
40
+ const { getByText } = render(<Default {...Default.args} />);
41
+ expect(getByText(Default.args.header)).toBeInTheDocument();
42
+ expect(getByText(Default.args.content)).toBeInTheDocument();
43
+ });
44
+ });
@@ -0,0 +1,45 @@
1
+ import { render, fireEvent } from '@testing-library/react';
2
+ import { Default } from './Modal.stories';
3
+ import { Button } from 'semantic-ui-react';
4
+ import '@testing-library/jest-dom/extend-expect';
5
+
6
+ describe('Default component', () => {
7
+ it('renders corectly', () => {
8
+ const { getByText } = render(<Default {...Default.args} />);
9
+
10
+ expect(getByText('Show Modal')).toBeInTheDocument();
11
+ fireEvent.click(getByText('Show Modal'));
12
+ expect(getByText('Modal Content')).toBeInTheDocument();
13
+ expect(getByText('No')).toBeInTheDocument();
14
+ expect(getByText('Yes')).toBeInTheDocument();
15
+
16
+ fireEvent.click(getByText('No'));
17
+ fireEvent.click(getByText('Show Modal'));
18
+ // fireEvent.click(
19
+ // container.querySelector('button[title="Close modal dialog"]'),
20
+ // );
21
+ });
22
+
23
+ it('renders corectly', () => {
24
+ const { getByText } = render(
25
+ <Default
26
+ header={'Modal Header'}
27
+ content={'Modal Content'}
28
+ size={'mini'}
29
+ trigger={<Button primary>Show Modal</Button>}
30
+ />,
31
+ );
32
+
33
+ expect(getByText('Show Modal')).toBeInTheDocument();
34
+ fireEvent.click(getByText('Show Modal'));
35
+ expect(getByText('Modal Content')).toBeInTheDocument();
36
+ expect(getByText('No')).toBeInTheDocument();
37
+ expect(getByText('Yes')).toBeInTheDocument();
38
+
39
+ fireEvent.click(getByText('Yes'));
40
+ fireEvent.click(getByText('Show Modal'));
41
+ // fireEvent.click(
42
+ // container.querySelector('button[title="Close modal dialog"]'),
43
+ // );
44
+ });
45
+ });
@@ -18,7 +18,6 @@ function Popup(props) {
18
18
  const triggerRef = useRef(null);
19
19
  const popupRef = useRef(null);
20
20
  const [isOpen, setIsOpen] = useState(false);
21
-
22
21
  const options = {
23
22
  placement: positionsMapping[props.position] || 'bottom-end',
24
23
  strategy: props.positionFixed || 'absolute',
@@ -33,12 +32,19 @@ function Popup(props) {
33
32
  ],
34
33
  };
35
34
 
36
- const { styles, attributes } = usePopper(
35
+ const { styles, attributes, update } = usePopper(
37
36
  triggerRef.current,
38
37
  popupRef.current,
39
38
  options,
40
39
  );
41
40
 
41
+ useEffect(() => {
42
+ const updatePlacement = async () => {
43
+ if (typeof update === 'function') await update();
44
+ };
45
+ updatePlacement();
46
+ }, [isOpen, update]);
47
+
42
48
  const handleClickOutside = (event) => {
43
49
  if (
44
50
  popupRef.current &&
@@ -72,7 +78,6 @@ function Popup(props) {
72
78
  const { trigger, className, size, position, basic, content, on } = props;
73
79
 
74
80
  const onEvent = 'on' + on.charAt(0).toUpperCase() + on.slice(1);
75
-
76
81
  return (
77
82
  <React.Fragment>
78
83
  {trigger && (
@@ -90,20 +95,22 @@ function Popup(props) {
90
95
  {...attributes.popper}
91
96
  >
92
97
  {isOpen && <EventStack name="keydown" on={closeOnEscape} />}
93
- <React.Fragment>
94
- <div
95
- className={cx(
96
- 'ui popup transition',
97
- className,
98
- size,
99
- position,
100
- basic ? 'basic' : '',
101
- isOpen ? 'visible' : '',
102
- )}
103
- >
104
- {content}
105
- </div>
106
- </React.Fragment>
98
+ {isOpen && (
99
+ <React.Fragment>
100
+ <div
101
+ className={cx(
102
+ 'ui popup transition',
103
+ className,
104
+ size,
105
+ position,
106
+ basic ? 'basic' : '',
107
+ 'visible',
108
+ )}
109
+ >
110
+ {content}
111
+ </div>
112
+ </React.Fragment>
113
+ )}
107
114
  </div>
108
115
  </React.Fragment>
109
116
  );
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import { render, fireEvent } from '@testing-library/react';
3
+ import Popup from './Popup';
4
+ import '@testing-library/jest-dom/extend-expect';
5
+
6
+ jest.mock('@popperjs/core', () => {
7
+ const originalModule = jest.requireActual('@popperjs/core');
8
+
9
+ return {
10
+ ...originalModule,
11
+ createPopper: jest.fn(() => ({
12
+ forceUpdate: jest.fn(),
13
+ destroy: jest.fn(),
14
+ })),
15
+ };
16
+ });
17
+
18
+ describe('Popup', () => {
19
+ const MockTrigger = ({ onClick }) => (
20
+ <button onClick={onClick}>Trigger</button>
21
+ );
22
+
23
+ it('should render the popup trigger', () => {
24
+ const { getByText } = render(
25
+ <Popup trigger={<MockTrigger />} content="Popup content" />,
26
+ );
27
+ expect(getByText('Trigger')).toBeInTheDocument();
28
+ });
29
+
30
+ it('should render the popup trigger', () => {
31
+ const { getByText } = render(
32
+ <Popup
33
+ position={'other'}
34
+ basic={true}
35
+ trigger={<MockTrigger />}
36
+ content="Popup content"
37
+ />,
38
+ );
39
+ expect(getByText('Trigger')).toBeInTheDocument();
40
+ });
41
+
42
+ it('should open and close the popup when the trigger is clicked', () => {
43
+ const { getByText } = render(
44
+ <Popup trigger={<MockTrigger />} content="Popup content" />,
45
+ );
46
+ fireEvent.click(getByText('Trigger'));
47
+ expect(getByText('Popup content')).toBeVisible();
48
+ });
49
+
50
+ it('should close the popup when the Escape key is pressed', () => {
51
+ const { getByText } = render(
52
+ <Popup trigger={<MockTrigger />} content="Popup content" />,
53
+ );
54
+ fireEvent.click(getByText('Trigger'));
55
+ expect(getByText('Popup content')).toBeVisible();
56
+
57
+ fireEvent.keyDown(document.body, { key: 'Enter' });
58
+ fireEvent.keyDown(document.body, { key: 'Escape' });
59
+ });
60
+ });