@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,14 +1,13 @@
1
- import React, { ReactElement } from 'react';
1
+ import React from 'react';
2
2
 
3
- import { mount, shallow } from 'enzyme';
4
- import 'jest-enzyme';
3
+ import { mdiCheck, mdiPlus } from '@lumx/icons';
4
+ import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
5
+ import { render, screen, within } from '@testing-library/react';
6
+ import { getByClassName, queryAllByClassName, queryByClassName } from '@lumx/react/testing/utils/queries';
7
+ import { Emphasis, Icon } from '@lumx/react';
5
8
 
6
- import { mdiCheck, mdiChevronDown, mdiPlus } from '@lumx/icons';
7
- import { commonTestsSuite, Wrapper } from '@lumx/react/testing/utils';
8
- import { getBasicClass } from '@lumx/react/utils/className';
9
9
  import { Button, ButtonProps } from './Button';
10
10
 
11
- const DEFAULT_PROPS = Button.defaultProps as any;
12
11
  const CLASSNAME = Button.className as string;
13
12
 
14
13
  type SetupProps = Partial<ButtonProps>;
@@ -16,137 +15,61 @@ type SetupProps = Partial<ButtonProps>;
16
15
  /**
17
16
  * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
18
17
  */
19
- const setup = (propsOverride: SetupProps = {}, shallowRendering = true) => {
18
+ const setup = (propsOverride: SetupProps = {}) => {
20
19
  const props: any = { ...propsOverride };
21
- const renderer: (el: ReactElement) => Wrapper = shallowRendering ? shallow : mount;
22
-
23
- const wrapper: Wrapper = renderer(<Button {...props} />);
24
-
25
- return {
26
- buttonRoot: wrapper.find('ButtonRoot'),
27
- icon: wrapper.find('Icon'),
28
- props,
29
- wrapper,
30
- };
20
+ render(<Button {...props} />);
21
+ const button = getByClassName(document.body, CLASSNAME);
22
+ const buttonWrapper = queryByClassName(document.body, 'lumx-button-wrapper');
23
+ const icons = queryAllByClassName(button, Icon.className as string);
24
+ return { props, button, buttonWrapper, icons };
31
25
  };
32
26
 
33
27
  describe(`<${Button.displayName}>`, () => {
34
- // 1. Test render via snapshot (default states of component).
35
- describe('Snapshots and structure', () => {
36
- it('should render button with label', () => {
28
+ describe('Props', () => {
29
+ it('should render default', () => {
37
30
  const label = 'Label';
38
- const { buttonRoot, icon, wrapper } = setup({
39
- children: label,
40
- });
41
- expect(wrapper).toMatchSnapshot();
42
-
43
- expect(buttonRoot).toExist();
44
-
45
- expect(icon).not.toExist();
46
-
47
- expect(buttonRoot.contains(label)).toBe(true);
31
+ const { button, icons } = setup({ children: label });
32
+ expect(button).toBe(screen.queryByRole('button', { name: label }));
33
+ expect(button).toHaveAttribute('type', 'button');
34
+ expect(button.className).toMatchInlineSnapshot(
35
+ `"lumx-button lumx-button--color-primary lumx-button--emphasis-high lumx-button--size-m lumx-button--theme-light lumx-button--variant-button"`,
36
+ );
37
+ expect(icons.length).toBe(0);
48
38
  });
49
39
 
50
- it('should render button with label and right icon', () => {
40
+ it('should render icons', () => {
51
41
  const label = 'Label';
52
- const { buttonRoot, icon, wrapper } = setup({
53
- children: label,
54
- rightIcon: mdiChevronDown,
55
- });
56
- expect(wrapper).toMatchSnapshot();
57
-
58
- expect(buttonRoot).toExist();
59
-
60
- expect(icon).toExist();
61
- expect(icon.length).toEqual(1);
62
-
63
- expect(buttonRoot.contains(label)).toBe(true);
42
+ const { button, icons } = setup({ children: label, rightIcon: mdiPlus, leftIcon: mdiCheck });
43
+ expect(button).toHaveTextContent(label);
44
+ expect(icons.length).toBe(2);
64
45
  });
65
46
 
66
- it('should render button with label and left icon', () => {
47
+ it('should render link', () => {
67
48
  const label = 'Label';
68
- const { buttonRoot, icon, wrapper } = setup({
69
- children: label,
70
- leftIcon: mdiChevronDown,
71
- });
72
- expect(wrapper).toMatchSnapshot();
73
-
74
- expect(buttonRoot).toExist();
75
-
76
- expect(icon).toExist();
77
- expect(icon.length).toEqual(1);
78
-
79
- expect(buttonRoot.contains(label)).toBe(true);
49
+ const { button } = setup({ children: label, href: 'https://example.com' });
50
+ expect(button).toBe(screen.queryByRole('link', { name: label }));
80
51
  });
81
52
 
82
- it('should render button with label and icons', () => {
83
- const label = 'Label';
84
- const { buttonRoot, icon, wrapper } = setup({
85
- children: label,
86
- leftIcon: mdiCheck,
87
- rightIcon: mdiChevronDown,
88
- });
89
- expect(wrapper).toMatchSnapshot();
90
-
91
- expect(buttonRoot).toExist();
92
-
93
- expect(icon).toExist();
94
- expect(icon.length).toEqual(2);
95
-
96
- expect(buttonRoot.contains(label)).toBe(true);
53
+ it('should render emphasis low', () => {
54
+ const { button } = setup({ emphasis: Emphasis.low });
55
+ expect(button.className).toMatchInlineSnapshot(
56
+ `"lumx-button lumx-button--color-dark lumx-button--emphasis-low lumx-button--size-m lumx-button--variant-button"`,
57
+ );
97
58
  });
98
- });
99
59
 
100
- // 2. Test defaultProps value and important props custom values.
101
- describe('Props', () => {
102
- it('should use default props', () => {
103
- const { buttonRoot } = setup();
104
-
105
- const actualProps = buttonRoot.props() as Partial<ButtonProps>;
106
- expect(actualProps.variant).toEqual('button');
107
- for (const [propName, propValue] of Object.entries(DEFAULT_PROPS)) {
108
- expect(actualProps[propName]).toEqual(propValue);
109
- }
110
- });
111
-
112
- it('should forward any CSS class', () => {
113
- const props = {
114
- className: 'component component--is-tested',
115
- };
116
- const { wrapper, buttonRoot } = setup(props);
117
- expect(wrapper).toMatchSnapshot();
118
-
119
- expect(buttonRoot).toHaveClassName(props.className);
120
- });
121
-
122
- it('should use the given props for class names', () => {
123
- const props: Partial<ButtonProps> = {
124
- leftIcon: mdiChevronDown,
125
- rightIcon: mdiPlus,
126
- };
127
- const { wrapper, buttonRoot } = setup(props);
128
- expect(wrapper).toMatchSnapshot();
129
-
130
- expect(buttonRoot).toHaveClassName(getBasicClass({ prefix: CLASSNAME, type: 'hasLeftIcon', value: true }));
131
- expect(buttonRoot).toHaveClassName(getBasicClass({ prefix: CLASSNAME, type: 'hasRightIcon', value: true }));
60
+ it('should render hasBackground', () => {
61
+ const label = 'Label';
62
+ const { buttonWrapper, button } = setup({ children: label, hasBackground: true });
63
+ expect(buttonWrapper).toBeInTheDocument();
64
+ expect(button).toBe(within(buttonWrapper as any).queryByRole('button', { name: label }));
132
65
  });
133
66
  });
134
67
 
135
- // 3. Test events.
136
- describe('Events', () => {
137
- // Nothing to do here.
138
- });
139
-
140
- // 4. Test conditions (i.e. things that display or not in the UI based on props).
141
- describe('Conditions', () => {
142
- // Nothing to do here.
143
- });
144
-
145
- // 5. Test state.
146
- describe('State', () => {
147
- // Nothing to do here.
148
- });
149
-
150
68
  // Common tests suite.
151
- commonTestsSuite(setup, { prop: 'buttonRoot' }, { className: CLASSNAME });
69
+ commonTestsSuiteRTL(setup, {
70
+ baseClassName: CLASSNAME,
71
+ forwardClassName: 'button',
72
+ forwardAttributes: 'button',
73
+ forwardRef: 'button',
74
+ });
152
75
  });
@@ -1,11 +1,11 @@
1
- import React, { ReactElement } from 'react';
2
-
3
- import { mount, shallow } from 'enzyme';
4
- import 'jest-enzyme';
1
+ import React from 'react';
5
2
 
6
3
  import { mdiPlus } from '@lumx/icons';
7
4
  import { Button, IconButton } from '@lumx/react';
8
- import { commonTestsSuite, Wrapper } from '@lumx/react/testing/utils';
5
+ import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
6
+ import { render } from '@testing-library/react';
7
+ import { getByClassName } from '@lumx/react/testing/utils/queries';
8
+
9
9
  import { ButtonGroup, ButtonGroupProps } from './ButtonGroup';
10
10
 
11
11
  const CLASSNAME = ButtonGroup.className as string;
@@ -15,7 +15,7 @@ type SetupProps = Partial<ButtonGroupProps>;
15
15
  /**
16
16
  * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
17
17
  */
18
- const setup = ({ ...propsOverride }: SetupProps = {}, shallowRendering = true) => {
18
+ const setup = (propsOverride: SetupProps = {}) => {
19
19
  const props: ButtonGroupProps = {
20
20
  children: (
21
21
  <>
@@ -25,42 +25,19 @@ const setup = ({ ...propsOverride }: SetupProps = {}, shallowRendering = true) =
25
25
  ),
26
26
  ...propsOverride,
27
27
  };
28
- const renderer: (el: ReactElement) => Wrapper = shallowRendering ? shallow : mount;
29
- const wrapper: Wrapper = renderer(<ButtonGroup {...props} />);
30
28
 
31
- return {
32
- group: wrapper.find(`.${CLASSNAME}`),
33
- props,
34
- wrapper,
35
- };
29
+ render(<ButtonGroup {...props} />);
30
+ const buttonGroup = getByClassName(document.body, CLASSNAME);
31
+
32
+ return { props, buttonGroup };
36
33
  };
37
34
 
38
35
  describe(`<${ButtonGroup.displayName}>`, () => {
39
- // 1. Test render via snapshot (default state of component).
40
- describe('Snapshots and structure', () => {
41
- it('should render correctly a group button', () => {
42
- const { group, wrapper } = setup();
43
- expect(wrapper).toMatchSnapshot();
44
-
45
- expect(group).toExist();
46
- expect(group).toHaveClassName(CLASSNAME);
47
-
48
- expect(group.children().length).toEqual(2);
49
- });
50
- });
51
-
52
- // 2. Test defaultProps value and important props custom values.
53
- // N/A
54
-
55
- // 3. Test events.
56
- // N/A
57
-
58
- // 4. Test conditions (i.e. things that display or not in the UI based on props).
59
- // N/A
60
-
61
- // 5. Test state.
62
- // N/A
63
-
64
36
  // Common tests suite.
65
- commonTestsSuite(setup, { className: 'group', prop: 'group' }, { className: CLASSNAME });
37
+ commonTestsSuiteRTL(setup, {
38
+ baseClassName: CLASSNAME,
39
+ forwardClassName: 'buttonGroup',
40
+ forwardAttributes: 'buttonGroup',
41
+ forwardRef: 'buttonGroup',
42
+ });
66
43
  });
@@ -36,6 +36,13 @@ export const WithImage = {
36
36
  args: { image: SQUARE_IMAGES.square1 },
37
37
  };
38
38
 
39
+ /**
40
+ * IconButton using a tooltip
41
+ */
42
+ export const WithTooltip = {
43
+ args: { icon: mdiSend, label: 'Send a message' },
44
+ };
45
+
39
46
  /**
40
47
  * Check icon button style variations (color, states, emphasis, etc.)
41
48
  */
@@ -1,103 +1,62 @@
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 { commonTestsSuite, Wrapper } from '@lumx/react/testing/utils';
7
- import { mdiClose } from '@lumx/icons';
3
+ import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
4
+ import { Button } from '@lumx/react';
5
+ import { render, screen } from '@testing-library/react';
6
+ import { getByClassName, queryByClassName, queryByTagName } from '@lumx/react/testing/utils/queries';
8
7
 
9
8
  import { IconButton, IconButtonProps } from './IconButton';
10
9
 
11
- const DEFAULT_PROPS = IconButton.defaultProps as any;
12
- const CLASSNAME = IconButton.className as string;
10
+ const CLASSNAME = Button.className as string;
13
11
 
14
12
  type SetupProps = Partial<IconButtonProps>;
15
13
 
16
14
  /**
17
15
  * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
18
16
  */
19
- const setup = (propsOverride: SetupProps = {}, shallowRendering = true) => {
17
+ const setup = (propsOverride: SetupProps = {}) => {
20
18
  const props: any = { ...propsOverride };
21
- const renderer: (el: ReactElement) => Wrapper = shallowRendering ? shallow : mount;
22
-
23
- const wrapper: Wrapper = renderer(<IconButton {...props} />);
19
+ render(<IconButton {...props} />);
20
+ const iconButton = getByClassName(document.body, CLASSNAME);
21
+ const icon = queryByClassName(iconButton, 'lumx-icon');
22
+ const img = queryByTagName(iconButton, 'IMG');
24
23
 
25
- return {
26
- buttonRoot: wrapper.find('ButtonRoot'),
27
- icon: wrapper.find('Icon'),
28
- img: wrapper.find('img'),
29
- props,
30
- wrapper,
31
- };
24
+ return { props, iconButton, icon, img };
32
25
  };
33
26
 
34
27
  describe(`<${IconButton.displayName}>`, () => {
35
- // 1. Test render via snapshot (default states of component).
36
- describe('Snapshots and structure', () => {
37
- it('should render icon button', () => {
38
- const { buttonRoot, icon, img, wrapper } = setup({});
39
- expect(wrapper).toMatchSnapshot();
40
- expect(buttonRoot).toExist();
41
- expect(icon).toExist();
42
- expect(img).not.toExist();
43
- });
44
-
45
- it('should render icon button with an image', () => {
46
- const { buttonRoot, icon, img, wrapper } = setup({ image: 'http://foo.com' });
47
- expect(wrapper).toMatchSnapshot();
48
- expect(buttonRoot).toExist();
49
- expect(icon).not.toExist();
50
- expect(img).toExist();
51
- });
52
-
53
- it('should render icon button with an image if both props are set', () => {
54
- const { buttonRoot, icon, img, wrapper } = setup({ image: 'http://foo.com', icon: mdiClose });
55
- expect(wrapper).toMatchSnapshot();
56
- expect(buttonRoot).toExist();
57
- expect(icon).not.toExist();
58
- expect(img).toExist();
59
- });
60
- });
61
-
62
- // 2. Test defaultProps value and important props custom values.
63
28
  describe('Props', () => {
64
- it('should use default props', () => {
65
- const { wrapper, buttonRoot } = setup();
66
- expect(wrapper).toMatchSnapshot();
67
-
68
- const actualProps = buttonRoot.props() as IconButtonProps;
69
- expect(actualProps.variant).toEqual('icon');
70
- for (const [propName, propValue] of Object.entries(DEFAULT_PROPS)) {
71
- expect(actualProps[propName]).toEqual(propValue);
72
- }
29
+ it('should render default', () => {
30
+ const { iconButton, icon, img } = setup();
31
+ expect(iconButton).toBeInTheDocument();
32
+ expect(iconButton.className).toMatchInlineSnapshot(
33
+ `"lumx-button lumx-button--color-primary lumx-button--emphasis-high lumx-button--size-m lumx-button--theme-light lumx-button--variant-icon"`,
34
+ );
35
+
36
+ expect(icon).toBeInTheDocument();
37
+ expect(img).not.toBeInTheDocument();
73
38
  });
74
39
 
75
- it('should forward any CSS class', () => {
76
- const props = {
77
- className: 'component component--is-tested',
78
- };
79
- const { wrapper, buttonRoot } = setup(props);
80
- expect(wrapper).toMatchSnapshot();
81
-
82
- expect(buttonRoot).toHaveClassName(props.className);
40
+ it('should render label', () => {
41
+ const label = 'Label';
42
+ const { iconButton } = setup({ label });
43
+ expect(iconButton).toBe(screen.queryByRole('button', { name: label }));
83
44
  });
84
- });
85
-
86
- // 3. Test events.
87
- describe('Events', () => {
88
- // Nothing to do here.
89
- });
90
45
 
91
- // 4. Test conditions (i.e. things that display or not in the UI based on props).
92
- describe('Conditions', () => {
93
- // Nothing to do here.
94
- });
46
+ it('should render icon button with an image', () => {
47
+ const { iconButton, icon, img } = setup({ image: 'http://foo.com' });
95
48
 
96
- // 5. Test state.
97
- describe('State', () => {
98
- // Nothing to do here.
49
+ expect(iconButton).toBeInTheDocument();
50
+ expect(icon).not.toBeInTheDocument();
51
+ expect(img).toBeInTheDocument();
52
+ });
99
53
  });
100
54
 
101
55
  // Common tests suite.
102
- commonTestsSuite(setup, { prop: 'buttonRoot' }, { className: CLASSNAME });
56
+ commonTestsSuiteRTL(setup, {
57
+ baseClassName: CLASSNAME,
58
+ forwardClassName: 'iconButton',
59
+ forwardAttributes: 'iconButton',
60
+ forwardRef: 'iconButton',
61
+ });
103
62
  });
@@ -61,7 +61,14 @@ export const IconButton: Comp<IconButtonProps, HTMLButtonElement> = forwardRef((
61
61
 
62
62
  return (
63
63
  <Tooltip label={hideTooltip ? '' : label} {...tooltipProps}>
64
- <ButtonRoot ref={ref} {...{ emphasis, size, theme, ...forwardedProps }} aria-label={label} variant="icon">
64
+ <ButtonRoot
65
+ ref={ref}
66
+ {...{ emphasis, size, theme, ...forwardedProps }}
67
+ aria-label={label}
68
+ variant="icon"
69
+ // Remove the aria-describedby added by the tooltip when it is the same text as the aria-label
70
+ aria-describedby={tooltipProps?.label && tooltipProps?.label === label && undefined}
71
+ >
65
72
  {image ? (
66
73
  <img
67
74
  // no need to set alt as an aria-label is already set on the button
@@ -1,11 +1,10 @@
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 { commonTestsSuite, Wrapper } from '@lumx/react/testing/utils';
7
- import { getBasicClass } from '@lumx/react/utils/className';
3
+ import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
8
4
 
5
+ import { getByClassName, getByTagName, queryByClassName } from '@lumx/react/testing/utils/queries';
6
+ import { render } from '@testing-library/react';
7
+ import userEvent from '@testing-library/user-event';
9
8
  import { Checkbox, CheckboxProps } from './Checkbox';
10
9
 
11
10
  const CLASSNAME = Checkbox.className as string;
@@ -15,100 +14,96 @@ type SetupProps = Partial<CheckboxProps>;
15
14
  /**
16
15
  * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
17
16
  */
18
- const setup = (propsOverride: SetupProps = {}, shallowRendering = true) => {
17
+ const setup = (propsOverride: SetupProps = {}) => {
19
18
  const props: any = { id: 'fixedId', ...propsOverride };
20
- const renderer: (el: ReactElement) => Wrapper = shallowRendering ? shallow : mount;
21
- const wrapper: Wrapper = renderer(<Checkbox {...props} />);
22
-
23
- return {
24
- helper: wrapper.find(`.${CLASSNAME}__helper`),
25
- label: wrapper.find(`.${CLASSNAME}__label`),
26
- props,
27
- wrapper,
28
- };
19
+ render(<Checkbox {...props} />);
20
+
21
+ const checkbox = getByClassName(document.body, CLASSNAME);
22
+ const helper = queryByClassName(checkbox, `${CLASSNAME}__helper`);
23
+ const label = queryByClassName(checkbox, `${CLASSNAME}__label`);
24
+ const input = getByTagName(checkbox, 'input');
25
+ return { checkbox, helper, label, input, props };
29
26
  };
30
27
 
31
28
  describe(`<${Checkbox.displayName}>`, () => {
32
- // 1. Test render via snapshot (default states of component).
33
- describe('Snapshots and structure', () => {
29
+ describe('Props', () => {
34
30
  it('should render correctly', () => {
35
- const { wrapper } = setup();
36
- expect(wrapper).toMatchSnapshot();
37
-
38
- expect(wrapper).toExist();
39
- expect(wrapper).toHaveClassName(CLASSNAME);
40
- expect(wrapper).not.toHaveClassName('lumx-checkbox--is-disabled');
41
- expect(wrapper).toHaveClassName('lumx-checkbox--is-unchecked');
42
- expect(wrapper.find('input')).toHaveProp('disabled', undefined);
31
+ const { checkbox, input, label, helper } = setup();
32
+ expect(checkbox).toBeInTheDocument();
33
+ expect(checkbox).toHaveClass(CLASSNAME);
34
+ expect(checkbox).not.toHaveClass('lumx-checkbox--is-disabled');
35
+ expect(checkbox).toHaveClass('lumx-checkbox--is-unchecked');
36
+
37
+ expect(label).not.toBeInTheDocument();
38
+ expect(helper).not.toBeInTheDocument();
39
+
40
+ expect(input).toBeInTheDocument();
41
+ expect(input).not.toBeChecked();
42
+ expect(input).not.toBeDisabled();
43
43
  });
44
- });
45
44
 
46
- // 2. Test defaultProps value and important props custom values.
47
- describe('Props', () => {
48
- it('should add a "disabled" and "checked" class names', () => {
49
- const { wrapper } = setup({
45
+ it('should render disabled and checked', () => {
46
+ const { checkbox, input } = setup({
50
47
  isDisabled: true,
51
48
  isChecked: true,
52
49
  });
50
+ expect(checkbox).toHaveClass('lumx-checkbox--is-disabled');
51
+ expect(checkbox).toHaveClass('lumx-checkbox--is-checked');
53
52
 
54
- expect(wrapper).toHaveClassName(getBasicClass({ prefix: CLASSNAME, type: 'disabled', value: true }));
55
- expect(wrapper.find('input')).toHaveProp('disabled', true);
56
- expect(wrapper).toHaveClassName(getBasicClass({ prefix: CLASSNAME, type: 'checked', value: true }));
53
+ expect(input).toBeChecked();
54
+ expect(input).toBeDisabled();
57
55
  });
58
56
 
59
- it('should use the given props', () => {
60
- const { helper, label, wrapper } = setup({
57
+ it('should render helper and label', () => {
58
+ const id = 'checkbox1';
59
+ const { props, helper, label, input } = setup({
60
+ id,
61
61
  helper: 'Test helper',
62
62
  label: 'Test label',
63
63
  });
64
64
 
65
- expect(helper).toExist();
66
- expect(label).toExist();
67
- expect(wrapper).toMatchSnapshot();
65
+ expect(helper).toBeInTheDocument();
66
+ expect(helper).toHaveTextContent(props.helper);
67
+ expect(helper).toHaveAttribute('id');
68
+
69
+ expect(label).toBeInTheDocument();
70
+ expect(label).toHaveTextContent(props.label);
71
+ expect(label).toHaveAttribute('for', id);
72
+
73
+ expect(input).toHaveAttribute('id', id);
74
+ expect(input).toHaveAttribute('aria-describedby', helper?.id);
68
75
  });
69
76
 
70
- it('should use the given props while passing custom props to input', () => {
71
- const { helper, label, wrapper } = setup({
72
- helper: 'Test helper',
73
- label: 'Test label',
77
+ it('should forward input props', () => {
78
+ const { props, input } = setup({
74
79
  inputProps: {
75
80
  'aria-labelledby': 'labelledby-id',
76
81
  },
77
82
  });
78
83
 
79
- expect(helper).toExist();
80
- expect(label).toExist();
81
- expect(wrapper).toMatchSnapshot();
84
+ expect(input).toHaveAttribute('aria-labelledby', props.inputProps['aria-labelledby']);
82
85
  });
83
86
  });
84
87
 
85
- // 3. Test events.
86
88
  describe('Events', () => {
87
- const onChange: jest.Mock = jest.fn();
89
+ const onChange = jest.fn();
88
90
 
89
- beforeEach(() => {
90
- onChange.mockClear();
91
- });
91
+ it('should trigger `onChange` when checkbox is clicked', async () => {
92
+ const value = 'value';
93
+ const name = 'name';
94
+ const { input } = setup({ checked: false, onChange, value, name });
95
+ expect(input).not.toBeChecked();
92
96
 
93
- it('should trigger `onChange` when checkbox is clicked', () => {
94
- const { wrapper } = setup({ checked: false, onChange }, false);
95
- const checkbox = wrapper.find('input');
97
+ await userEvent.click(input);
96
98
 
97
- checkbox.simulate('change');
98
- expect(onChange).toHaveBeenCalled();
99
+ expect(onChange).toHaveBeenCalledWith(true, value, name, expect.any(Object));
99
100
  });
100
101
  });
101
102
 
102
- // 4. Test conditions (i.e. things that display or not in the UI based on props).
103
- describe('Conditions', () => {
104
- // Nothing to do here.
105
- });
106
-
107
- // 5. Test state.
108
- describe('State', () => {
109
- // Nothing to do here.
110
- });
111
-
112
103
  // Common tests suite.
113
- commonTestsSuite(setup, { className: 'wrapper', prop: 'wrapper' }, { className: CLASSNAME });
104
+ commonTestsSuiteRTL(setup, {
105
+ baseClassName: CLASSNAME,
106
+ forwardClassName: 'checkbox',
107
+ forwardAttributes: 'checkbox',
108
+ });
114
109
  });