Skip to content

Commit 013e85e

Browse files
committed
ShallowWrapper calls update() automatically
1 parent 085e014 commit 013e85e

File tree

2 files changed

+88
-7
lines changed

2 files changed

+88
-7
lines changed

packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4656,4 +4656,75 @@ describe('shallow', () => {
46564656
});
46574657
});
46584658
});
4659+
describe('setState through a props method', () => {
4660+
it('should be able to get the latest state value', () => {
4661+
const Child = props => <button onClick={props.onClick}>click</button>;
4662+
class App extends React.Component {
4663+
constructor(props) {
4664+
super(props);
4665+
this.state = {
4666+
count: 0,
4667+
};
4668+
}
4669+
onIncrement() {
4670+
this.setState({
4671+
count: this.state.count + 1,
4672+
});
4673+
}
4674+
render() {
4675+
return (
4676+
<div>
4677+
<Child onClick={() => this.onIncrement()} />
4678+
<p>{this.state.count}</p>
4679+
</div>
4680+
);
4681+
}
4682+
}
4683+
const wrapper = shallow(<App />);
4684+
const p = wrapper.find('p');
4685+
expect(wrapper.find('p').text()).to.equal('0');
4686+
wrapper.find(Child).prop('onClick')();
4687+
// this is still 0 because the wrapper won't be updated
4688+
expect(p.text()).to.equal('0');
4689+
expect(wrapper.find('p').text()).to.equal('1');
4690+
});
4691+
});
4692+
describe('setState through a props method in async', () => {
4693+
it('should be able to get the latest state value', (done) => {
4694+
const Child = props => <button onClick={props.onClick}>click</button>;
4695+
let App;
4696+
const promise = new Promise((resolve) => {
4697+
App = class extends React.Component {
4698+
constructor(props) {
4699+
super(props);
4700+
this.state = {
4701+
count: 0,
4702+
};
4703+
}
4704+
onIncrement() {
4705+
setTimeout(() => {
4706+
this.setState({
4707+
count: this.state.count + 1,
4708+
}, resolve);
4709+
});
4710+
}
4711+
render() {
4712+
return (
4713+
<div>
4714+
<Child onClick={() => this.onIncrement()} />
4715+
<p>{this.state.count}</p>
4716+
</div>
4717+
);
4718+
}
4719+
};
4720+
});
4721+
const wrapper = shallow(<App />);
4722+
promise.then(() => {
4723+
expect(wrapper.find('p').text()).to.equal('1');
4724+
done();
4725+
});
4726+
expect(wrapper.find('p').text()).to.equal('0');
4727+
wrapper.find(Child).prop('onClick')();
4728+
});
4729+
});
46594730
});

packages/enzyme/src/ShallowWrapper.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,17 @@ class ShallowWrapper {
152152
return this[ROOT];
153153
}
154154

155+
getRootNodeInternal() {
156+
return this[ROOT][NODE];
157+
}
155158

156159
getNodeInternal() {
157160
if (this.length !== 1) {
158161
throw new Error('ShallowWrapper::getNode() can only be called when wrapping one node');
159162
}
163+
if (this[ROOT] === this) {
164+
this.update();
165+
}
160166
return this[NODE];
161167
}
162168

@@ -169,7 +175,7 @@ class ShallowWrapper {
169175
if (this.length !== 1) {
170176
throw new Error('ShallowWrapper::getElement() can only be called when wrapping one node');
171177
}
172-
return getAdapter(this[OPTIONS]).nodeToElement(this[NODE]);
178+
return getAdapter(this[OPTIONS]).nodeToElement(this.getNodeInternal());
173179
}
174180

175181
/**
@@ -178,7 +184,7 @@ class ShallowWrapper {
178184
* @return {Array<ReactElement>}
179185
*/
180186
getElements() {
181-
return this[NODES].map(getAdapter(this[OPTIONS]).nodeToElement);
187+
return this.getNodesInternal().map(getAdapter(this[OPTIONS]).nodeToElement);
182188
}
183189

184190
// eslint-disable-next-line class-methods-use-this
@@ -187,6 +193,9 @@ class ShallowWrapper {
187193
}
188194

189195
getNodesInternal() {
196+
if (this[ROOT] === this && this.length === 1) {
197+
this.update();
198+
}
190199
return this[NODES];
191200
}
192201

@@ -227,9 +236,10 @@ class ShallowWrapper {
227236
if (this[ROOT] !== this) {
228237
throw new Error('ShallowWrapper::update() can only be called on the root');
229238
}
230-
this.single('update', () => {
231-
privateSetNodes(this, getRootNode(this[RENDERER].getNode()));
232-
});
239+
if (this.length !== 1) {
240+
throw new Error('ShallowWrapper::update() can only be called when wrapping one node');
241+
}
242+
privateSetNodes(this, getRootNode(this[RENDERER].getNode()));
233243
return this;
234244
}
235245

@@ -795,7 +805,7 @@ class ShallowWrapper {
795805
* @returns {ShallowWrapper}
796806
*/
797807
parents(selector) {
798-
const allParents = this.wrap(this.single('parents', n => parentsOfNode(n, this[ROOT][NODE])));
808+
const allParents = this.wrap(this.single('parents', n => parentsOfNode(n, this.getRootNodeInternal())));
799809
return selector ? allParents.filter(selector) : allParents;
800810
}
801811

@@ -1190,7 +1200,7 @@ if (ITERATOR_SYMBOL) {
11901200
Object.defineProperty(ShallowWrapper.prototype, ITERATOR_SYMBOL, {
11911201
configurable: true,
11921202
value: function iterator() {
1193-
const iter = this[NODES][ITERATOR_SYMBOL]();
1203+
const iter = this.getNodesInternal()[ITERATOR_SYMBOL]();
11941204
const adapter = getAdapter(this[OPTIONS]);
11951205
return {
11961206
next() {

0 commit comments

Comments
 (0)