Skip to content

Commit 8fb8a39

Browse files
committed
Add connectAdvanced() tests
1 parent 1dc56ca commit 8fb8a39

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import React, { Component } from 'react'
2+
import * as rtl from 'react-testing-library'
3+
import { Provider as ProviderMock, connectAdvanced } from '../../src/index.js'
4+
import { createStore } from 'redux'
5+
import 'jest-dom/extend-expect'
6+
7+
describe('React', () => {
8+
describe('connectAdvanced', () => {
9+
it('should map state and render once on mount', () => {
10+
const initialState = {
11+
foo: 'bar'
12+
}
13+
14+
let mapCount = 0
15+
let renderCount = 0
16+
17+
const store = createStore(() => initialState)
18+
19+
function Inner(props) {
20+
renderCount++
21+
return <div data-testid="foo">{JSON.stringify(props)}</div>
22+
}
23+
24+
const Container = connectAdvanced(() => {
25+
return state => {
26+
mapCount++
27+
return state
28+
}
29+
})(Inner)
30+
31+
const tester = rtl.render(
32+
<ProviderMock store={store}>
33+
<Container />
34+
</ProviderMock>
35+
)
36+
37+
expect(tester.getByTestId('foo')).toHaveTextContent('bar')
38+
39+
expect(mapCount).toEqual(1)
40+
expect(renderCount).toEqual(1)
41+
})
42+
43+
it('should render on reference change', () => {
44+
let mapCount = 0
45+
let renderCount = 0
46+
47+
// force new reference on each dispatch
48+
const store = createStore(() => ({
49+
foo: 'bar'
50+
}))
51+
52+
function Inner(props) {
53+
renderCount++
54+
return <div data-testid="foo">{JSON.stringify(props)}</div>
55+
}
56+
57+
const Container = connectAdvanced(() => {
58+
return state => {
59+
mapCount++
60+
return state
61+
}
62+
})(Inner)
63+
64+
rtl.render(
65+
<ProviderMock store={store}>
66+
<Container />
67+
</ProviderMock>
68+
)
69+
70+
store.dispatch({ type: 'NEW_REFERENCE' })
71+
72+
// Should have mapped the state on mount and on the dispatch
73+
expect(mapCount).toEqual(2)
74+
75+
// Should have rendered on mount and after the dispatch bacause the map
76+
// state returned new reference
77+
expect(renderCount).toEqual(2)
78+
})
79+
80+
it('should not render when the returned reference does not change', () => {
81+
const staticReference = {
82+
foo: 'bar'
83+
}
84+
85+
let mapCount = 0
86+
let renderCount = 0
87+
88+
// force new reference on each dispatch
89+
const store = createStore(() => ({
90+
foo: 'bar'
91+
}))
92+
93+
function Inner(props) {
94+
renderCount++
95+
return <div data-testid="foo">{JSON.stringify(props)}</div>
96+
}
97+
98+
const Container = connectAdvanced(() => {
99+
return () => {
100+
mapCount++
101+
// but return static reference
102+
return staticReference
103+
}
104+
})(Inner)
105+
106+
const tester = rtl.render(
107+
<ProviderMock store={store}>
108+
<Container />
109+
</ProviderMock>
110+
)
111+
112+
store.dispatch({ type: 'NEW_REFERENCE' })
113+
114+
expect(tester.getByTestId('foo')).toHaveTextContent('bar')
115+
116+
// The state should have been mapped twice: on mount and on the dispatch
117+
expect(mapCount).toEqual(2)
118+
119+
// But the render should have been called only on mount since the map state
120+
// did not return a new reference
121+
expect(renderCount).toEqual(1)
122+
})
123+
124+
it('should map state on own props change but not render when the reference does not change', () => {
125+
const staticReference = {
126+
foo: 'bar'
127+
}
128+
129+
let mapCount = 0
130+
let renderCount = 0
131+
132+
const store = createStore(() => staticReference)
133+
134+
function Inner(props) {
135+
renderCount++
136+
return <div data-testid="foo">{JSON.stringify(props)}</div>
137+
}
138+
139+
const Container = connectAdvanced(() => {
140+
return () => {
141+
mapCount++
142+
// return the static reference
143+
return staticReference
144+
}
145+
})(Inner)
146+
147+
class OuterComponent extends Component {
148+
constructor() {
149+
super()
150+
this.state = { foo: 'FOO' }
151+
}
152+
153+
setFoo(foo) {
154+
this.setState({ foo })
155+
}
156+
157+
render() {
158+
return (
159+
<div>
160+
<Container {...this.state} />
161+
</div>
162+
)
163+
}
164+
}
165+
166+
let outerComponent
167+
rtl.render(
168+
<ProviderMock store={store}>
169+
<OuterComponent ref={c => (outerComponent = c)} />
170+
</ProviderMock>
171+
)
172+
173+
outerComponent.setFoo('BAR')
174+
175+
// map on mount and on prop change
176+
expect(mapCount).toEqual(2)
177+
178+
// render only on mount but skip on prop change because no new
179+
// reference was returned
180+
expect(renderCount).toEqual(1)
181+
})
182+
})
183+
})

0 commit comments

Comments
 (0)