Describe the bug
The following test passes in 3.4.1 but fails in 3.4.2.
class Comp extends Component {
state = {
key: "",
}
componentDidMount() {
this.instanceFunction();
}
instanceFunction = () => this.setState(() => ({ key: "value" }));
render() {
const { key } = this.state;
return null;
}
}
it("should work", () => {
shallow(<Comp />);
});
The error in 3.4.2 is:
FAIL src/test.js
✕ should work (16ms)
● should work
Method “setState” is only meant to be run on a single node. undefined found instead.
11 | }
12 |
> 13 | instanceFunction = () => this.setState(() => ({ key: "value" }));
| ^
14 |
15 | render() {
16 | const { key } = this.state;
at ShallowWrapper.single (node_modules/enzyme/build/ShallowWrapper.js:1718:17)
at ShallowWrapper.setState (node_modules/enzyme/build/ShallowWrapper.js:499:14)
at Comp.ShallowWrapper.instance.setState (node_modules/enzyme/build/ShallowWrapper.js:184:33)
at Comp.setState [as instanceFunction] (src/test.js:13:33)
at Comp.instanceFunction [as componentDidMount] (src/test.js:10:10)
at node_modules/enzyme/build/ShallowWrapper.js:189:20
at Object.batchedUpdates (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:392:22)
at new ShallowWrapper (node_modules/enzyme/build/ShallowWrapper.js:188:24)
at shallow (node_modules/enzyme/build/shallow.js:21:10)
at Object.<anonymous> (src/test.js:22:3)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 2.147s
Ran all test suites matching /src\/test.js/i.
error Command failed with exit code 1.
To Reproduce
Steps to reproduce the behavior:
[email protected]Expected behavior
The test should pass.
Desktop (please complete the following information):
+1
Probably introduced here: https://github.com/airbnb/enzyme/commit/a50570d847fac11dc122c43651107e46ba03de73#diff-fa27c82ee4fde075bae6173848e17c82
+1 yes happening to us too, due to https://github.com/airbnb/enzyme/blob/a50570d847fac11dc122c43651107e46ba03de73/packages/enzyme/src/ShallowWrapper.js#L177-L180 as setState is getting appended to instance.
I think we should avoid addingsetState to instance as then also the code will get executed without appending instance.
+1 got this error this morning aswell.
+1 got this same issue after upgrade to 3.4.2
Any ETA on fixing this or backing out the change? I have a bunch of builds that are failing and would hate to have to go through each of them and pin to a version.
@deedubbu i'm working on it; i hope to have a patch out tonight.
Sorry for the regression. I’m going to write a patch for this.
@koba04 please review #1763
@ljharb Thank you! I'm reviewing it.
Please upgrade to v3.4.3 🙏
I believe this may still be an issue. In my shallow rendered component tests I'm getting:
Method “setState” is only meant to be run on a single node. undefined found instead.
componentDidMount(){
this.setState({ valid: this.props.oldEmail != this.state.email })
}
Resolved by reverting to 3.4.1 for now....
Let me know if I can provide more info :)
@Tinusw Please open a new issue with a test case that reproduces it.
Looks like any change will trigger componentDidMount.
Not sure why, but the 3.4.3 release broke my tests. I receive Error: ShallowWrapper::setState() can only be called on the root errors all over the place.
The relevant test is attached. I was able to figure out that componentDidMount is called twice with the 3.4.3 release, which was not the case before.
it('<MyComponent />', async () => {
fetch.mockResponse(JSON.stringify(jsonData));
const wrapper = shallow(<MyComponent />, { disableLifecycleMethods: true });
await wrapper.instance().componentDidMount();
wrapper.update();
expect(fetch.mock.calls.length).toEqual(1);
expect(wrapper.find(Table).length).toEqual(1);
});
It's very helpful to open a new issue with a test case that reproduces it.
Sorry about that, I'm on it :)
Most helpful comment
+1 yes happening to us too, due to https://github.com/airbnb/enzyme/blob/a50570d847fac11dc122c43651107e46ba03de73/packages/enzyme/src/ShallowWrapper.js#L177-L180 as
setStateis getting appended toinstance.I think we should avoid adding
setStateto instance as then also the code will get executed without appending instance.