Enzyme: Cannot read property 'tag' of null

Created on 27 Aug 2018  路  12Comments  路  Source: enzymejs/enzyme

Describe the bug
Seeing an issue after upgrading to Enzyme 3.5.0 & enzyme-adapter-react-16 1.3.0 and react 16.4.2 on a large number of tests in our test suite.
The errors seem to all relate to new the fibre addition and tags and one example is below:

    TypeError: Cannot read property 'tag' of null

      14 | describe('TextProgressIndicator', () => {
      15 |   describe('Renders as expected - no text content', () => {
    > 16 |     const wrapper = mount(<TextProgressIndicator />);
         |                     ^
      17 |     const div = wrapper.find('div');
      18 |
      19 |     it('does not have any div', () => {

      at detectFiberTags (node_modules/enzyme-adapter-react-16/build/detectFiberTags.js:105:107)
      at ReactSixteenAdapter.createMountRenderer (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:290:56)
      at ReactSixteenAdapter.createRenderer (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:497:25)
      at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:113:30)
      at mount (node_modules/enzyme/build/mount.js:21:10)
      at Suite.<anonymous> (packages/intelligent-evidence-gathering/src/components/__tests__/TextProgressIndicator.test.js:16:21)
      at Suite.describe (packages/intelligent-evidence-gathering/src/components/__tests__/TextProgressIndicator.test.js:15:3)
      at Object.describe (packages/intelligent-evidence-gathering/src/components/__tests__/TextProgressIndicator.test.js:14:1)

The class above as example is extremely simple:

const TextProgressIndicator = ({ content }) => {
  if (!content || content.length === 0) {
    return null;
  }
  return <div className="ieg-form__progress-indicator">{content}</div>;
};
TextProgressIndicator.propTypes = {
  content: PropTypes.string,
};
TextProgressIndicator.defaultProps = {
  content: null,
};
export default TextProgressIndicator;

Rolling back the version of the enzyme-adapter-react-16 to 1.2.0 resolves the tests.

Most helpful comment

Useful guidance that points me to the right direction. I ran into this same error. It turns out that in out jest.config.js we called a script that mocks createPortal.

All 12 comments

Thanks, this is a great bug to catch.

@ronanmulvaney hm, i'm unable to reproduce this. what exactly is line 105 of node_modules/enzyme-adapter-react-16/build/detectFiberTags.js when you get this error? How are you using jsdom, and which version?

@ronanmulvaney also, what version of react-dom are you using? Note that react and react-dom must always match minor versions.

react-dom 16.4.2, have latest Jest (23.5.0) so this is using jsdom 11.12.0 rather than specifying it ourselves.
Line 105 is

      HostPortal: getFiber(_reactDom2['default'].createPortal(null, global.document.createElement('div'))).tag,

And just noticed why - because of https://github.com/facebook/react/issues/11565 we have the advised

ReactDOM.createPortal = node => node;

in our tests setup which is now probably interfering with this addition.

ah that would definitely break it. I'd do delete ReactDOM.createPortal if you want to avoid breaking enzyme; why are you using react-test-renderer directly?

Jest snapshot testing in my case.

Can you use enzyme's .debug() for that?

Debug didn't quite go as deep as I wanted here so ended up incorporating https://github.com/adriantoine/enzyme-to-json to give me something that matched my current snapshots plus gave the Portal support that was lacking.
Thanks for your help/direction on this one.

Useful guidance that points me to the right direction. I ran into this same error. It turns out that in out jest.config.js we called a script that mocks createPortal.

I found the same issue and changed the version to fix.

For those of you who have this error because you're mocking createPortal, I found a workaround if you still need to mock it. You assign the original createPortal implementation to a variable, mock the implementation and run your test, then reassign it to the original implementation after the test. Only downside is you would have to do this for every test where you need it.

    it('Renders correctly', () => {
        const oldPortal = ReactDOM.createPortal;
        ReactDOM.createPortal = node => node; // for components that use Portal
        const component = renderer.create(<Portal>{children}</Portal>);
        const tree = component.toJSON();

        expect(tree).toMatchSnapshot();

        ReactDOM.createPortal = oldPortal;
    });
Was this page helpful?
0 / 5 - 0 ratings

Related issues

blainekasten picture blainekasten  路  3Comments

heikkimu picture heikkimu  路  3Comments

ivanbtrujillo picture ivanbtrujillo  路  3Comments

mattkauffman23 picture mattkauffman23  路  3Comments

rexonms picture rexonms  路  3Comments