15

For a library written in ES6/7, I want to compile (to ES5) the library to a dist/ folder. I also want to run the tests (written in ES6/7) for this lib.

My dev dependencies look like this (package.json):

"devDependencies": {
  "@babel/cli": "^7.4.4",
  "@babel/core": "^7.4.5",
  "@babel/preset-env": "^7.4.5",
  "@babel/register": "^7.4.4",
  "chai": "^4.2.0",
  "mocha": "^6.1.4",
  "sinon": "^7.3.2"
},

My build and test scripts looks like this (package.json):

"scripts": {
  "test": "mocha --require @babel/register",
  "build": "babel src -d dist --presets=@babel/preset-env"
},

Running npm run build works well. The dist/ folder gets populated with transpiled files.

Running npm run test does not seem to work - this is my problem.

> mocha --require @babel/register

/Users/dro/Repos/lib/node_modules/yargs/yargs.js:1163
      else throw err
           ^

ReferenceError: regeneratorRuntime is not defined

Initially I got an import error, which was resolved by adding .babelrc file.

Below is my .babelrc file content.

{
  "presets": ["@babel/preset-env"]
}

I was reading about regeneratorRuntime and it got me to this link about babel-polyfill where they explain I shouldn't need that polyfill.

This will emulate a full ES2015+ environment (no < Stage 4 proposals) and is intended to be used in an application rather than a library/tool.

What is needed to set this up properly?


I am not using webpack.

miphe
  • 1,763
  • 1
  • 20
  • 33
  • [Read this answer to understand Babel, in short](https://stackoverflow.com/a/54017427/104380) – vsync Dec 25 '22 at 08:49

3 Answers3

8

Testing in ES6 with Mocha and Babel 7. Look here: https://dev.to/bnorbertjs/my-nodejs-setup-mocha--chai-babel7-es6-43ei or http://jamesknelson.com/testing-in-es6-with-mocha-and-babel-6/

npm install --save @babel/runtime 
npm install --save-dev @babel/plugin-transform-runtime

And, in .babelrc, add:

{
    "presets": ["@babel/preset-env"],
    "plugins": [
        ["@babel/transform-runtime"]
    ]
}
Umbro
  • 1,984
  • 12
  • 40
  • 99
  • Thanks for those resources - I've gone through James Knelson's article, since it's from 2015, it's no longer applicable. I will look at dev.to now! – miphe Jun 20 '19 at 09:58
  • 2
    the article at dev.to is helpful, but still doesn't solve my issue. They are using Mocha 5, where the `--compiler` option is available. In Mocha 6 we may only use `--require` as stated [here in the compilers deprecation article](https://github.com/mochajs/mocha/wiki/compilers-deprecation#what-should-i-use-instead-then). – miphe Jun 20 '19 at 10:38
  • Read transcript: https://egghead.io/lessons/javascript-how-to-write-a-javascript-library-adding-es6-support-to-tests-using-mocha-and-babel – Umbro Jun 20 '19 at 10:45
  • With Babel 7, the `--compilers` flag is deprecated in favour of `--register`, which I'm using above. I've also updated the question with the error after adding a .babelrc file. I'm tinkering around with the test script and seems this also fails `"mocha --require @babel/register @babel/polyfill` (`Error: No test files found: "@babel/polyfill"`), but the package is installed. – miphe Jun 20 '19 at 11:04
  • v7 migration article was very informative - I didn't find it until now. Your answer works perfectly - thank you! – miphe Jun 20 '19 at 11:50
4

Look at the project documentation:

npm install --save-dev babel-register

In your package.json file make the following changes:

{
  "scripts": {
    "test": "mocha --require babel-register"
  }
}

Some features will require a polyfill:

npm install --save-dev babel-polyfill
{
  "scripts": {
    "test": "mocha --require babel-polyfill --require babel-register"
  }
}
ET-CS
  • 6,334
  • 5
  • 43
  • 73
  • This method works, but the steps copied here are not sufficient. Quote from the project document: Great! You've configured Babel but you haven't made it actually do anything. ... In order to enable the preset you have to define it in your .babelrc file, like this: ```{ "presets": ["@babel/preset-env"] }``` – Zhiyong Aug 21 '20 at 19:47
  • side-note, you want to use `@babel/PAKAGE-NAME` not `babel-PACKAGE-NAME`. e.g. `@babel/register` not `babel-register`. Except for a few where you don't get a clean 1-to-1 mapping like that. babel switched from the `babel-` convention to the `@babel/` convention not too long ago. `babel-` packages are maintained, but only `@babel/` packages are getting updated – acat Mar 16 '22 at 23:45
1

Below steps are for applying Babel transformations & core-js polyfills for your tests file:

All transformations are only done per current environment, so only what is needed to be transpiled/polyfilled, will be. Target environments may be defined from a .browserslist file or as a property in package.json file. (read more here)

Step 1: Install packages:

  1. @babel/core (read why)
  2. @babel/preset-env (read why)
  3. @babel/register (read why)
  4. core-js (read why)

Note that @babel/polyfill exists and uses core-js under the hood. However, it was deprecated in favor of using core-js directly.

Step 2: Create a Babel configuration file babel.config.js

(used to be .babelrc.js or a .json file). Create this file at the root-level of your code.

The most basic configuration (for just testing and not bundling) would look like this:

module.exports = {
  presets: [
    ['@babel/preset-env', { 
      "corejs": "3.26",   
      "useBuiltIns": "usage"
    }],
};

corejs - This is the polyfills library and should be specified with the minor version, otherwise x.0 will be used. It is needed when testing code on rather "old" Node versions, which do not support all of the language methods. This ofc depends on your own usage of such javascript methods. (for example String.prototype.replaceAll).

useBuiltIns - must be set in order for the corejs polyfills to be applied. Read about it in the official docs.

By default, @babel/preset-env will compile your code for the current environment, but you can specify a different environment by setting the "targets" option in the configuration.


Ofc, you can add more presets like @babel/preset-react for example, if your code it written in React, or any other plugins which are specifically needed for your code.

Step 3: Connect mocha to the babel configuration:

In your package.json file

Under the scripts section, simply write something like this:

"test": "mocha \"src/**/*.test.js\""

Create a .mocharc.json file with this content:

{
  "exit": true,
  "color": true,
  "require": ["@babel/register"],
  "ignore": "node_modules"
}

This will apply Babel transformations to all of your test files.

If you need need to apply some special global javascript before/to all of your tests, you can add another file to the require setting, for example, fixtures.cjs:

"require": ["@babel/register", "fixtures.cjs"],

fixtures.cjs:

Below example applies a chai (popular alongside Mocha) plugin for testing DOM-related code:

var chai = require('chai'),
  chaiDOM = require('chai-dom');

// https://stackoverflow.com/questions/62255953/chai-usechaihttp-once-or-in-every-test-file
// https://mochajs.org/#global-teardown-fixtures
exports.mochaGlobalSetup = function () {
    chai.use(chaiDOM);
}


Interesting reads:

vsync
  • 118,978
  • 58
  • 307
  • 400