Enzyme: "findWhere" by node.text() when mounted causes "Cannot read property 'textContent' of null"

Created on 9 Mar 2018  ·  10Comments  ·  Source: enzymejs/enzyme

Current behavior

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)

Expected behavior

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.

Your environment

Node v8.9.0 on macOS 10.12.6.

API

  • [ ] shallow
  • [x] mount
  • [ ] render

Version

| library | version
| ---------------- | -------
| Enzyme | 3.3.0
| React | 16.2.0

Adapter

  • [x] enzyme-adapter-react-16
  • [ ] enzyme-adapter-react-15
  • [ ] enzyme-adapter-react-15.4
  • [ ] enzyme-adapter-react-14
  • [ ] enzyme-adapter-react-13
  • [ ] enzyme-adapter-react-helper
  • [ ] others ( )
mount bug

Most helpful comment

Opening a PR with failing test cases would be very helpful, even without a fix :-)

Done.

All 10 comments

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.

@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.

Was this page helpful?
0 / 5 - 0 ratings