Skip to content

Commit 3a915e6

Browse files
committed
feat: upgrade to react 18, react-router v6, react-redux v8, react-testing-library
BREAKING CHANGE: swap enzyme in favour of react-testing-library (RTL) for unit tests; upgrade to React v18, react-redux v8, react-router-dom v6
1 parent d0a40c6 commit 3a915e6

File tree

7 files changed

+49
-57
lines changed

7 files changed

+49
-57
lines changed

template.json

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
{
22
"package": {
33
"dependencies": {
4-
"@types/enzyme": "3.10.4",
5-
"@types/jest": "27.0.0",
4+
"@testing-library/react": "14.0.0",
65
"@types/node": "14.0.0",
7-
"@types/react": "17.0.0",
8-
"@types/react-dom": "17.0.0",
9-
"@types/react-redux": "7.1.7",
10-
"@types/react-router-dom": "5.1.3",
11-
"@types/redux-mock-store": "^1.0.1",
6+
"@types/react": "18.2.6",
7+
"@types/react-dom": "18.2.4",
8+
"@types/react-redux": "8.0.5",
9+
"@types/react-router-dom": "5.3.3",
10+
"@types/redux-mock-store": "1.0.1",
1211
"@typescript-eslint/eslint-plugin": "5.59.5",
1312
"@typescript-eslint/parser": "5.9.1",
14-
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.0",
15-
"enzyme": "3.11.0",
1613
"eslint": "8.6.0",
1714
"eslint-config-airbnb-typescript": "16.1.0",
1815
"eslint-config-prettier": "8.0.0",
@@ -22,12 +19,14 @@
2219
"eslint-plugin-react": "7.21.5",
2320
"eslint-plugin-react-hooks": "4.0.8",
2421
"prettier": "2.0.0",
25-
"react-redux": "7.1.3",
26-
"react-router-dom": "5.1.2",
27-
"redux": "4.0.5",
22+
"react-redux": "8.0.5",
23+
"react-router-dom": "6.11.1",
24+
"redux": "4.2.1",
2825
"redux-devtools-extension": "2.13.8",
2926
"redux-mock-store": "1.5.4",
30-
"typescript": "~4.5.0"
27+
"typescript": "~4.5.0",
28+
"@testing-library/jest-dom": "5.16.5",
29+
"@babel/runtime": "7.21.5"
3130
},
3231
"scripts": {
3332
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",

template/src/App.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import { BrowserRouter, Switch, Route } from 'react-router-dom'
2+
import { BrowserRouter, Routes, Route } from 'react-router-dom'
33

44
import { Navbar } from './components/Navbar'
55
import { About } from './pages/About'
@@ -9,12 +9,12 @@ const App: React.FC = () => {
99
return (
1010
<BrowserRouter>
1111
<Navbar />
12-
<Switch>
13-
<div className="container">
14-
<Route path="/" component={Home} exact />
15-
<Route path="/about" component={About} />
16-
</div>
17-
</Switch>
12+
<div className="container">
13+
<Routes>
14+
<Route path="/" element={<Home />} />
15+
<Route path="/about" element={<About />} />
16+
</Routes>
17+
</div>
1818
</BrowserRouter>
1919
)
2020
}

template/src/components/counter/Counter.spec.tsx

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import React from 'react'
1+
import { render, screen, fireEvent } from '@testing-library/react'
22
import { Provider } from 'react-redux'
3-
import { mount } from 'enzyme'
43
import configureStore from 'redux-mock-store'
54

65
import { actionTypes } from '../../features/counter'
@@ -17,52 +16,43 @@ describe('Counter', () => {
1716
// Add jest mock spy to watch for store.dispatch method. See https://jestjs.io/docs/en/jest-object#jestspyonobject-methodname for more info
1817
jest.spyOn(store, 'dispatch')
1918

20-
beforeEach(() => {
21-
// Clear any saved mock data from previous tests, because jest saves calls data for spies and mocks, https://jestjs.io/docs/en/mock-function-api#mockfnmockclear
22-
store.dispatch.mockClear()
23-
})
24-
25-
it('renders without crashing.', () => {
26-
const wrapper = mount(
19+
test('renders without crashing.', () => {
20+
render(
2721
<Provider store={store}>
2822
<Counter />
2923
</Provider>
3024
)
3125

32-
const countValue = wrapper.find('strong').text()
33-
expect(countValue).toBe('42')
26+
const countValue = screen.getByText('42')
27+
expect(countValue).toBeInTheDocument()
3428
})
3529

36-
it('should be possible to increment counter.', () => {
37-
const wrapper = mount(
30+
test('should be possible to increment counter.', () => {
31+
render(
3832
<Provider store={store}>
3933
<Counter />
4034
</Provider>
4135
)
4236

43-
wrapper
44-
.find('button')
45-
.filter({ 'data-qa': 'increment-counter' })
46-
.simulate('click')
37+
const incrementButton = screen.getByRole('button', { name: 'increment' })
38+
fireEvent.click(incrementButton)
4739

48-
expect(store.dispatch).toBeCalledTimes(1)
40+
expect(store.dispatch).toHaveBeenCalledTimes(1)
4941

50-
expect(store.dispatch).toBeCalledWith({
42+
expect(store.dispatch).toHaveBeenCalledWith({
5143
type: actionTypes.INCREMENT_COUNTER,
5244
})
5345
})
5446

55-
it('should be possible to decrement counter.', () => {
56-
const wrapper = mount(
47+
test('should be possible to decrement counter.', () => {
48+
render(
5749
<Provider store={store}>
5850
<Counter />
5951
</Provider>
6052
)
6153

62-
wrapper
63-
.find('button')
64-
.filter({ 'data-qa': 'decrement-counter' })
65-
.simulate('click')
54+
const decrementButton = screen.getByRole('button', { name: 'decrement' })
55+
fireEvent.click(decrementButton)
6656

6757
expect(store.dispatch).toHaveBeenCalledTimes(1)
6858

template/src/features/counter/counterReducer.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import counterReducer from './counterReducer'
33
import { CounterActionTypes } from './types'
44

55
describe('features > counter > counterReducer', () => {
6-
it(`increments value, if ${INCREMENT_COUNTER} action is provided`, () => {
6+
test(`increments value, if ${INCREMENT_COUNTER} action is provided`, () => {
77
const initialState = {
88
value: 0,
99
}
@@ -19,7 +19,7 @@ describe('features > counter > counterReducer', () => {
1919
expect(counterReducer(initialState, action)).toEqual(expectedState)
2020
})
2121

22-
it(`increments value, if ${DECREMENT_COUNTER} action is provided`, () => {
22+
test(`increments value, if ${DECREMENT_COUNTER} action is provided`, () => {
2323
const initialState = {
2424
value: 0,
2525
}

template/src/index.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import React from 'react'
2-
import ReactDOM from 'react-dom'
1+
import { createRoot } from 'react-dom/client'
32
import { Provider } from 'react-redux'
43
import store from './store'
54

65
import './index.css'
76

87
import App from './App'
98

10-
ReactDOM.render(
9+
const container = document.getElementById('root') as HTMLDivElement
10+
const root = createRoot(container!)
11+
12+
root.render(
1113
<Provider store={store}>
1214
<App />
13-
</Provider>,
14-
document.getElementById('root')
15+
</Provider>
1516
)

template/src/pages/About.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ export const About: React.FC = () => {
1313
omnis doloremque itaque eius eaque sint facilis unde tenetur reiciendis
1414
aliquam soluta?
1515
</p>
16-
<button type="button" className="btn" onClick={() => navigate('/')}>
16+
<button
17+
type="button"
18+
className="btn"
19+
cy-data="go-back-button"
20+
onClick={() => navigate('/')}
21+
>
1722
Go back
1823
</button>
1924
</Fragment>

template/src/setupTests.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
import { configure } from 'enzyme'
2-
import Adapter from '@wojtekmaj/enzyme-adapter-react-17'
3-
4-
configure({ adapter: new Adapter() })
1+
import '@testing-library/jest-dom'

0 commit comments

Comments
 (0)