Enzyme: webpack/karma: react 16.8.6 causing test failures

Created on 25 Apr 2019  ·  14Comments  ·  Source: enzymejs/enzyme

Current behavior

Tests using mount from enzyme are failing, and we noticed that changing them to use shallow is fine.

Using mount produces the following error:

TypeError: Cannot read property '_reactInternalFiber' of null at getFiber (webpack:///node_modules/enzyme-adapter-react-16/build/detectFiberTags.js:50:0 <- packages/sh-search-2/test/src/index.js:41740:15) at detectFiberTags (webpack:///node_modules/enzyme-adapter-react-16/build/detectFiberTags.js:103:0 <- packages/sh-search-2/test/src/index.js:41793:17) at ReactSixteenAdapter.createMountRenderer (webpack:///node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:404:0 <- packages/sh-search-2/test/src/index.js:41096:56) at ReactSixteenAdapter.createRenderer (webpack:///node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:766:0 <- packages/sh-search-2/test/src/index.js:41458:25) at new ReactWrapper (webpack:///node_modules/enzyme/build/ReactWrapper.js:132:0 <- packages/sh-search-2/test/src/index.js:45064:30) at mount (webpack:///node_modules/enzyme/build/mount.js:21:0

I've tried changing react versions, but anything with 16.8.* causes these kinds of failures. Any help is much appreciated!

Expected behavior

Tests pass using mount.

Your environment

Using react with enzyme

API

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

Version

| library | version
| ------------------- | -------
| enzyme | 3.9.0
| react | 16.8.6
| react-dom | 16.8.6
| react-test-renderer | 16.8.6
| adapter (below) | 1.12.1

Adapter

  • [x] enzyme-adapter-react-16
Need To Reproduce

Most helpful comment

@howdyitshelena @ljharb I'm experiencing this with the following setup as well in my CRA 2.0/storybook setup. I'm at a loss after a day and a half of toying with versions. Only custom webpack config is in ./storybook folder as defined for use in a CRA 2.0 app. Open to any ideas, voodoo, human sacrifice, etc.

$ npm ls react react-dom enzyme enzyme-adapter-react-16 react-test-renderer

[email protected] C:\projects\react-ui-components
+-- @storybook/[email protected]
| +-- @storybook/[email protected]
| | +-- [email protected]  deduped
| | '-- [email protected]
| '-- [email protected]
+-- @storybook/[email protected]
| '-- @storybook/[email protected]
|   '-- @storybook/[email protected]
|     +-- [email protected]  deduped
|     '-- [email protected]  deduped
+-- [email protected]
+-- [email protected]
| '-- [email protected]  deduped
'-- [email protected]

src/setupTests.js

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

any.test.tsx

import React from 'react';
import { mount } from 'enzyme';

 it(`Works', () => {
    const wrapper=  mount(
      <div>_reactInternalFiber error occurs here</div>
    );
  });

yarn test

 FAIL  src/Filter/Filterable.test.tsx (7.292s)
  ● <Filterable /> › Displays correct number of unfiltered data items

    TypeError: Cannot read property '_reactInternalFiber' of null

      32 | 
      33 |   it('Displays correct number of unfiltered data items', () => {
    > 34 |     const wrapper = mount(<div>_reactInternalFiber error occurs here</div>);
         |                     ^
      35 |     expect(wrapper.find('div')).toHaveLength(1);
      36 |     // const wrapper = mount(
      37 |     //   <Filterable<string> data={data}>

      at _reactInternalFiber (node_modules/enzyme-adapter-react-16/src/detectFiberTags.js:14:15)
      at getFiber (node_modules/enzyme-adapter-react-16/src/detectFiberTags.js:45:15)
      at ReactSixteenAdapter.createMountRenderer (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:356:19)
      at ReactSixteenAdapter.createMountRenderer [as createRenderer] (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:632:51)
      at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:132:30)
      at mount (node_modules/enzyme/build/mount.js:21:10)
      at Object.it (src/Filter/Filterable.test.tsx:34:21)

All 14 comments

hmm, I can't reproduce this locally. Are you bundling enzyme with webpack?

@ljharb we are using webpack, and enzyme's a devDependency. We're using lerna for our monorepo, and something I've noticed is that tests will pass for individual packages, but once I run it for the entire monorepo, the tests that use mount will fail. Thanks for the fast feedback!

right, but the stack trace suggests you're bundling enzyme itself. Are you bundling your tests?

@ljharb yes we are - I see, is that the issue?

It's surprising; typically tests run in node :-) but the implication is that you might have some webpack config messing with things. What's your webpack config look like?

@ljharb thank you so much for helping out with this! Really appreciate it! We have our base webpack config, and then for tests, we extend/modify the base. Also realized our webpack and karma which we use to run tests, are all quite old, so I'm going to update those and see if we get any luck :)

Base:

let path = require('path');
let webpack = require('webpack');

module.exports = {
  devtool: 'inline-source-map',
  devServer: {
    https: true,
    port: 443,
    hot: true,
    host: 'localhost.intuit.com',
    overlay: true,
    watchContentBase: true,
  },
  output: {
    path: path.join(__dirname, '/'),
    filename: 'example.js',
    libraryTarget: 'umd',
    chunkFilename: '[name].bundle.js',
    publicPath: '/examples/',
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.(png|jpg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              name: 'images/[name].[ext]',
              limit: 10000,
            },
          },
        ],
      },
      {
        test: /\.svg$/,
        use: [{ loader: 'babel-loader' }, { loader: 'svg-react-loader' }],
      },
      /*

      test: /\.yml$/
      yaml-loader -> json-loader

      */

      {
        test: /\.yml$/,
        use: [{ loader: 'json-loader' }, { loader: 'yaml-loader' }],
      },
      /*

      test: /\.pcss$/
      postcss-loader -> css-loader -> style-loader

      */
      {
        test: /\.pcss$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              localIdentName: 'sh-[local]-[hash:base64:5]',
              modules: true,
            },
          },
          {
            loader: 'postcss-loader',
          },
        ],
      },
      /*

      test: /\.css$/
      css-loader -> style-loader

      NOTES: When sharing the same identName with the pcss loader, lemon reset / style loader ran into load precedence issues for unkown reasons.
             This issue is currently resolved by the unique -ext- prefix in localIdentName, but this may require a unique loader in the future.
      */
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              localIdentName: 'sh-ext-[local]-[hash:base64:5]',
              modules: true,
            },
          },
        ],
      },
      {
        test: /\.js$/,
        use: [{ loader: 'babel-loader' }],
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [new webpack.HotModuleReplacementPlugin()],
};

Test config:

import Config from 'webpack-config';
import webpack from 'webpack';
import path from 'path';

const webpack_path = path.join(__dirname, '/webpack.config.babel.js');
const entry = process.env.entry;

export default new Config()
  .extend({
    [webpack_path]: config => {
      delete config.entry;
      delete config.externals;
      delete config.plugins;
      delete config.devServer;
      return config;
    },
  })
  .merge({
    entry: entry ? entry : './index.js',
    plugins: [
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: JSON.stringify('test'),
        },
      }),
    ],
  });

welp upgrading those packages didn't seem to help haha but will just keep poking at it. Thanks again @ljharb :D

np - nothing seems to be jumping out at me.

@howdyitshelena @ljharb I'm experiencing this with the following setup as well in my CRA 2.0/storybook setup. I'm at a loss after a day and a half of toying with versions. Only custom webpack config is in ./storybook folder as defined for use in a CRA 2.0 app. Open to any ideas, voodoo, human sacrifice, etc.

$ npm ls react react-dom enzyme enzyme-adapter-react-16 react-test-renderer

[email protected] C:\projects\react-ui-components
+-- @storybook/[email protected]
| +-- @storybook/[email protected]
| | +-- [email protected]  deduped
| | '-- [email protected]
| '-- [email protected]
+-- @storybook/[email protected]
| '-- @storybook/[email protected]
|   '-- @storybook/[email protected]
|     +-- [email protected]  deduped
|     '-- [email protected]  deduped
+-- [email protected]
+-- [email protected]
| '-- [email protected]  deduped
'-- [email protected]

src/setupTests.js

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

any.test.tsx

import React from 'react';
import { mount } from 'enzyme';

 it(`Works', () => {
    const wrapper=  mount(
      <div>_reactInternalFiber error occurs here</div>
    );
  });

yarn test

 FAIL  src/Filter/Filterable.test.tsx (7.292s)
  ● <Filterable /> › Displays correct number of unfiltered data items

    TypeError: Cannot read property '_reactInternalFiber' of null

      32 | 
      33 |   it('Displays correct number of unfiltered data items', () => {
    > 34 |     const wrapper = mount(<div>_reactInternalFiber error occurs here</div>);
         |                     ^
      35 |     expect(wrapper.find('div')).toHaveLength(1);
      36 |     // const wrapper = mount(
      37 |     //   <Filterable<string> data={data}>

      at _reactInternalFiber (node_modules/enzyme-adapter-react-16/src/detectFiberTags.js:14:15)
      at getFiber (node_modules/enzyme-adapter-react-16/src/detectFiberTags.js:45:15)
      at ReactSixteenAdapter.createMountRenderer (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:356:19)
      at ReactSixteenAdapter.createMountRenderer [as createRenderer] (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:632:51)
      at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:132:30)
      at mount (node_modules/enzyme/build/mount.js:21:10)
      at Object.it (src/Filter/Filterable.test.tsx:34:21)

Maybe you mocked react-dom?
and you need to delete this:
jest.mock('react-dom');

@binaryjunkie are you running enzyme within storybook?

@adolfius47 This was my problem. You're a little hero in my book.

Yes. Some latent nonsense from trying to get other things to play right, I'm sure. Who's mocking whom now? :) Thank you for your help!

Seems likely this is caused by broken mocks.

Closing for now, but happy to reopen if it can be reproduced.

Was this page helpful?
0 / 5 - 0 ratings