jeudi 9 août 2018

Testing React with enzyme and Jest: Invariant Violation: Target container is not a DOM element

I am having an issue setting up enzyme/jest.

It looks like there's something missing in my config. I created the project using create-react-app and later on I installed enzyme. It works well if I use a selector, like a class name, in small components. But now I wanted to add a test for my component, which is the main one in the App, and I am running into this error. I have found people experiencing this issue but no solution that works.

I am pasting here all the details, if anyone has run into this, how have you solved it?

The error says:

 FAIL  src/__tests__/components/App.js
  ● Test suite failed to run

    Invariant Violation: Target container is not a DOM element.

      10 | import './styles/base.scss';
      11 | 
    > 12 | ReactDOM.render(
      13 |     <Provider store={store}>
      14 |         <PersistGate loading={null} persistor={persistor}>
      15 |             <BrowserRouter>

This is the test I am trying to run:

import React from 'react';
import { shallow } from 'enzyme';
import App from '../../';
import Header from '../../components/header';

describe('<App />', () => {

    const wrapped = shallow (<App />);

    it('Should render a Header', () => {
        expect(wrapped.find(Header).length).toBeEqual(1);
    });
});

package.json:

{
  "name": "nasa-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "autoprefixer": "7.1.6",
    "axios": "^0.18.0",
    "babel-core": "6.26.0",
    "babel-eslint": "7.2.3",
    "babel-jest": "20.0.3",
    "babel-loader": "7.1.2",
    "babel-preset-react-app": "^3.1.1",
    "babel-runtime": "6.26.0",
    "better-react-spinkit": "^2.0.4",
    "case-sensitive-paths-webpack-plugin": "2.1.1",
    "chalk": "^1.1.3",
    "classnames": "^2.2.6",
    "css-loader": "0.28.7",
    "dotenv": "4.0.0",
    "dotenv-expand": "4.2.0",
    "eslint": "4.10.0",
    "eslint-config-react-app": "^2.1.0",
    "eslint-loader": "1.9.0",
    "eslint-plugin-flowtype": "2.39.1",
    "eslint-plugin-import": "2.8.0",
    "eslint-plugin-jsx-a11y": "5.1.1",
    "eslint-plugin-react": "7.4.0",
    "extract-text-webpack-plugin": "3.0.2",
    "file-loader": "1.1.5",
    "fs-extra": "3.0.1",
    "html-webpack-plugin": "2.29.0",
    "include-media": "^1.4.9",
    "moment": "^2.22.2",
    "node-sass": "^4.9.2",
    "object-assign": "4.1.1",
    "open-color": "^1.6.3",
    "postcss-flexbugs-fixes": "3.2.0",
    "postcss-loader": "2.0.8",
    "promise": "8.0.1",
    "raf": "3.4.0",
    "react": "^16.4.1",
    "react-bootstrap": "^0.32.1",
    "react-dev-utils": "^5.0.1",
    "react-dom": "^16.4.1",
    "react-icons": "^2.2.7",
    "react-redux": "^5.0.7",
    "react-router": "^4.3.1",
    "react-router-dom": "^4.3.1",
    "react-router-redux": "^4.0.8",
    "redux": "^4.0.0",
    "redux-persist": "^5.10.0",
    "redux-promise": "^0.6.0",
    "resolve": "1.6.0",
    "sass-loader": "^7.0.3",
    "style-loader": "0.19.0",
    "sw-precache-webpack-plugin": "0.11.4",
    "url-loader": "0.6.2",
    "webpack": "3.8.1",
    "webpack-dev-server": "2.9.4",
    "webpack-manifest-plugin": "1.3.2",
    "whatwg-fetch": "2.0.3"
  },
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js --env=jsdom"
  },
  "jest": {
    "presets": [
      "env",
      "react"
    ],
    "collectCoverageFrom": [
      "src/**/*.{js,jsx,mjs}"
    ],
    "setupFiles": [
      "<rootDir>/config/polyfills.js",
      "<rootDir>/config/setupTests.js"
    ],
    "testMatch": [
      "<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}",
      "<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
    ],
    "testEnvironment": "node",
    "testURL": "http://localhost",
    "transform": {
      "^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
      "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
      "^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
    },
    "transformIgnorePatterns": [
      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"
    ],
    "moduleNameMapper": {
      "^react-native$": "react-native-web"
    },
    "moduleFileExtensions": [
      "web.js",
      "js",
      "json",
      "web.jsx",
      "jsx",
      "node",
      "mjs"
    ]
  },
  "babel": {
    "presets": [
      "react-app"
    ]
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "devDependencies": {
    "jest": "^22.1.4",
    "redux-devtools-extension": "^2.13.5",
    "enzyme": "^3.4.1",
    "enzyme-adapter-react-16": "^1.2.0"
  }
}

config/setupTests.json:

  import {
    configure,
  } from 'enzyme';
  
  import Adapter from 'enzyme-adapter-react-16';
  
  configure({
    adapter: new Adapter()
  });

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store, persistor } from './store';
import { PersistGate } from 'redux-persist/integration/react';
import registerServiceWorker from './registerServiceWorker';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

import './styles/base.scss';

ReactDOM.render(
    <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
            <BrowserRouter>
                <App />
            </BrowserRouter>
        </PersistGate>
    </Provider>,
    document.getElementById('root')
);
registerServiceWorker();

App.js

import React, { Fragment } from 'react';
import { Route, Switch } from 'react-router-dom';
import Header from './components/header';
import Home from './components/home';
import { Search, Asset } from './containers';

import styles from './App.scss';
import classNames from 'classnames/bind';

const cx = classNames.bind(styles);

const App = () => (
    <Fragment>
        <Header />
        <div className={ cx('container') }>
            <Switch>
                <Route exact path='/' component={Home}/>
                <Route exact path='/search' component={Search}/>
                <Route path='/asset/:asset' component={Asset}/>
            </Switch>
        </div>
    </Fragment>
);

export default App;

Aucun commentaire:

Enregistrer un commentaire