Skip to content

Commit 9cfb7b0

Browse files
ref(react-testing-library): Introduce user-event (#29638)
1 parent 59db383 commit 9cfb7b0

File tree

39 files changed

+330
-334
lines changed

39 files changed

+330
-334
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"@testing-library/jest-dom": "^5.14.1",
3333
"@testing-library/react": "^12.0.0",
3434
"@testing-library/react-hooks": "^7.0.2",
35+
"@testing-library/user-event": "^13.5.0",
3536
"@types/color": "^3.0.2",
3637
"@types/compression-webpack-plugin": "^6.0.5",
3738
"@types/css-minimizer-webpack-plugin": "^3.0.1",

static/app/components/clipboardTooltip.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const TooltipClipboardWrapper = styled('div')`
4646
`;
4747

4848
const TooltipClipboardIconWrapper = styled('div')`
49+
pointer-events: auto;
4950
position: relative;
5051
bottom: -${space(0.25)};
5152
:hover {

tests/js/sentry-test/reactTestingLibrary.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import {Component, Fragment} from 'react';
22
import {cache} from '@emotion/css';
33
import {CacheProvider, ThemeProvider} from '@emotion/react';
4-
import {render, RenderOptions} from '@testing-library/react';
4+
import {
5+
fireEvent as reactRtlFireEvent,
6+
render,
7+
RenderOptions,
8+
} from '@testing-library/react';
9+
import userEvent from '@testing-library/user-event';
510

611
import {Organization} from 'app/types';
712
import {lightTheme} from 'app/utils/theme';
@@ -68,4 +73,11 @@ const mountWithTheme = (
6873

6974
export * from '@testing-library/react';
7075

71-
export {mountWithTheme};
76+
/**
77+
* @deprecated
78+
* Use userEvent over fireEvent where possible.
79+
* More details: https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#not-using-testing-libraryuser-event
80+
*/
81+
const fireEvent = reactRtlFireEvent;
82+
83+
export {mountWithTheme, userEvent, fireEvent};

tests/js/spec/components/banner.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {fireEvent, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary';
1+
import {mountWithTheme, screen, userEvent} from 'sentry-test/reactTestingLibrary';
22

33
import Banner from 'app/components/banner';
44

@@ -7,7 +7,7 @@ describe('Banner', function () {
77
mountWithTheme(<Banner dismissKey="test" title="test" />);
88
expect(screen.getByText('test')).toBeInTheDocument();
99

10-
fireEvent.click(screen.getByLabelText('Close'));
10+
userEvent.click(screen.getByLabelText('Close'));
1111

1212
expect(screen.queryByText('test')).not.toBeInTheDocument();
1313
expect(localStorage.getItem('test-banner-dismissed')).toBe('true');

tests/js/spec/components/breadcrumbs.spec.jsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {fireEvent, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary';
1+
import {mountWithTheme, screen, userEvent} from 'sentry-test/reactTestingLibrary';
22

33
import Breadcrumbs from 'app/components/breadcrumbs';
44

@@ -43,15 +43,15 @@ describe('Breadcrumbs', () => {
4343

4444
it('generates correct links', () => {
4545
createWrapper();
46-
fireEvent.click(screen.getByText('Test 1'));
46+
userEvent.click(screen.getByText('Test 1'));
4747
expect(routerContext.context.router.push).toHaveBeenCalledWith('/test1');
48-
fireEvent.click(screen.getByText('Test 2'));
48+
userEvent.click(screen.getByText('Test 2'));
4949
expect(routerContext.context.router.push).toHaveBeenCalledWith('/test2');
5050
});
5151

5252
it('does not make links where no `to` is provided', () => {
5353
createWrapper();
54-
fireEvent.click(screen.getByText('Test 3'));
54+
userEvent.click(screen.getByText('Test 3'));
5555
expect(routerContext.context.router.push).not.toHaveBeenCalled();
5656
});
5757

@@ -77,12 +77,12 @@ describe('Breadcrumbs', () => {
7777
/>,
7878
{context: routerContext}
7979
);
80-
fireEvent.mouseOver(screen.getByText('dropdown crumb'));
80+
userEvent.hover(screen.getByText('dropdown crumb'));
8181

8282
const item3 = await screen.findByText('item3');
8383
expect(item3).toBeInTheDocument();
8484

85-
fireEvent.click(item3);
85+
userEvent.click(item3);
8686
expect(onSelect).toHaveBeenCalledWith(
8787
expect.objectContaining({label: 'item3'}),
8888
expect.anything(),

tests/js/spec/components/button.spec.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {fireEvent, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary';
1+
import {mountWithTheme, screen, userEvent} from 'sentry-test/reactTestingLibrary';
22

33
import Button from 'app/components/button';
44

@@ -38,7 +38,7 @@ describe('Button', function () {
3838
mountWithTheme(<Button onClick={spy}>Click me</Button>, {
3939
context: routerContext,
4040
});
41-
fireEvent.click(screen.getByText('Click me'));
41+
userEvent.click(screen.getByText('Click me'));
4242

4343
expect(spy).toHaveBeenCalled();
4444
});
@@ -51,7 +51,7 @@ describe('Button', function () {
5151
</Button>,
5252
{context: routerContext}
5353
);
54-
fireEvent.click(screen.getByText('Click me'));
54+
userEvent.click(screen.getByText('Click me'));
5555

5656
expect(spy).not.toHaveBeenCalled();
5757
});

tests/js/spec/components/clipboardTooltip.spec.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import copy from 'copy-text-to-clipboard';
22

3-
import {fireEvent, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary';
3+
import {mountWithTheme, screen, userEvent} from 'sentry-test/reactTestingLibrary';
44

55
import ClipboardTooltip from 'app/components/clipboardTooltip';
66

@@ -17,13 +17,12 @@ describe('ClipboardTooltip', function () {
1717
);
1818

1919
expect(screen.getByText(content)).toBeInTheDocument();
20-
fireEvent.mouseEnter(screen.getByText(content));
20+
userEvent.hover(screen.getByText(content));
2121

2222
await screen.findByText(title);
2323

24-
const clipboardContent = screen.getByLabelText('Copy to clipboard');
25-
expect(clipboardContent).toBeInTheDocument();
26-
fireEvent.click(clipboardContent);
24+
expect(screen.getByLabelText('Copy to clipboard')).toBeInTheDocument();
25+
userEvent.click(screen.getByLabelText('Copy to clipboard'));
2726

2827
expect(copy).toHaveBeenCalledWith(title);
2928
});

tests/js/spec/components/errorRobot.spec.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {fireEvent, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary';
1+
import {mountWithTheme, screen, userEvent} from 'sentry-test/reactTestingLibrary';
22

33
import {Client} from 'app/api';
44
import {ErrorRobot} from 'app/components/errorRobot';
@@ -42,7 +42,7 @@ describe('ErrorRobot', function () {
4242

4343
it('Renders installation instructions', function () {
4444
createWrapper();
45-
fireEvent.click(screen.getByText('Installation Instructions'));
45+
userEvent.click(screen.getByText('Installation Instructions'));
4646
expect(routerContext.context.router.push).toHaveBeenCalledWith(
4747
'/org-slug/project-slug/getting-started/'
4848
);

tests/js/spec/components/events/interfaces/breadcrumbs/breadcrumbs.spec.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {initializeOrg} from 'sentry-test/initializeOrg';
2-
import {fireEvent, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary';
2+
import {mountWithTheme, screen, userEvent} from 'sentry-test/reactTestingLibrary';
33
import {getAllByTextContent} from 'sentry-test/utils';
44

55
import Breadcrumbs from 'app/components/events/interfaces/breadcrumbs';
@@ -70,15 +70,15 @@ describe('Breadcrumbs', () => {
7070
it('should filter crumbs based on crumb message', async function () {
7171
mountWithTheme(<Breadcrumbs {...props} />);
7272

73-
const searchInput = screen.getByPlaceholderText('Search breadcrumbs');
74-
75-
fireEvent.change(searchInput, {target: {value: 'hi'}});
73+
userEvent.type(screen.getByPlaceholderText('Search breadcrumbs'), 'hi');
7674

7775
expect(
7876
await screen.findByText('Sorry, no breadcrumbs match your search query')
7977
).toBeInTheDocument();
8078

81-
fireEvent.change(searchInput, {target: {value: 'up'}});
79+
userEvent.click(screen.getByLabelText('Clear'));
80+
81+
userEvent.type(screen.getByPlaceholderText('Search breadcrumbs'), 'up');
8282

8383
expect(
8484
screen.queryByText('Sorry, no breadcrumbs match your search query')
@@ -90,9 +90,7 @@ describe('Breadcrumbs', () => {
9090
it('should filter crumbs based on crumb level', function () {
9191
mountWithTheme(<Breadcrumbs {...props} />);
9292

93-
const searchInput = screen.getByPlaceholderText('Search breadcrumbs');
94-
95-
fireEvent.change(searchInput, {target: {value: 'war'}});
93+
userEvent.type(screen.getByPlaceholderText('Search breadcrumbs'), 'war');
9694

9795
// breadcrumbs + filter item
9896
// TODO(Priscila): Filter should not render in the dom if not open
@@ -102,9 +100,7 @@ describe('Breadcrumbs', () => {
102100
it('should filter crumbs based on crumb category', function () {
103101
mountWithTheme(<Breadcrumbs {...props} />);
104102

105-
const searchInput = screen.getByPlaceholderText('Search breadcrumbs');
106-
107-
fireEvent.change(searchInput, {target: {value: 'error'}});
103+
userEvent.type(screen.getByPlaceholderText('Search breadcrumbs'), 'error');
108104

109105
expect(getAllByTextContent('error')).toHaveLength(2);
110106
});
@@ -129,7 +125,7 @@ describe('Breadcrumbs', () => {
129125

130126
const searchInput = screen.getByPlaceholderText('Search breadcrumbs');
131127

132-
fireEvent.change(searchInput, {target: {value: 'sup'}});
128+
userEvent.type(searchInput, 'sup');
133129

134130
expect(screen.queryByTestId('crumb')).not.toBeInTheDocument();
135131

tests/js/spec/components/events/interfaces/crashContent/stackTrace/content.spec.tsx

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {fireEvent, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary';
1+
import {mountWithTheme, screen, userEvent} from 'sentry-test/reactTestingLibrary';
22

33
import StackTraceContent from 'app/components/events/interfaces/crashContent/stackTrace/content';
44
import {StacktraceType} from 'app/types/stacktrace';
@@ -81,19 +81,15 @@ describe('StackTrace', function () {
8181
const frameTitles = screen.getAllByTestId('title');
8282

8383
// collapse the expanded frame (by default)
84-
fireEvent.mouseDown(frameTitles[0]);
85-
fireEvent.click(frameTitles[0]);
84+
userEvent.click(frameTitles[0]);
8685

8786
// all frames are now collapsed
8887
expect(screen.queryByTestId('toggle-button-expanded')).not.toBeInTheDocument();
8988
expect(screen.getAllByTestId('toggle-button-collapsed')).toHaveLength(5);
9089

9190
// expand penultimate and last frame
92-
fireEvent.mouseDown(frameTitles[frameTitles.length - 2]);
93-
fireEvent.click(frameTitles[frameTitles.length - 2]);
94-
95-
fireEvent.mouseDown(frameTitles[frameTitles.length - 1]);
96-
fireEvent.click(frameTitles[frameTitles.length - 1]);
91+
userEvent.click(frameTitles[frameTitles.length - 2]);
92+
userEvent.click(frameTitles[frameTitles.length - 1]);
9793

9894
// two frames are now collapsed
9995
expect(screen.getAllByTestId('toggle-button-expanded')).toHaveLength(2);
@@ -114,8 +110,7 @@ describe('StackTrace', function () {
114110
expect(screen.getAllByTestId('toggle-button-collapsed')).toHaveLength(4);
115111

116112
// collapse the expanded frame (by default)
117-
fireEvent.mouseDown(expandedToggleButtons);
118-
fireEvent.click(expandedToggleButtons);
113+
userEvent.click(expandedToggleButtons);
119114

120115
// all frames are now collapsed
121116
expect(screen.queryByTestId('toggle-button-expanded')).not.toBeInTheDocument();
@@ -124,11 +119,8 @@ describe('StackTrace', function () {
124119
const collapsedToggleButtons = screen.getAllByTestId('toggle-button-collapsed');
125120

126121
// expand penultimate and last frame
127-
fireEvent.mouseDown(collapsedToggleButtons[collapsedToggleButtons.length - 2]);
128-
fireEvent.click(collapsedToggleButtons[collapsedToggleButtons.length - 2]);
129-
130-
fireEvent.mouseDown(collapsedToggleButtons[collapsedToggleButtons.length - 1]);
131-
fireEvent.click(collapsedToggleButtons[collapsedToggleButtons.length - 1]);
122+
userEvent.click(collapsedToggleButtons[collapsedToggleButtons.length - 2]);
123+
userEvent.click(collapsedToggleButtons[collapsedToggleButtons.length - 1]);
132124

133125
// two frames are now collapsed
134126
expect(screen.getAllByTestId('toggle-button-expanded')).toHaveLength(2);

0 commit comments

Comments
 (0)