Jest: babel7 object destructing fails in test cases

Created on 3 Sep 2018  ยท  13Comments  ยท  Source: facebook/jest

๐Ÿ› Bug Report

I have a react project which I recently migrated to bable7. everything works fine but when I tried to run my test cases it started failing. all of the other issue I was able to resolve except this one.
it seems like object destructuring seems to be failing when running jest

here is my component that fails.

import React from 'react';
import PropTypes from 'prop-types';
import { Input } from 'antd';

const { Search } = Input;  // jest fails here....

class TextBoxWithButton extends React.Component {
  static propTypes = {
    placeholder: PropTypes.string.isRequired,
    onAction: PropTypes.func.isRequired,
    buttonText: PropTypes.string,
  }

  static defaultProps = {
    buttonText: '',
  }

  constructor(props) {
    super(props);
    this.state = {
      value: '',
    };
  }

  onSubmit = (value) => {
    const { onAction } = this.props;
    this.setState({
      value: '',
    });
    onAction(value);
  }

  handleChange = (ev) => {
    this.setState({
      value: ev.target.value,
    });
  }

  render() {
    const { placeholder, buttonText } = this.props;
    const { value } = this.state;
    return (
      <React.Fragment>
        <Search
          placeholder={placeholder}
          onSearch={this.onSubmit}
          enterButton={buttonText}
          value={value}
          onChange={this.handleChange}
        />
      </React.Fragment>

    );
  }
}

export default TextBoxWithButton;

here is my .babelrc

{
  "presets": [
    ["@babel/preset-env", {  "modules": false, "useBuiltIns":"usage"  }],
    "@babel/preset-react"
  ],
  "plugins": [
    "react-hot-loader/babel",
    "@babel/plugin-proposal-object-rest-spread",
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-syntax-dynamic-import",
    ["import", {  "libraryName": "antd", "libraryDirectory": "es", "style": false }],
    [
      "module-resolver",
      {
        "root": [
          "./src"
        ],
        "alias": {
          "App": "./src/App",
          "Common": "./src/App/Common",
          "Elements": "./src/App/Elements",
          "Router": "./src/App/Router",
          "Constants": "./src/Constants",
          "Services": "./src/Services",
          "Store": "./src/Store",
          "Styles": "./src/Styles",
          "Assets": "./src/Assets"
        }
      }
    ]
  ],
  "env": {
    "test": {
      "presets": [
        ["@babel/preset-env"],
        "@babel/preset-react"
      ],
      "plugins": [
        "@babel/plugin-transform-modules-commonjs",
        "@babel/plugin-proposal-object-rest-spread",
        "@babel/plugin-proposal-class-properties",
        "@babel/plugin-syntax-dynamic-import",
        ["import", {  "libraryName": "antd", "style": "css" }]
      ]
    }
  }
}

here is my jest.config.js

const jestConfig = {
  verbose: true,
  moduleNameMapper: {
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/__mocks__/fileMock.js',
    '\\.(css|scss)$': '<rootDir>/__mocks__/styleMock.js',
  },
  transform: {
    '^.+\\.jsx?$': '<rootDir>/node_modules/babel-jest',
    '^.+\\.js?$': '<rootDir>/node_modules/babel-jest',
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/__mocks__/fileMock.js',
  },
  moduleFileExtensions: [
    'js',
    'jsx',
  ],
  unmockedModulePathPatterns: [
    '<rootDir>/node_modules/react/',
    '<rootDir>/node_modules/react-dom/',
  ],
  moduleDirectories: [
    'node_modules',
  ],
  transformIgnorePatterns: [
    '/node_modules/',
  ],
  coveragePathIgnorePatterns: [
    '/node_modules/',
  ],
  modulePathIgnorePatterns: [
    '/node_modules/',
  ],
  collectCoverage: true,
  coverageReporters: [
    'json',
    'lcov',
    'text',
  ],
};

module.exports = jestConfig // eslint-disable-line

here is my package.json

{
  "name": "react-app",
  "version": "1.0.0",
  "main": "index.jsx",
  "license": "MIT",
  "scripts": {
    "start": "npm run start:dev",
    "start:dev": "npm run dev-server --   --mode development --env.NODE_ENV=development --env.PROXY_ORIGIN=http://localhost:3000",
    "start:stage": "npm run dev-server --  --mode development --env.NODE_ENV=development --env.PROXY_ORIGIN=http://localhost:3001",
    "start:dev-min": "npm run start:dev -- --env.MIN_STATS=true",
    "start:analyze-speed": "npm run start:dev -- --env.addons=speedmeasure",
    "build": "npm run test && webpack --optimize-minimize --mode production --env.NODE_ENV=production --env.PUBLIC_PATH=/",
    "build:analyze-bundle": "npm run build -- --env.addons=bundleanalyzer",
    "build:analyze-buddy": "npm run build -- --env.addons=bundlebuddy",
    "dev-server": "webpack-dev-server --inline",
    "test:watch": "npm run test -- --watchAll",
    "test": "export BABEL_ENV=test&&NODE_ENV=test&& jest",
    "profile": "webpack --env.NODE_ENV=production --progress -c --profile --json  > stats.json"
  },
  "description": "this tool will be used to book consultation for clients.",
  "dependencies": {
    "@babel/polyfill": "^7.0.0",
    "antd": "^3.9.0",
    "axios": "^0.18.0",
    "moment": "^2.22.2",
    "prop-types": "^15.6.2",
    "react": "^16.4.2",
    "react-asynchronous-component": "^1.0.2",
    "react-dom": "^16.4.2",
    "react-hot-loader": "^4.3.5",
    "react-redux": "^5.0.7",
    "react-router-dom": "^4.3.1",
    "redux": "^4.0.0",
    "regenerator-runtime": "^0.12.1",
    "redux-saga": "^0.16.0"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.0.0",
    "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
    "@babel/plugin-syntax-dynamic-import": "^7.0.0",
    "@babel/plugin-transform-modules-commonjs": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-react": "^7.0.0",
    "antd-scss-theme-plugin": "^1.0.7",
    "autoprefixer": "^9.1.3",
    "babel-core": "7.0.0-bridge.0",
    "babel-eslint": "^8.2.6",
    "babel-jest": "^23.4.2",
    "babel-loader": "^8.0.0",
    "babel-plugin-import": "^1.8.0",
    "babel-plugin-module-resolver": "^3.1.1",
    "bundle-buddy-webpack-plugin": "^0.3.0",
    "clean-webpack-plugin": "^0.1.19",
    "css-loader": "^1.0.0",
    "cssnano": "^4.1.0",
    "enzyme": "^3.5.0",
    "enzyme-adapter-react-16": "^1.3.1",
    "error-overlay-webpack-plugin": "^0.1.5",
    "eslint": "^5.5.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-import-resolver-babel-module": "^5.0.0-beta.1",
    "eslint-loader": "^2.1.0",
    "eslint-plugin-css-modules": "^2.8.1",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-jsx-a11y": "^6.1.1",
    "eslint-plugin-react": "^7.11.1",
    "extract-text-webpack-plugin": "*",
    "fast-sass-loader": "^1.4.6",
    "file-loader": "^1.1.11",
    "glob": "^7.1.3",
    "hard-source-webpack-plugin": "^0.12.0",
    "html-webpack-plugin": "^3.2.0",
    "jest": "^23.5.0",
    "jest-cli": "^23.5.0",
    "less-loader": "^4.1.0",
    "mini-css-extract-plugin": "^0.4.2",
    "node-sass": "^4.9.3",
    "optimize-css-assets-webpack-plugin": "^5.0.1",
    "postcss-loader": "^3.0.0",
    "purify-css": "^1.2.5",
    "purifycss-webpack": "^0.7.0",
    "sass-loader": "^7.1.0",
    "speed-measure-webpack-plugin": "^1.2.2",
    "style-loader": "^0.22.1",
    "system-bell-webpack-plugin": "*",
    "uglifyjs-webpack-plugin": "^1.3.0",
    "webpack": "^4.17.1",
    "webpack-bundle-analyzer": "^2.13.1",
    "webpack-bundle-tracker": "^0.3.0",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.7",
    "webpack-manifest-plugin": "^2.0.3",
    "webpack-merge": "^4.1.4"
  }
}

here is the jest test runner fail output

 FAIL  src/App/Elements/__tests__/index.spec.js
  โ— Test suite failed to run

    ReferenceError: Input is not defined

      3 | import { Input } from 'antd';
      4 |
    > 5 | const { Search } = Input;
        |                    ^
      6 |
      7 | class TextBoxWithButton extends React.Component {
      8 |   static propTypes = {

      at Object.Input (src/App/Elements/TextBox/TextBoxWithButton/TextBoxWithButton.component.jsx:5:20)
      at Object.<anonymous> (src/App/Elements/index.js:2:1)
      at Object.<anonymous> (src/App/Elements/__tests__/index.spec.js:1:1)

To Reproduce

install bable7
install babel-core = 7.0.0-bridge.0
use object destructring in any component.
and run jest

Expected behavior

jest should be able to use babel-jest and transform es6 and process it.

All 13 comments

Looks like Input is undefined because e.g. antd is mocked by a manual mock (inside __mocks__ dir) or Babel is wrongly configured for test environment.

@thymikee i have not mocked antd anywhere and .babelrc is also added in my post. the strange thing is it was working fine on babel6 . after upgrading to babel7, this issue started after that.

@thymikee i also tried without destructuring and it works..

import React from 'react';
import PropTypes from 'prop-types';
import { Input } from 'antd';

const Search = Input.Search;  // this works fine

Reopening for now, I guess we need to find out better solutions for babel 7, as it currently causes a lot of confusion

The easiest here would be to create reproduction repos we can pull down. While pasting the content of different files is pretty good, doing a quick clone, install, test is way quicker and approachable and we can be sure we haven't missed any detail ๐Ÿ™‚
Babel 7 works fine in my experience, so good reproduction cases for bug reports is essential

@thymikee @SimenB thanks for taking out the time. I found a cause of the problem.
so the issue is when I use babel 7 in my project. and if my test coverage is on. jestwill fail to transform antd components where object destructuring is used. i am not sure if its because of jest or antd. i have my test repo here. for now i have disabled test coverage for my directory where i am using these antd components to make my project work.

steps to reproduce.
go to client folder
go to jest.config.js

coveragePathIgnorePatterns: [
    '<rootDir>/node_modules/',
    '<rootDir>/src/App/Elements/',  // remove this
  ],

then do npm install
hit npm run test to start the jest

Excuse me. Is there any solution now?๐Ÿ˜‚

Jest now uses Babel7 on master (you can try it with jest@beta), so that should not be an issue anymore. @hannadrehman @chenxiaochun can you verify?

Not sure what's going on - babel-plugin-import makes it really hard to follow what's going on. Jest transpiles the code (const { Search } = Input;) to this code:

/* istanbul ignore next */
var _ref = (cov_1hdai2lsp.s[1]++, Input),
    Search = _ref.Search;

While without coverage, the code is:

var Search = _input.default.Search;

Notice the _input.default. I don't know why _input disappears. All collectCoverage does to the transform is add babel-plugin-istanbul, but my guess is that babel-plugin-import does something weird which confuses the istanbul plugin.

https://github.com/facebook/jest/blob/938f1466be978a9f2646e6710646eb6439134ea6/packages/babel-jest/src/index.js#L89-L102

A smaller reproduction would make this more viable to debug - as is, I'd say this is a configuration error. If you're able to extract an example that's just Jest and a minimal babel config (not 50 lines and conditionals), we might be able to put together a reproduction that can be reported to either babel, babel-plugin-istanbul or babel-plugin-import

-    "jest": "^23.1.0",
+    "jest": "^24.0.0-alpha.9",

@thymikee ,The latest version is 24.0.0? I have try it, but it's not ok.

Same with jest 24.8.0

It's might be not jest related.
Removing babel-plugin-import
['import', { libraryName: 'antd', style: 'css' }]
from babel env test configuration resolves the issue.
So it's either babel-plugin-import issue, or babel-plugin-import conflicting with some other plugin.

@artlaman It work for me! thanks ๐Ÿ‘๐Ÿป

Was this page helpful?
0 / 5 - 0 ratings

Related issues

withinboredom picture withinboredom  ยท  3Comments

samzhang111 picture samzhang111  ยท  3Comments

nsand picture nsand  ยท  3Comments

kgowru picture kgowru  ยท  3Comments

paularmstrong picture paularmstrong  ยท  3Comments