I would like to write a test that checks if a certain phrase appears anywhere in my rendered component. When I use shallow, I have no issues:
const container = shallow(
<div>
<div>apple</div>
<div>banana</div>
<div>orange</div>
</div>
);
const nodesWithBanana = container.findWhere(node => /banana/.test(node.text()));
console.log(nodesWithBanana.length);
// 3 (outer div, inner div, the text node itself)
However, when I switch to mount instead, the same operation gives me an error that does not make a lot of sense to me:
const container = mount(
<div>
<div>apple</div>
<div>banana</div>
<div>orange</div>
</div>
);
const nodesWithBanana = container.findWhere(node => /banana/.test(node.text()));
// TypeError: Cannot read property 'textContent' of null
Full stacktrace:
TypeError: Cannot read property 'textContent' of null
at ReactWrapper.<anonymous> (/Users/angelika/code/MyApp/node_modules/enzyme/build/ReactWrapper.js:799:43)
at ReactWrapper.single (/Users/angelika/code/MyApp/node_modules/enzyme/build/ReactWrapper.js:1534:25)
at ReactWrapper.text (/Users/angelika/code/MyApp/node_modules/enzyme/build/ReactWrapper.js:798:21)
at /Users/angelika/code/MyApp/source/components/AnnotationComponent.spec.jsx:165:76
at /Users/angelika/code/MyApp/node_modules/enzyme/build/ReactWrapper.js:1409:18
at /Users/angelika/code/MyApp/node_modules/enzyme/build/RSTTraversal.js:75:9
at treeForEach (/Users/angelika/code/MyApp/node_modules/enzyme/build/RSTTraversal.js:65:5)
at /Users/angelika/code/MyApp/node_modules/enzyme/build/RSTTraversal.js:68:12
at Array.forEach (<anonymous>)
at treeForEach (/Users/angelika/code/MyApp/node_modules/enzyme/build/RSTTraversal.js:67:24)
at /Users/angelika/code/MyApp/node_modules/enzyme/build/RSTTraversal.js:68:12
at Array.forEach (<anonymous>)
at treeForEach (/Users/angelika/code/MyApp/node_modules/enzyme/build/RSTTraversal.js:67:24)
at treeFilter (/Users/angelika/code/MyApp/node_modules/enzyme/build/RSTTraversal.js:74:3)
at ReactWrapper.<anonymous> (/Users/angelika/code/MyApp/node_modules/enzyme/build/ReactWrapper.js:63:12)
at /Users/angelika/code/MyApp/node_modules/enzyme/build/ReactWrapper.js:1383:21
at Array.map (<anonymous>)
at ReactWrapper.flatMap (/Users/angelika/code/MyApp/node_modules/enzyme/build/ReactWrapper.js:1382:45)
at findWhereUnwrapped (/Users/angelika/code/MyApp/node_modules/enzyme/build/ReactWrapper.js:62:18)
at ReactWrapper.findWhere (/Users/angelika/code/MyApp/node_modules/enzyme/build/ReactWrapper.js:1408:16)
at Object.<anonymous> (/Users/angelika/code/MyApp/source/components/AnnotationComponent.spec.jsx:165:39)
at Object.asyncFn (/Users/angelika/code/MyApp/node_modules/jest-jasmine2/build/jasmine_async.js:82:37)
at resolve (/Users/angelika/code/MyApp/node_modules/jest-jasmine2/build/queue_runner.js:52:12)
at new Promise (<anonymous>)
at mapper (/Users/angelika/code/MyApp/node_modules/jest-jasmine2/build/queue_runner.js:39:19)
at promise.then (/Users/angelika/code/MyApp/node_modules/jest-jasmine2/build/queue_runner.js:73:82)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
If filtering nodes by their text is truly impossible on a mounted component, I would like to receive a more meaningful message and the official documentation to mention this behavior.
Otherwise, I would expect the output to be identical as when using shallow.
Node v8.9.0 on macOS 10.12.6.
| library | version
| ---------------- | -------
| Enzyme | 3.3.0
| React | 16.2.0
Yep, I have been running into this, and it does feel broken. I use this instead:
const textContent = node => {
try {
// enzyme sometimes blows up on text()
return node.text();
} catch (_e) {
return '';
}
};
Can you use wrapper.text()?
This does seem like a bug, but it might not be one you need to encounter.
Specifically, the bug is here: https://github.com/airbnb/enzyme/blob/master/packages/enzyme/src/ReactWrapper.js#L535 which does not match https://github.com/airbnb/enzyme/blob/master/packages/enzyme/src/ShallowWrapper.js#L650 / https://github.com/airbnb/enzyme/blob/3211a0e6ae2f781ab7e1ef59361e24b67330e09d/packages/enzyme/src/RSTTraversal.js#L116-118
Anyone want to submit a PR with a fix and a test case?
@ljharb Looks like it's not a full fix, because this:
expect(input.findWhere(n => n.text().includes('High risk')).length).toEqual(
0,
);
is throwing with
Method “text” is only meant to be run on a single node. 0 found instead.
at ReactWrapper.single (scripts/third-party/node_modules/enzyme/build/ReactWrapper.js:1536:17)
at ReactWrapper.text (scripts/third-party/node_modules/enzyme/build/ReactWrapper.js:798:21)
Should we relax the single as well?
Although I don't know why findWhere passes empty wrapper, that doesn't make any sense to me.
Opening a PR with failing test cases would be very helpful, even without a fix :-)
@ljharb But actually putting in the fix is easy (at least for the original issue), but getting the test case is hard. Do you know why the node is sometimes null? I don't have the knowledge on enzyme internals to understand when that is happening.
I don't :-/ but presumably if you're hitting the failure, you have a component you could use to replicate it? Even using mount, you could drill down until you found the problem, I'd assume.
Opening a PR with failing test cases would be very helpful, even without a fix :-)
Done.
The PR in question: #1582
Thank you very much - I've commented on the PR with my thoughts, and tl;dr: .text() should not throw when there's no DOM node.
Most helpful comment
Done.