Skip to content

Commit d312c70

Browse files
committed
Add test from reduxjs#293 and uncomment now-passing expect in 'should pass state consistently to mapState'
1 parent 82e8a6a commit d312c70

File tree

2 files changed

+66
-9
lines changed

2 files changed

+66
-9
lines changed

test/components/Provider.spec.js

+64-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import expect from 'expect'
22
import React, { PropTypes, Component } from 'react'
33
import TestUtils from 'react-addons-test-utils'
44
import { createStore } from 'redux'
5-
import { Provider } from '../../src/index'
5+
import { Provider, connect } from '../../src/index'
66

77
describe('React', () => {
88
describe('Provider', () => {
@@ -108,4 +108,67 @@ describe('React', () => {
108108
expect(spy.calls.length).toBe(0)
109109
})
110110
})
111+
112+
it('should pass state consistently to mapState', () => {
113+
function stringBuilder(prev = '', action) {
114+
return action.type === 'APPEND'
115+
? prev + action.body
116+
: prev
117+
}
118+
119+
const store = createStore(stringBuilder)
120+
121+
store.dispatch({ type: 'APPEND', body: 'a' })
122+
let childMapStateInvokes = 0
123+
124+
@connect(state => ({ state }), null, null, { withRef: true })
125+
class Container extends Component {
126+
emitChange() {
127+
store.dispatch({ type: 'APPEND', body: 'b' })
128+
}
129+
130+
render() {
131+
return (
132+
<div>
133+
<button ref="button" onClick={this.emitChange.bind(this)}>change</button>
134+
<ChildContainer parentState={this.props.state} />
135+
</div>
136+
)
137+
}
138+
}
139+
140+
@connect((state, parentProps) => {
141+
childMapStateInvokes++
142+
// The state from parent props should always be consistent with the current state
143+
expect(state).toEqual(parentProps.parentState)
144+
return {}
145+
})
146+
class ChildContainer extends Component {
147+
render() {
148+
return <div {...this.props} />
149+
}
150+
}
151+
152+
const tree = TestUtils.renderIntoDocument(
153+
<Provider store={store}>
154+
<Container />
155+
</Provider>
156+
)
157+
158+
expect(childMapStateInvokes).toBe(1)
159+
160+
// The store state stays consistent when setState calls are batched
161+
store.dispatch({ type: 'APPEND', body: 'c' })
162+
expect(childMapStateInvokes).toBe(2)
163+
164+
// setState calls DOM handlers are batched
165+
const container = TestUtils.findRenderedComponentWithType(tree, Container)
166+
const node = container.getWrappedInstance().refs.button
167+
TestUtils.Simulate.click(node)
168+
expect(childMapStateInvokes).toBe(3)
169+
170+
// Provider uses unstable_batchedUpdates() under the hood
171+
store.dispatch({ type: 'APPEND', body: 'd' })
172+
expect(childMapStateInvokes).toBe(4)
173+
})
111174
})

test/components/connect.spec.js

+2-8
Original file line numberDiff line numberDiff line change
@@ -1538,14 +1538,8 @@ describe('React', () => {
15381538
TestUtils.Simulate.click(node)
15391539
expect(childMapStateInvokes).toBe(3)
15401540

1541-
// In future all setState calls will be batched[1]. Uncomment when it
1542-
// happens. For now redux-batched-updates middleware can be used as
1543-
// workaround this.
1544-
//
1545-
// [1]: https://twitter.com/sebmarkbage/status/642366976824864768
1546-
//
1547-
// store.dispatch({ type: 'APPEND', body: 'd' })
1548-
// expect(childMapStateInvokes).toBe(4)
1541+
store.dispatch({ type: 'APPEND', body: 'd' })
1542+
expect(childMapStateInvokes).toBe(4)
15491543
})
15501544

15511545
it('should not render the wrapped component when mapState does not produce change', () => {

0 commit comments

Comments
 (0)