Skip to content

Commit cdbd00d

Browse files
feat: migrate enzyme with RTL (#615)
1 parent 683f57d commit cdbd00d

10 files changed

+11493
-7160
lines changed

jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const { createConfig } = require('@edx/frontend-build');
22

33
module.exports = createConfig('jest', {
4-
setupFiles: [
4+
setupFilesAfterEnv: [
55
'<rootDir>/src/setupTest.js',
66
],
77
testTimeout: 20000,

package-lock.json

Lines changed: 11434 additions & 7101 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@
3636
"@edx/browserslist-config": "1.2.0",
3737
"@edx/frontend-build": "13.0.14",
3838
"@edx/paragon": "21.5.6",
39+
"@testing-library/jest-dom": "6.1.5",
40+
"@testing-library/react": "12.1.5",
3941
"@testing-library/react-hooks": "^8.0.1",
40-
"@wojtekmaj/enzyme-adapter-react-17": "0.8.0",
4142
"axios-mock-adapter": "^1.21.3",
4243
"core-js": "3.34.0",
43-
"enzyme": "3.11.0",
4444
"husky": "8.0.3",
4545
"jsdoc": "^4.0.0",
4646
"nodemon": "3.0.2",

src/react/AppProvider.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ export default function AppProvider({ store, children, wrapWithRouter }) {
7474
<OptionalReduxProvider store={store}>
7575
{wrapWithRouter ? (
7676
<Router basename={basename}>
77-
{children}
77+
<div data-testid="browser-router">
78+
{children}
79+
</div>
7880
</Router>
7981
) : children}
8082
</OptionalReduxProvider>

src/react/AppProvider.test.jsx

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React from 'react';
22
import { createStore } from 'redux';
3-
import { mount } from 'enzyme';
4-
import { BrowserRouter as Router } from 'react-router-dom';
3+
import { render } from '@testing-library/react';
54
import AppProvider from './AppProvider';
65
import { initialize } from '../initialize';
76

@@ -52,56 +51,57 @@ describe('AppProvider', () => {
5251
it('should render its children with a router', () => {
5352
const component = (
5453
<AppProvider store={createStore(state => state)}>
55-
<div>Child One</div>
56-
<div>Child Two</div>
54+
<div className="child">Child One</div>
55+
<div className="child">Child Two</div>
5756
</AppProvider>
5857
);
5958

60-
const wrapper = mount(component);
61-
const list = wrapper.find('div');
62-
expect(wrapper.find(Router).length).toEqual(1);
59+
const wrapper = render(component);
60+
const list = wrapper.container.querySelectorAll('div.child');
61+
62+
expect(wrapper.getByTestId('browser-router')).toBeInTheDocument();
6363
expect(list.length).toEqual(2);
64-
expect(list.at(0).text()).toEqual('Child One');
65-
expect(list.at(1).text()).toEqual('Child Two');
64+
expect(list[0].textContent).toEqual('Child One');
65+
expect(list[1].textContent).toEqual('Child Two');
6666

67-
const reduxProvider = wrapper.find('Provider');
68-
expect(reduxProvider.length).toEqual(1);
67+
const reduxProvider = wrapper.getByTestId('redux-provider');
68+
expect(reduxProvider).toBeInTheDocument();
6969
});
7070

7171
it('should render its children without a router', () => {
7272
const component = (
7373
<AppProvider store={createStore(state => state)} wrapWithRouter={false}>
74-
<div>Child One</div>
75-
<div>Child Two</div>
74+
<div className="child">Child One</div>
75+
<div className="child">Child Two</div>
7676
</AppProvider>
7777
);
7878

79-
const wrapper = mount(component);
80-
const list = wrapper.find('div');
81-
expect(wrapper.find(Router).length).toEqual(0);
79+
const wrapper = render(component);
80+
const list = wrapper.container.querySelectorAll('div.child');
81+
expect(wrapper.queryByTestId('browser-router')).not.toBeInTheDocument();
8282
expect(list.length).toEqual(2);
83-
expect(list.at(0).text()).toEqual('Child One');
84-
expect(list.at(1).text()).toEqual('Child Two');
83+
expect(list[0].textContent).toEqual('Child One');
84+
expect(list[1].textContent).toEqual('Child Two');
8585

86-
const reduxProvider = wrapper.find('Provider');
87-
expect(reduxProvider.length).toEqual(1);
86+
const reduxProvider = wrapper.getByTestId('redux-provider');
87+
expect(reduxProvider).toBeInTheDocument();
8888
});
8989

9090
it('should skip redux Provider if not given a store', () => {
9191
const component = (
9292
<AppProvider>
93-
<div>Child One</div>
94-
<div>Child Two</div>
93+
<div className="child">Child One</div>
94+
<div className="child">Child Two</div>
9595
</AppProvider>
9696
);
9797

98-
const wrapper = mount(component);
99-
const list = wrapper.find('div');
98+
const wrapper = render(component);
99+
const list = wrapper.container.querySelectorAll('div.child');
100100
expect(list.length).toEqual(2);
101-
expect(list.at(0).text()).toEqual('Child One');
102-
expect(list.at(1).text()).toEqual('Child Two');
101+
expect(list[0].textContent).toEqual('Child One');
102+
expect(list[1].textContent).toEqual('Child Two');
103103

104-
const reduxProvider = wrapper.find('Provider');
105-
expect(reduxProvider.length).toEqual(0);
104+
const reduxProvider = wrapper.queryByTestId('redux-provider');
105+
expect(reduxProvider).not.toBeInTheDocument();
106106
});
107107
});

src/react/AuthenticatedPageRoute.test.jsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable react/jsx-no-constructed-context-values */
22
import React from 'react';
3-
import { mount } from 'enzyme';
3+
import { render } from '@testing-library/react';
44
import { Route, Routes, MemoryRouter } from 'react-router-dom';
55
import { getAuthenticatedUser, getLoginRedirectUrl } from '../auth';
66
import AuthenticatedPageRoute from './AuthenticatedPageRoute';
@@ -47,7 +47,7 @@ describe('AuthenticatedPageRoute', () => {
4747
</AppContext.Provider>
4848
);
4949
global.location.href = 'http://localhost/authenticated';
50-
mount(component);
50+
render(component);
5151
expect(getLoginRedirectUrl).toHaveBeenCalledWith('http://localhost/authenticated');
5252
expect(sendPageEvent).not.toHaveBeenCalled();
5353
expect(global.location.assign).toHaveBeenCalledWith('http://localhost/login?next=http%3A%2F%2Flocalhost%2Fauthenticated');
@@ -76,7 +76,7 @@ describe('AuthenticatedPageRoute', () => {
7676
</MemoryRouter>
7777
</AppContext.Provider>
7878
);
79-
mount(component);
79+
render(component);
8080
expect(getLoginRedirectUrl).not.toHaveBeenCalled();
8181
expect(sendPageEvent).not.toHaveBeenCalled();
8282
expect(global.location.assign).toHaveBeenCalledWith('http://localhost/elsewhere');
@@ -100,13 +100,13 @@ describe('AuthenticatedPageRoute', () => {
100100
</MemoryRouter>
101101
</AppContext.Provider>
102102
);
103-
const wrapper = mount(component);
103+
const wrapper = render(component);
104104

105105
expect(getLoginRedirectUrl).not.toHaveBeenCalled();
106106
expect(global.location.assign).not.toHaveBeenCalled();
107107
expect(sendPageEvent).not.toHaveBeenCalled();
108-
const element = wrapper.find('p');
109-
expect(element.text()).toEqual('Anonymous'); // This is just a sanity check on our setup.
108+
const element = wrapper.container.querySelector('p');
109+
expect(element.textContent).toEqual('Anonymous'); // This is just a sanity check on our setup.
110110
});
111111

112112
it('should render authenticated route if authenticated', () => {
@@ -125,11 +125,11 @@ describe('AuthenticatedPageRoute', () => {
125125
</MemoryRouter>
126126
</AppContext.Provider>
127127
);
128-
const wrapper = mount(component);
128+
const wrapper = render(component);
129129
expect(getLoginRedirectUrl).not.toHaveBeenCalled();
130130
expect(global.location.assign).not.toHaveBeenCalled();
131131
expect(sendPageEvent).toHaveBeenCalled();
132-
const element = wrapper.find('p');
133-
expect(element.text()).toEqual('Authenticated');
132+
const element = wrapper.container.querySelector('p');
133+
expect(element.textContent).toEqual('Authenticated');
134134
});
135135
});

src/react/ErrorBoundary.test.jsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import React from 'react';
2-
import { mount } from 'enzyme';
2+
import { render } from '@testing-library/react';
33

44
import ErrorBoundary from './ErrorBoundary';
5-
import ErrorPage from './ErrorPage';
65
import { initializeMockApp } from '..';
76

87
describe('ErrorBoundary', () => {
@@ -28,10 +27,10 @@ describe('ErrorBoundary', () => {
2827
<div>Yay</div>
2928
</ErrorBoundary>
3029
);
31-
const wrapper = mount(component);
30+
const { container: wrapper } = render(component);
3231

33-
const element = wrapper.find('div');
34-
expect(element.text()).toEqual('Yay');
32+
const element = wrapper.querySelector('div');
33+
expect(element.textContent).toEqual('Yay');
3534
});
3635

3736
it('should render ErrorPage if it has an error', () => {
@@ -45,7 +44,7 @@ describe('ErrorBoundary', () => {
4544
</ErrorBoundary>
4645
);
4746

48-
mount(component);
47+
render(component);
4948

5049
expect(logError).toHaveBeenCalledTimes(1);
5150
expect(logError).toHaveBeenCalledWith(
@@ -57,28 +56,29 @@ describe('ErrorBoundary', () => {
5756
});
5857
it('should render the fallback component when an error occurs', () => {
5958
function FallbackComponent() {
60-
return <div>Oops, something went wrong!</div>;
59+
return <div data-testid="fallback-component">Oops, something went wrong!</div>;
6160
}
6261
function ComponentError() {
6362
throw new Error('An error occurred during the click event!');
6463
}
65-
const wrapper = mount(
64+
const wrapper = render(
6665
<ErrorBoundary fallbackComponent={<FallbackComponent />}>
6766
<ComponentError />
6867
</ErrorBoundary>,
6968
);
70-
expect(wrapper.contains(<FallbackComponent />)).toBe(true);
69+
70+
expect(wrapper.queryByTestId('fallback-component')).toBeInTheDocument();
7171
});
7272

7373
it('should render the ErrorPage fallbackComponent is null', () => {
7474
function ComponentError() {
7575
throw new Error('An error occurred during the click event!');
7676
}
77-
const wrapper = mount(
77+
const wrapper = render(
7878
<ErrorBoundary fallbackComponent={null}>
7979
<ComponentError />
8080
</ErrorBoundary>,
8181
);
82-
expect(wrapper.contains(<ErrorPage />)).toBe(true);
82+
expect(wrapper.queryByTestId('error-page')).toBeInTheDocument();
8383
});
8484
});

src/react/ErrorPage.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function ErrorPage({
3636

3737
return (
3838
<IntlProvider locale={locale} messages={getMessages()}>
39-
<Container fluid className="py-5 justify-content-center align-items-start text-center">
39+
<Container fluid className="py-5 justify-content-center align-items-start text-center" data-testid="error-page">
4040
<Row>
4141
<Col>
4242
<p className="text-muted">

src/react/OptionalReduxProvider.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ export default function OptionalReduxProvider({ store, children }) {
1313

1414
return (
1515
<Provider store={store}>
16-
{children}
16+
<div data-testid="redux-provider">
17+
{children}
18+
</div>
1719
</Provider>
1820
);
1921
}

src/setupTest.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
/* eslint-disable import/no-extraneous-dependencies */
22
import 'core-js/stable';
33
import 'regenerator-runtime/runtime';
4-
5-
import Enzyme from 'enzyme';
6-
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
7-
8-
Enzyme.configure({ adapter: new Adapter() });
4+
import '@testing-library/jest-dom';
95

106
// These configuration values are usually set in webpack's EnvironmentPlugin however
117
// Jest does not use webpack so we need to set these so for testing

0 commit comments

Comments
 (0)