@lumx/react 3.3.1-alpha.0 → 3.3.1

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 (117) hide show
  1. package/_internal/ClickAwayProvider.js.map +1 -1
  2. package/_internal/types.d.ts +0 -2
  3. package/index.d.ts +2 -0
  4. package/index.js +347 -75
  5. package/index.js.map +1 -1
  6. package/package.json +23 -19
  7. package/src/components/autocomplete/Autocomplete.test.tsx +55 -142
  8. package/src/components/autocomplete/AutocompleteMultiple.test.tsx +37 -75
  9. package/src/components/autocomplete/__mockData__/index.ts +6 -1
  10. package/src/components/badge/Badge.test.tsx +20 -64
  11. package/src/components/button/Button.test.tsx +44 -121
  12. package/src/components/button/ButtonGroup.test.tsx +16 -39
  13. package/src/components/button/IconButton.stories.tsx +7 -0
  14. package/src/components/button/IconButton.test.tsx +37 -78
  15. package/src/components/button/IconButton.tsx +8 -1
  16. package/src/components/checkbox/Checkbox.test.tsx +62 -67
  17. package/src/components/chip/Chip.test.tsx +89 -139
  18. package/src/components/chip/ChipGroup.test.tsx +27 -10
  19. package/src/components/date-picker/DatePicker.test.tsx +15 -23
  20. package/src/components/date-picker/DatePickerControlled.test.tsx +24 -20
  21. package/src/components/date-picker/DatePickerField.test.tsx +43 -27
  22. package/src/components/dialog/Dialog.test.tsx +36 -35
  23. package/src/components/divider/Divider.test.tsx +23 -69
  24. package/src/components/dropdown/Dropdown.test.tsx +30 -61
  25. package/src/components/expansion-panel/ExpansionPanel.test.tsx +12 -8
  26. package/src/components/flag/Flag.test.tsx +28 -53
  27. package/src/components/generic-block/GenericBlock.test.tsx +93 -89
  28. package/src/components/grid-column/GridColumn.stories.tsx +3 -3
  29. package/src/components/icon/Icon.test.tsx +80 -64
  30. package/src/components/index.ts +0 -2
  31. package/src/components/inline-list/InlineList.test.tsx +30 -17
  32. package/src/components/input-helper/InputHelper.test.tsx +21 -81
  33. package/src/components/input-label/InputLabel.test.tsx +19 -61
  34. package/src/components/lightbox/Lightbox.test.tsx +3 -2
  35. package/src/components/link/Link.test.tsx +47 -31
  36. package/src/components/link-preview/LinkPreview.test.tsx +51 -51
  37. package/src/components/message/Message.test.tsx +31 -52
  38. package/src/components/mosaic/Mosaic.test.tsx +56 -72
  39. package/src/components/notification/Notification.test.tsx +51 -82
  40. package/src/components/popover/Popover.tsx +7 -9
  41. package/src/components/progress-tracker/ProgressTracker.test.tsx +20 -33
  42. package/src/components/progress-tracker/ProgressTrackerProvider.test.tsx +61 -36
  43. package/src/components/progress-tracker/ProgressTrackerStep.test.tsx +19 -109
  44. package/src/components/progress-tracker/ProgressTrackerStepPanel.test.tsx +21 -58
  45. package/src/components/progress-tracker/ProgressTrackerStepPanel.tsx +1 -1
  46. package/src/components/radio-button/RadioButton.test.tsx +78 -92
  47. package/src/components/radio-button/RadioGroup.test.tsx +13 -59
  48. package/src/components/select/Select.test.tsx +115 -284
  49. package/src/components/select/SelectMultiple.stories.tsx +105 -2
  50. package/src/components/select/SelectMultiple.test.tsx +126 -322
  51. package/src/components/select/WithSelectContext.tsx +10 -4
  52. package/src/components/side-navigation/SideNavigation.test.tsx +22 -35
  53. package/src/components/side-navigation/SideNavigationItem.test.tsx +72 -139
  54. package/src/components/switch/Switch.test.tsx +70 -149
  55. package/src/components/table/Table.test.tsx +2 -0
  56. package/src/components/table/TableBody.test.tsx +18 -8
  57. package/src/components/table/TableCell.test.tsx +34 -9
  58. package/src/components/table/TableHeader.test.tsx +18 -8
  59. package/src/components/table/TableRow.test.tsx +28 -8
  60. package/src/components/tabs/Tab.test.tsx +27 -96
  61. package/src/components/tabs/TabList.test.tsx +21 -56
  62. package/src/components/tabs/TabPanel.test.tsx +20 -55
  63. package/src/components/tabs/TabPanel.tsx +1 -1
  64. package/src/components/tabs/TabProvider.test.tsx +158 -37
  65. package/src/components/tabs/test-utils.ts +39 -0
  66. package/src/components/text-field/TextField.stories.tsx +14 -5
  67. package/src/components/text-field/TextField.test.tsx +54 -8
  68. package/src/components/text-field/TextField.tsx +49 -5
  69. package/src/components/tooltip/Tooltip.test.tsx +134 -75
  70. package/src/components/tooltip/useInjectTooltipRef.tsx +9 -2
  71. package/src/components/uploader/Uploader.test.tsx +60 -48
  72. package/src/components/user-block/UserBlock.test.tsx +69 -13
  73. package/src/hooks/useFocusTrap.ts +2 -2
  74. package/src/testing/utils/commonTestsSuiteRTL.ts +18 -8
  75. package/src/testing/utils/index.ts +0 -1
  76. package/src/utils/flattenChildren.ts +5 -0
  77. package/src/components/autocomplete/__snapshots__/Autocomplete.test.tsx.snap +0 -213
  78. package/src/components/autocomplete/__snapshots__/AutocompleteMultiple.test.tsx.snap +0 -88
  79. package/src/components/badge/__snapshots__/Badge.test.tsx.snap +0 -11
  80. package/src/components/button/ButtonRoot.test.tsx +0 -203
  81. package/src/components/button/__snapshots__/Button.test.tsx.snap +0 -96
  82. package/src/components/button/__snapshots__/ButtonGroup.test.tsx.snap +0 -22
  83. package/src/components/button/__snapshots__/ButtonRoot.test.tsx.snap +0 -160
  84. package/src/components/button/__snapshots__/IconButton.test.tsx.snap +0 -83
  85. package/src/components/checkbox/__snapshots__/Checkbox.test.tsx.snap +0 -141
  86. package/src/components/chip/__snapshots__/Chip.test.tsx.snap +0 -12
  87. package/src/components/chip/__snapshots__/ChipGroup.test.tsx.snap +0 -29
  88. package/src/components/date-picker/__snapshots__/DatePicker.test.tsx.snap +0 -22
  89. package/src/components/date-picker/__snapshots__/DatePickerControlled.test.tsx.snap +0 -597
  90. package/src/components/date-picker/__snapshots__/DatePickerField.test.tsx.snap +0 -43
  91. package/src/components/divider/__snapshots__/Divider.test.tsx.snap +0 -9
  92. package/src/components/dropdown/__snapshots__/Dropdown.test.tsx.snap +0 -35
  93. package/src/components/icon/__snapshots__/Icon.test.tsx.snap +0 -49
  94. package/src/components/input-helper/__snapshots__/InputHelper.test.tsx.snap +0 -9
  95. package/src/components/input-label/__snapshots__/InputLabel.test.tsx.snap +0 -10
  96. package/src/components/link/__snapshots__/Link.test.tsx.snap +0 -29
  97. package/src/components/message/__snapshots__/Message.test.tsx.snap +0 -15
  98. package/src/components/notification/__snapshots__/Notification.test.tsx.snap +0 -34
  99. package/src/components/progress-tracker/__snapshots__/ProgressTracker.test.tsx.snap +0 -41
  100. package/src/components/progress-tracker/__snapshots__/ProgressTrackerStep.test.tsx.snap +0 -141
  101. package/src/components/progress-tracker/__snapshots__/ProgressTrackerStepPanel.test.tsx.snap +0 -25
  102. package/src/components/radio-button/__snapshots__/RadioButton.test.tsx.snap +0 -113
  103. package/src/components/radio-button/__snapshots__/RadioGroup.test.tsx.snap +0 -26
  104. package/src/components/select/__snapshots__/Select.test.tsx.snap +0 -43
  105. package/src/components/select/__snapshots__/SelectMultiple.test.tsx.snap +0 -87
  106. package/src/components/side-navigation/__snapshots__/SideNavigation.test.tsx.snap +0 -7
  107. package/src/components/side-navigation/__snapshots__/SideNavigationItem.test.tsx.snap +0 -30
  108. package/src/components/switch/__snapshots__/Switch.test.tsx.snap +0 -179
  109. package/src/components/tabs/__snapshots__/Tab.test.tsx.snap +0 -62
  110. package/src/components/tabs/__snapshots__/TabList.test.tsx.snap +0 -22
  111. package/src/components/tabs/__snapshots__/TabPanel.test.tsx.snap +0 -25
  112. package/src/components/tabs/test.mocks.ts +0 -33
  113. package/src/components/text-field/__snapshots__/TextField.test.tsx.snap +0 -42
  114. package/src/components/tooltip/__snapshots__/Tooltip.test.tsx.snap +0 -233
  115. package/src/components/uploader/__snapshots__/Uploader.test.tsx.snap +0 -14
  116. package/src/testing/utils/commonTestsSuite.ts +0 -71
  117. package/src/utils/flattenChildren.test.tsx +0 -58
@@ -1,89 +1,73 @@
1
- import { Mosaic, MosaicProps } from '@lumx/react/components/mosaic/Mosaic';
2
- import { commonTestsSuite, Wrapper } from '@lumx/react/testing/utils';
3
-
4
- import { mount, shallow } from 'enzyme';
5
- import 'jest-enzyme';
1
+ import React from 'react';
6
2
 
7
- import React, { ReactElement } from 'react';
8
- import { Theme } from '..';
3
+ import { Mosaic, MosaicProps } from '@lumx/react/components/mosaic/Mosaic';
4
+ import { render, screen, within } from '@testing-library/react';
5
+ import { getByClassName, queryAllByClassName, queryByClassName } from '@lumx/react/testing/utils/queries';
6
+ import { Thumbnail } from '@lumx/react';
7
+ import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
8
+ import range from 'lodash/range';
9
+ import userEvent from '@testing-library/user-event';
9
10
 
10
11
  const CLASSNAME = Mosaic.className as string;
11
12
 
12
- // Mock out the useIntersectionObserver hook since it can't work with Jest/Enzyme.
13
- jest.mock('@lumx/react/hooks/useIntersectionObserver', () => ({
14
- useIntersectionObserver: () => new Map(),
15
- }));
16
-
17
- type SetupProps = Partial<MosaicProps>;
18
-
19
- const setup = (propsOverride: SetupProps = {}, shallowRendering = true) => {
20
- const props: any = { ...propsOverride };
21
- const renderer: (el: ReactElement) => Wrapper = shallowRendering ? shallow : mount;
22
- const wrapper = renderer(<Mosaic {...props} />);
23
-
24
- return {
25
- thumbnails: wrapper.find('Thumbnail'),
26
- props,
27
- wrapper,
28
- };
13
+ const setup = (props: Partial<MosaicProps> = {}) => {
14
+ render(<Mosaic thumbnails={[]} {...props} />);
15
+ const mosaic = getByClassName(document.body, CLASSNAME);
16
+ const thumbnails = queryAllByClassName(mosaic, Thumbnail.className as string);
17
+ const overlay = queryByClassName(mosaic, `${CLASSNAME}__overlay`);
18
+ return { props, mosaic, thumbnails, overlay };
29
19
  };
30
20
 
21
+ const generateThumbnails = (count: number) =>
22
+ range(1, count + 1).map((i) => ({
23
+ image: `https://example.com/image${i}.png`,
24
+ alt: '',
25
+ }));
26
+
31
27
  describe(`<${Mosaic.displayName}>`, () => {
32
- describe('Props', () => {
33
- it('should pass theme prop to Thumbnails', () => {
34
- const expectedTheme = Theme.dark;
35
- const { thumbnails } = setup({
36
- theme: expectedTheme,
37
- thumbnails: [
38
- { alt: 'image0', image: 'image/file/path/0' },
39
- { alt: 'image1', image: 'image/file/path/1' },
40
- { alt: 'image2', image: 'image/file/path/2' },
41
- { alt: 'image3', image: 'image/file/path/3' },
42
- ],
43
- });
44
- thumbnails.forEach((thumbnail: Wrapper) => {
45
- expect(thumbnail.prop('theme')).toBe(expectedTheme);
46
- });
28
+ it.each([1, 2, 3, 4])('should render %s thumbnail', async (count) => {
29
+ const { mosaic, thumbnails } = setup({
30
+ thumbnails: generateThumbnails(count),
47
31
  });
32
+ expect(mosaic).toHaveClass(`${CLASSNAME}--has-${count}-thumbnail${count > 1 ? 's' : ''}`);
33
+ expect(thumbnails.length).toBe(count);
34
+ for (const thumbnail of thumbnails) {
35
+ expect(within(thumbnail).queryByRole('img')).toBeInTheDocument();
36
+ }
48
37
  });
49
38
 
50
- describe('Events', () => {
51
- it('should keep Thumbnail onClick', () => {
52
- const onClick = jest.fn();
53
- const { thumbnails } = setup({
54
- thumbnails: [
55
- { alt: 'image0', image: 'image/file/path/0', onClick },
56
- { alt: 'image1', image: 'image/file/path/1' },
57
- { alt: 'image2', image: 'image/file/path/2' },
58
- { alt: 'image3', image: 'image/file/path/3' },
59
- ],
60
- });
61
- thumbnails.forEach((thumbnail: Wrapper) => {
62
- thumbnail.simulate('click');
63
- });
64
- expect(onClick).toHaveBeenCalledTimes(1);
39
+ it('should render more than 4 thumbnails', () => {
40
+ const { mosaic, thumbnails, overlay } = setup({
41
+ thumbnails: generateThumbnails(6),
65
42
  });
43
+ expect(mosaic).toHaveClass(`${CLASSNAME}--has-4-thumbnails`);
44
+ expect(thumbnails.length).toBe(4);
45
+ expect(overlay).toBeInTheDocument();
46
+ expect(overlay).toHaveTextContent('+2');
47
+ });
66
48
 
67
- it('should handle both Thumbnail onClick and Mosaic onImageClick', () => {
68
- const onImageClick = jest.fn();
69
- const onClick = jest.fn();
70
- const { thumbnails } = setup({
71
- onImageClick,
72
- thumbnails: [
73
- { alt: 'image0', image: 'image/file/path/0', onClick },
74
- { alt: 'image1', image: 'image/file/path/1' },
75
- { alt: 'image2', image: 'image/file/path/2' },
76
- { alt: 'image3', image: 'image/file/path/3' },
77
- ],
78
- });
79
- thumbnails.forEach((thumbnail: Wrapper) => {
80
- thumbnail.simulate('click');
81
- });
82
- expect(onClick).toHaveBeenCalledTimes(1);
83
- expect(onImageClick).toHaveBeenCalledTimes(4);
49
+ it('should render clickable', async () => {
50
+ const onClick = jest.fn();
51
+ const onImageClick = jest.fn();
52
+ const { thumbnails } = setup({
53
+ thumbnails: generateThumbnails(6),
54
+ onImageClick,
55
+ onClick,
84
56
  });
57
+
58
+ expect(screen.queryAllByRole('button').length).toBe(thumbnails.length);
59
+
60
+ // Click the third image
61
+ await userEvent.click(thumbnails[2]);
62
+ expect(onImageClick).toHaveBeenCalledWith(2);
63
+ expect(onClick).toHaveBeenCalled();
85
64
  });
86
65
 
87
66
  // Common tests suite.
88
- commonTestsSuite(setup, { className: 'wrapper' }, { className: CLASSNAME });
67
+ commonTestsSuiteRTL(setup, {
68
+ baseClassName: CLASSNAME,
69
+ forwardClassName: 'mosaic',
70
+ forwardAttributes: 'mosaic',
71
+ forwardRef: 'mosaic',
72
+ });
89
73
  });
@@ -1,108 +1,77 @@
1
- import React, { ReactElement } from 'react';
1
+ import React from 'react';
2
2
 
3
- import { mount, shallow } from 'enzyme';
4
- import 'jest-enzyme';
5
-
6
- import noop from 'lodash/noop';
7
3
  import { Kind } from '@lumx/react';
8
- import { Wrapper } from '@lumx/react/testing/utils';
4
+ import { render, within } from '@testing-library/react';
5
+ import { queryByClassName } from '@lumx/react/testing/utils/queries';
6
+ import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
7
+ import userEvent from '@testing-library/user-event';
9
8
 
10
9
  import { Notification, NotificationProps } from './Notification';
11
10
 
12
11
  const CLASSNAME = Notification.className as string;
13
12
 
14
- type SetupProps = Partial<NotificationProps>;
15
-
16
13
  /**
17
14
  * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
18
15
  */
19
- const setup = (propsOverride: SetupProps = {}, shallowRendering = true) => {
20
- const props: any = { ...propsOverride };
21
- const renderer: (el: ReactElement) => Wrapper = shallowRendering ? shallow : mount;
22
- const wrapper: Wrapper = renderer(<Notification {...props} />);
23
-
24
- const notification: Wrapper = wrapper.find('.lumx-notification');
25
- const icon: Wrapper = wrapper.find('.lumx-notification__icon');
26
- const content: Wrapper = wrapper.find('.lumx-notification__content');
27
- const action: Wrapper = wrapper.find('.lumx-notification__action');
16
+ const setup = (props: Partial<NotificationProps> = {}) => {
17
+ render(<Notification isOpen type={Kind.info} {...props} />);
18
+ const notification = queryByClassName(document.body, CLASSNAME);
28
19
 
29
- return { action, content, icon, notification, props, wrapper };
30
- };
31
-
32
- const properties = {
33
- error: {
34
- content: 'Error',
35
- onClick: noop,
36
- isOpen: true,
37
- type: Kind.error,
38
- },
39
- info: {
40
- content: 'Info',
41
- onClick: noop,
42
- isOpen: true,
43
- type: Kind.info,
44
- },
45
- infoWithCallback: {
46
- onActionClick: noop,
47
- actionLabel: 'Undo',
48
- content: 'Info with callback',
49
- onClick: noop,
50
- isOpen: true,
51
- type: Kind.info,
52
- },
53
- success: {
54
- content: 'Success',
55
- onClick: noop,
56
- isOpen: true,
57
- type: Kind.success,
58
- },
20
+ const icon = notification && queryByClassName(notification, `${CLASSNAME}__icon`);
21
+ const action = notification && queryByClassName(notification, `${CLASSNAME}__action`);
22
+ const actionButton = action && within(action).queryByRole('button');
59
23
 
60
- warning: {
61
- content: 'Warning',
62
- onClick: noop,
63
- isOpen: true,
64
- type: Kind.warning,
65
- },
24
+ return { action, actionButton, icon, notification, props };
66
25
  };
67
26
 
68
27
  describe(`<${Notification.displayName}>`, () => {
69
- // 1. Test render via snapshot (default states of component).
70
- describe('Snapshots and structure', () => {
71
- it('should render defaults', () => {
72
- const { wrapper, notification } = setup(properties.info);
73
- expect(wrapper).toMatchSnapshot();
28
+ it('should not render without type', () => {
29
+ const { notification } = setup({ type: undefined });
30
+ expect(notification).not.toBeInTheDocument();
31
+ });
74
32
 
75
- expect(notification).toExist();
33
+ it('should not render when closed', () => {
34
+ const { notification } = setup({ isOpen: false });
35
+ expect(notification).not.toBeInTheDocument();
36
+ });
76
37
 
77
- expect(notification).toHaveClassName(CLASSNAME);
78
- expect(notification).toHaveClassName(`${CLASSNAME}--color-dark`);
79
- });
38
+ it('should render content', () => {
39
+ const content = 'Content';
40
+ const { notification, icon } = setup({ content });
41
+ expect(notification).toBeInTheDocument();
42
+ expect(notification).toHaveTextContent(content);
43
+ expect(icon).toBeInTheDocument();
44
+ });
80
45
 
81
- it('should render nothing since the notification is closed', () => {
82
- const { wrapper, notification } = setup({ ...properties.info, isOpen: false });
83
- expect(wrapper).toMatchSnapshot();
46
+ it('should render content & action', async () => {
47
+ const onClick = jest.fn();
48
+ const onActionClick = jest.fn();
49
+ const content = 'Content';
50
+ const actionLabel = 'actionLabel';
51
+ const { notification, action, actionButton } = setup({ content, actionLabel, onClick, onActionClick });
84
52
 
85
- expect(notification).not.toExist();
86
- });
87
- });
53
+ expect(notification).toBeInTheDocument();
54
+ expect(notification).toHaveTextContent(content);
88
55
 
89
- // 2. Test defaultProps value and important props custom values.
90
- describe('Props', () => {
91
- // Nothing to do here.
92
- });
56
+ expect(action).toBeInTheDocument();
57
+ expect(actionButton).toBeInTheDocument();
58
+ expect(actionButton).toHaveTextContent(actionLabel);
93
59
 
94
- // 3. Test events.
95
- describe('Events', () => {
96
- // Nothing to do here.
97
- });
60
+ // Click action button
61
+ await userEvent.click(actionButton as any);
62
+ expect(onActionClick).toHaveBeenCalled();
63
+ expect(onClick).not.toHaveBeenCalled();
98
64
 
99
- // 4. Test conditions (i.e. things that display or not in the UI based on props).
100
- describe('Conditions', () => {
101
- // Nothing to do here.
65
+ // Click notification
66
+ await userEvent.click(notification as any);
67
+ expect(onClick).toHaveBeenCalled();
102
68
  });
103
69
 
104
- // 5. Test state.
105
- describe('State', () => {
106
- // Nothing to do here.
70
+ // Common tests suite.
71
+ commonTestsSuiteRTL(setup, {
72
+ baseClassName: CLASSNAME,
73
+ forwardClassName: 'notification',
74
+ forwardAttributes: 'notification',
75
+ forwardRef: 'notification',
107
76
  });
108
77
  });
@@ -173,18 +173,16 @@ const _InnerPopover: Comp<PopoverProps, HTMLDivElement> = forwardRef((props, ref
173
173
  * unless specifically requested not to.
174
174
  */
175
175
  if (isFocusedWithin.current && focusAnchorOnClose) {
176
- if (parentElement?.current) {
177
- parentElement?.current.focus();
178
- }
179
-
180
- const firstFocusable = anchorRef?.current && getFirstAndLastFocusable(anchorRef?.current).first;
181
- if (firstFocusable) {
176
+ let elementToFocus = parentElement?.current;
177
+ if (!elementToFocus && anchorRef?.current) {
182
178
  // Focus the first focusable element in anchor.
183
- firstFocusable.focus();
184
- } else {
179
+ elementToFocus = getFirstAndLastFocusable(anchorRef.current).first;
180
+ }
181
+ if (!elementToFocus) {
185
182
  // Fallback on the anchor element.
186
- anchorRef?.current?.focus();
183
+ elementToFocus = anchorRef?.current;
187
184
  }
185
+ elementToFocus?.focus({ preventScroll: true });
188
186
  }
189
187
 
190
188
  onClose();
@@ -1,57 +1,44 @@
1
+ import React from 'react';
2
+
1
3
  import { ProgressTrackerStep } from '@lumx/react';
2
- import { commonTestsSuite, Wrapper } from '@lumx/react/testing/utils';
4
+ import { render, within } from '@testing-library/react';
5
+ import { getByClassName } from '@lumx/react/testing/utils/queries';
6
+ import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
3
7
 
4
- import { mount, shallow } from 'enzyme';
5
- import 'jest-enzyme';
6
- import React, { ReactElement } from 'react';
7
- import { setupTabProviderMocks } from '../tabs/test.mocks';
8
8
  import { ProgressTracker, ProgressTrackerProps } from './ProgressTracker';
9
9
 
10
10
  const CLASSNAME = ProgressTracker.className as string;
11
11
 
12
- // Mock useTabProviderContext.
13
- jest.mock('../tabs/state', () => {
14
- const state = jest.requireActual('../tabs/state');
15
- return { ...state, useTabProviderContext: jest.fn(), useTabProviderContextState: jest.fn() };
16
- });
17
-
18
12
  type SetupProps = Partial<ProgressTrackerProps>;
19
13
 
20
14
  /**
21
15
  * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
22
16
  */
23
- const setup = ({ ...propsOverride }: SetupProps = {}, shallowRendering = true) => {
17
+ const setup = (propsOverride: SetupProps = {}) => {
24
18
  const steps = [<ProgressTrackerStep key={0} label="Step 0" />, <ProgressTrackerStep key={1} label="Step 1" />];
25
- const props: ProgressTrackerProps = {
19
+ const props = {
26
20
  children: steps,
27
21
  'aria-label': 'Steps',
28
22
  ...propsOverride,
29
23
  };
30
- const renderer: (el: ReactElement) => Wrapper = shallowRendering ? shallow : mount;
31
- const wrapper: Wrapper = renderer(<ProgressTracker {...props} />);
24
+ render(<ProgressTracker {...props} />);
25
+ const progressTracker = getByClassName(document.body, CLASSNAME);
32
26
 
33
- return { props, wrapper };
27
+ return { props, progressTracker };
34
28
  };
35
29
 
36
30
  describe(`<${ProgressTracker.displayName}>`, () => {
37
- beforeEach(() => {
38
- setupTabProviderMocks();
39
- });
40
-
41
- // 1. Test render via snapshot (default states of component).
42
- describe('Snapshots and structure', () => {
43
- it('should render correctly', () => {
44
- const { wrapper } = setup();
45
- expect(wrapper).toMatchSnapshot();
46
-
47
- expect(wrapper).toExist();
48
- expect(wrapper).toHaveClassName(CLASSNAME);
49
-
50
- expect(wrapper.childAt(0)).toExist();
51
- expect(wrapper.childAt(0)).toHaveClassName('lumx-progress-tracker__steps');
52
- });
31
+ it('should render default', () => {
32
+ const label = 'Steps';
33
+ const { progressTracker } = setup({ 'aria-label': label });
34
+ expect(within(progressTracker).queryByRole('tablist', { name: label })).toBeInTheDocument();
53
35
  });
54
36
 
55
37
  // Common tests suite.
56
- commonTestsSuite(setup, { className: 'wrapper', prop: 'wrapper' }, { className: CLASSNAME });
38
+ commonTestsSuiteRTL(setup, {
39
+ baseClassName: CLASSNAME,
40
+ forwardClassName: 'progressTracker',
41
+ forwardAttributes: 'progressTracker',
42
+ forwardRef: 'progressTracker',
43
+ });
57
44
  });
@@ -1,42 +1,67 @@
1
- import { ProgressTracker, ProgressTrackerProvider, ProgressTrackerStep, ProgressTrackerStepPanel } from '@lumx/react';
2
- import { mount } from 'enzyme';
3
- import 'jest-enzyme';
4
1
  import React from 'react';
5
2
 
3
+ import {
4
+ ProgressTracker,
5
+ ProgressTrackerProvider,
6
+ ProgressTrackerProviderProps,
7
+ ProgressTrackerStep,
8
+ ProgressTrackerStepPanel,
9
+ } from '@lumx/react';
10
+
11
+ import { render } from '@testing-library/react';
12
+ import { checkTabActive, query } from '../tabs/test-utils';
13
+
14
+ const setup = (props: Partial<ProgressTrackerProviderProps> = {}) =>
15
+ render(
16
+ <ProgressTrackerProvider {...props}>
17
+ <ProgressTracker aria-label="Progress tracker steps">
18
+ <ProgressTrackerStep label="Step 1" />
19
+ <ProgressTrackerStep label="Step 2" />
20
+ </ProgressTracker>
21
+
22
+ <ProgressTrackerStepPanel>Progress tracker step 1 content</ProgressTrackerStepPanel>
23
+ <ProgressTrackerStepPanel>Progress tracker step 2 content</ProgressTrackerStepPanel>
24
+ </ProgressTrackerProvider>,
25
+ );
26
+
6
27
  describe(`<${ProgressTrackerProvider.displayName}>`, () => {
7
- // 1. Test render via snapshot (default states of component).
8
- describe('Snapshots and structure', () => {
9
- it('should render', () => {
10
- const wrapper = mount(
11
- <ProgressTrackerProvider>
12
- <ProgressTracker aria-label="Progress tracker steps">
13
- <ProgressTrackerStep label="step 1" />
14
- <ProgressTrackerStep label="step 1" />
15
- </ProgressTracker>
16
-
17
- <ProgressTrackerStepPanel>Progress tracker step 1 content</ProgressTrackerStepPanel>
18
- <ProgressTrackerStepPanel>Progress tracker step 2 content</ProgressTrackerStepPanel>
19
- </ProgressTrackerProvider>,
20
- );
21
- const steps = wrapper.find(ProgressTrackerStep).find('button');
22
- const firstProgressTrackerStep = steps.get(0);
23
- const secondProgressTrackerStep = steps.get(1);
24
-
25
- const stepPanels = wrapper.find(ProgressTrackerStepPanel).find('div');
26
- const firstProgressTrackerStepPanel = stepPanels.get(0);
27
- const secondProgressTrackerStepPanel = stepPanels.get(1);
28
-
29
- // First step is selected.
30
- expect(firstProgressTrackerStep.props['aria-selected']).toBe(true);
31
- expect(secondProgressTrackerStep.props['aria-selected']).toBe(false);
32
-
33
- // ProgressTrackerStep id and step panel aria-labelledby by should match
34
- expect(firstProgressTrackerStep.props.id).toBe(firstProgressTrackerStepPanel.props['aria-labelledby']);
35
- expect(secondProgressTrackerStep.props.id).toBe(secondProgressTrackerStepPanel.props['aria-labelledby']);
36
-
37
- // ProgressTrackerStep panel id and step aria-controls by should match
38
- expect(firstProgressTrackerStepPanel.props.id).toBe(firstProgressTrackerStep.props['aria-controls']);
39
- expect(secondProgressTrackerStepPanel.props.id).toBe(secondProgressTrackerStep.props['aria-controls']);
28
+ describe('default config', () => {
29
+ it('should render aria tab pattern', () => {
30
+ setup();
31
+
32
+ // Step list
33
+ const tabList = query.tabList('Progress tracker steps');
34
+ expect(tabList).toBeInTheDocument();
35
+ expect(query.tabs(tabList).length).toBe(2);
36
+
37
+ // Step 1
38
+ const tab1 = query.tab('Step 1', tabList);
39
+ expect(tab1).toBeInTheDocument();
40
+
41
+ // Step 2
42
+ const tab2 = query.tab('Step 2', tabList);
43
+ expect(tab2).toBeInTheDocument();
44
+
45
+ // Step panel 1
46
+ const tabPanel1 = query.tabPanel('Step 1');
47
+ expect(tabPanel1).toBeInTheDocument();
48
+ expect(tab1).toHaveAttribute('aria-controls', tabPanel1?.id);
49
+
50
+ // Step panel 2
51
+ const tabPanel2 = query.tabPanel('Step 2');
52
+ expect(tabPanel2).toBeInTheDocument();
53
+ expect(tab2).toHaveAttribute('aria-controls', tabPanel2?.id);
54
+
55
+ // First step is active
56
+ checkTabActive('Step 1');
57
+ });
58
+ });
59
+
60
+ describe('not lazy', () => {
61
+ it('should render panel content', () => {
62
+ setup({ isLazy: false });
63
+
64
+ checkTabActive('Step 1', { isLazy: false });
40
65
  });
41
66
  });
42
67
  });