Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use babel-preset-env with Jest

We are in the midst of updating our API, and Henry Zhu from Babel alerted me to this preset called babel-preset-env to replace need for babel-preset-es2015 and babel-preset-es2018.

Now, I am encountering difficulty understanding the simplest way to handle everything.

  • Our API uses node v8.x and async/await, native promises
  • I want spread operator
  • I want pipeline operator
  • I want import/export syntax
  • I want to support Jest
  • I like how babel-node transpiles the API into memory

This will be easier if I just show you the current position of our config:

.babelrc

 {
   "presets": [
     "env",
       {
         "targets": {
           "node": "current"
         }
       },
     "jest"
   ]
 }

package.json

 {
   "scripts": {
     "test": "node --harmony-async-await node_modules/jest/bin/jest.js",
     "start:local": "NODE_ENV=localhost npm run babel-node -- warpcore/server.js",
     "start": "npm run babel-node -- warpcore/server.js",
     "babel-node": "babel-node --presets=es2015,stage-2"
   },
   "dependencies": {
     "babel-polyfill": "^6.23.0"
   },
   "devDependencies": {
     "babel-cli": "^6.24.1",
     "babel-core": "^6.25.0",
     "babel-eslint": "^7.2.3",
     "babel-jest": "^20.0.3",
     "babel-preset-env": "^1.6.0",
     "babel-preset-es2015": "^6.24.1",
     "babel-preset-es2018": "^1.0.0",
     "babel-preset-stage-2": "^6.24.1",
     "jest": "^20.0.4"
   },
   "jest": {
     "testURL": "http://localhost:8080",
     "testEnvironment": "node"
   }
 }

I am uncertain how these things need to be organized to best achieve my bullet list above.

What changes should I make?

  • I think the babel-node script needs to change
  • I suspect I can remove some of these packages
  • I suspect the .babelrc file isn't optimal
like image 389
agm1984 Avatar asked Dec 14 '22 21:12

agm1984


2 Answers

If you want to use babel-preset-env as a replacement for babel-preset-es2015 (which is deprecated) with Jest, then you have to make sure that the "modules" property in your "env" configuration is set to "commonjs".

Here is an exemplary configuration:

.babelrc

{     
  "env": {
    "test": {
      "plugins": [
        "transform-class-properties",
        "transform-object-rest-spread"
      ],
      "presets": [
        "jest",
        "react",
        [
          "env",
          {
            "debug": false,
            "modules": "commonjs",
            "targets": {
              "node": "current"
            },
            "useBuiltIns": true
          }
        ]
      ]
    }
  }
}

You can see in env.test, that the preset env (which is the "babel-preset-env" configuration) has "modules" set to "commonjs". That's important, otherwise you will get "SyntaxError: Unexpected token import".

For completeness, here is a simple test:

ExampleButton.test.jsx

import ExampleButton from './ExampleButton';
import React from 'react';
import renderer from 'react-test-renderer';

test('Example Test', () => {
  const component = renderer.create(<ExampleButton />);
  const json = component.toJSON();
  expect(json.type).toBe('button');
});

ExampleButton.jsx

import React from 'react';

class ExampleButton extends React.Component {
  render() {
    return (
      <button onClick={this.props.onClick}>
        {this.props.text}
      </button>
    )
  }
}

export default ExampleButton;

For my Babel setup, I have used the following dependencies:

"babel-core": "6.26.0",
"babel-jest": "21.2.0",
"babel-plugin-transform-class-properties": "6.24.1",
"babel-plugin-transform-object-rest-spread": "6.26.0",
"babel-preset-env": "1.6.1",
"babel-preset-react": "6.24.1",
"jest": "21.2.1",
"react-test-renderer": "16.1.1",
like image 173
Benny Neugebauer Avatar answered Dec 21 '22 10:12

Benny Neugebauer


I think I got it working. Here is the solution:

.babelrc

The one posted in the question has a syntax error because the env preset needs to be wrapped in brackets[] (from: http://babeljs.io/docs/plugins/preset-env/)

Correct:

 {
   "presets": [
     ["env",
       {
         "targets": {
           "node": "current"
         }
       }],
     "jest"
   ]
 }

package.json

The one posted in the question has a few things that can be removed:

  {
     "scripts": {
       "test": "jest --verbose",
       "start:local": "cross-env NODE_ENV=localhost babel-node -- app.js",
       "babel-node": "babel-node --presets=env"
    },
    "dependencies": {
      "babel-cli": "^6.24.1",
      "babel-preset-env": "^1.6.0"
    },
    "devDependencies": {
      "babel-eslint": "^7.2.3",
      "babel-jest": "^20.0.3",
      "jest": "^20.0.4"
    },
    "jest": {
      "testURL": "http://localhost:8080",
      "testEnvironment": "node"
    }
  }

Much cleaner in my opinion. You can modulate the presets from the .babelrc file if you want to explicitly include or exclude any, or specify which browsers to support.

like image 42
agm1984 Avatar answered Dec 21 '22 09:12

agm1984