Skip to content

Commit 901e907

Browse files
authored
Update React Redux recipe to use custom render with wrapper (testing-library#424)
* Chore: Update react-redux recipe to use custom render with wrapper * Review fixes, removed the h1 and refactored the class component to a functional one * Added the export and updated the comment after kent's review
1 parent 560e372 commit 901e907

File tree

1 file changed

+61
-45
lines changed

1 file changed

+61
-45
lines changed

docs/example-react-redux.md

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,25 @@ title: React Redux
88
import React from 'react'
99
import { connect } from 'react-redux'
1010

11-
class Counter extends React.Component {
12-
increment = () => {
13-
this.props.dispatch({ type: 'INCREMENT' })
11+
const Counter = ({ dispatch, count }) => {
12+
const increment = () => {
13+
dispatch({ type: 'INCREMENT' })
1414
}
1515

16-
decrement = () => {
17-
this.props.dispatch({ type: 'DECREMENT' })
16+
const decrement = () => {
17+
dispatch({ type: 'DECREMENT' })
1818
}
1919

20-
render() {
21-
return (
20+
return (
21+
<div>
22+
<h2>Counter</h2>
2223
<div>
23-
<h2>Counter</h2>
24-
<div>
25-
<button onClick={this.decrement}>-</button>
26-
<span data-testid="count-value">{this.props.count}</span>
27-
<button onClick={this.increment}>+</button>
28-
</div>
24+
<button onClick={this.decrement}>-</button>
25+
<span data-testid="count-value">{count}</span>
26+
<button onClick={this.increment}>+</button>
2927
</div>
30-
)
31-
}
28+
</div>
29+
)
3230
}
3331

3432
export default connect(state => ({ count: state.count }))(Counter)
@@ -58,58 +56,76 @@ export function reducer(state = initialState, action) {
5856
}
5957
```
6058

61-
Now here's what your test will look like:
59+
To test our connected component we can create a custom `render` function using
60+
the `wrapper` option as explained in the
61+
[setup](./react-testing-library/setup.md) page.
62+
Our custom `render` function can look like this:
6263

63-
```jsx
64-
// counter.test.js
64+
```js
65+
// test-utils.js
6566
import React from 'react'
67+
import { render as rtlRender } from '@testing-library/react'
6668
import { createStore } from 'redux'
6769
import { Provider } from 'react-redux'
68-
import { render, fireEvent } from '@testing-library/react'
69-
import '@testing-library/jest-dom/extend-expect'
70-
import { initialState, reducer } from './reducer.js'
71-
import Counter from './counter.js'
72-
7370

74-
// this is a handy function that I normally make available for all my tests
75-
// that deal with connected components.
76-
// you can provide initialState for the entire store that the ui is rendered with
77-
function renderWithRedux(
71+
function render(
7872
ui,
79-
{ initialState, store = createStore(reducer, initialState) } = {}
73+
{
74+
initialState,
75+
store = createStore(reducer, initialState),
76+
...renderOptions
77+
} = {}
8078
) {
81-
return {
82-
...render(<Provider store={store}>{ui}</Provider>),
83-
// adding `store` to the returned utilities to allow us
84-
// to reference it in our tests (just try to avoid using
85-
// this to test implementation details).
86-
store,
79+
function Wrapper({ children }) {
80+
return <Provider store={store}>{children}</Provider>
8781
}
82+
return rtlRender(ui, { wrapper: Wrapper, ...renderOptions })
8883
}
8984

85+
// re-export everything
86+
export * from '@testing-library/react'
87+
88+
// override render method
89+
export { render }
90+
```
91+
92+
```jsx
93+
// counter.test.js
94+
import React from 'react'
95+
import { createStore } from 'redux'
96+
import { Provider } from 'react-redux'
97+
import { } from '@testing-library/react'
98+
// We're using our own custom render function and not RTL's render
99+
// our custom utils also re-export everything from RTL
100+
// so we can import fireEvent and screen here as well
101+
import { render, fireEvent, screen } from './test-utils.js
102+
import '@testing-library/jest-dom/extend-expect'
103+
import { initialState, reducer } from './reducer.js'
104+
import Counter from './counter.js'
105+
90106
test('can render with redux with defaults', () => {
91-
const { getByTestId, getByText } = renderWithRedux(<Counter />)
92-
fireEvent.click(getByText('+'))
93-
expect(getByTestId('count-value')).toHaveTextContent('1')
107+
renderWithRedux(<Counter />)
108+
fireEvent.click(screen.getByText('+'))
109+
expect(screen.getByTestId('count-value')).toHaveTextContent('1')
94110
})
95111
96112
test('can render with redux with custom initial state', () => {
97-
const { getByTestId, getByText } = renderWithRedux(<Counter />, {
113+
renderWithRedux(<Counter />, {
98114
initialState: { count: 3 },
99115
})
100-
fireEvent.click(getByText('-'))
101-
expect(getByTestId('count-value')).toHaveTextContent('2')
116+
fireEvent.click(screen.getByText('-'))
117+
expect(screen.getByTestId('count-value')).toHaveTextContent('2')
102118
})
103119
104120
test('can render with redux with custom store', () => {
105121
// this is a silly store that can never be changed
106122
const store = createStore(() => ({ count: 1000 }))
107-
const { getByTestId, getByText } = renderWithRedux(<Counter />, {
123+
renderWithRedux(<Counter />, {
108124
store,
109125
})
110-
fireEvent.click(getByText('+'))
111-
expect(getByTestId('count-value')).toHaveTextContent('1000')
112-
fireEvent.click(getByText('-'))
113-
expect(getByTestId('count-value')).toHaveTextContent('1000')
126+
fireEvent.click(screen.getByText('+'))
127+
expect(screen.getByTestId('count-value')).toHaveTextContent('1000')
128+
fireEvent.click(screen.getByText('-'))
129+
expect(screen.getByTestId('count-value')).toHaveTextContent('1000')
114130
})
115131
```

0 commit comments

Comments
 (0)