Jest: Testing browser code using native ES modules

Created on 7 Aug 2016  ยท  15Comments  ยท  Source: facebook/jest

We're in the process of migrating to webpack 2.

As part of this migration, we're moving to use the native ES module support there. This creates an issue when testing with Jest, because Node doesn't support ES modules yet.

Right now, we're addressing this by turning on the CommonJS module transform when NODE_ENV is test, but it might be cleaner if babel-preset-jest included the CommonJS module transform.

Separately, behavior is going to be slightly inconsistent with libraries, as webpack will use the module entry point that should point at an ES module build when available, while Jest will use the main entry point which will not.

Most helpful comment

@oscar-b I just do this:

    "test": {
      "plugins": [
        // Jest runs in Node and needs CommonJS modules. For normal builds,
        // webpack supports ES modules.
        ["transform-es2015-modules-commonjs", { "loose": true }]
      ]
    }

You don't need to re-specify all the existing presets.

@cpojer You want this as a PR to https://facebook.github.io/jest/docs/tutorial-webpack.html? I can add a paragraph there if that's what you mean.

All 15 comments

yeah I think that makes sense. Are you willing to add this to the preset and send a PR? :)

I tried taking a look for a bit but I couldn't figure out whether babel-preset-jest runs before or after user-specified presets.

Unfortunately it would be dangerous to just add the CommonJS module transform to the preset if it runs _before_ user-specified options, as there'd be no way to make sure that a change there doesn't override the user-provided module transform.

Can we just do "passPerPreset: true" and put the babel-preset-jest into the last list and then try to see when they run?

The plugins in the Jest preset run first. I think babel-jest would have to get quite a bit more complicated to properly order the plugins, and that probably doing something like this in user space would be better:

const { buildPreset } = require('babel-preset-es2015');

const { NODE_ENV } = process.env;

module.exports = {
  presets: [
    [buildPreset, {
      loose: true,
      // Jest runs in Node and needs CommonJS modules. For normal builds,
      // webpack supports ES modules.
      modules: NODE_ENV === 'test' ? 'commonjs' : false,
    }],
  ],
};

Sound reasonable?

^- That's what I'm actually doing right now.

In the tutorial we can also just recommend people to add:

{
  "env": {
    "test": [config]
  }
}

that should work fine, right? And people can continue to use babel-jest.

:facepalm:

I got carried away because I was using something like that for a bunch of libraries where the default was "use CommonJS modules" and I wanted to specifically disable CommonJS modules in certain cases.

What you have there is obviously much better.

Let's close this now and update the tutorial for webpack two support when that is actually shipped and ready. Do you wanna work on this?

Just for the sake of finding this issue, I'll add the errors this causes. Obvious now, of course ;)

โ— Runtime Error
  - c:\Dev\example\app\jesttest\__tests__\link.test.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import React from 'react';
                                                                                             ^^^^^^
    SyntaxError: Unexpected token import

My .babelrc now looks like this, and it seems to work as it should:

{
    "presets": [
        ["es2015", {"modules": false}],
        "stage-0",
        "react"
    ],
    "env":{
        "test": {
            "presets": [
                "es2015",
                "stage-0",
                "react"
            ]
        }
    },
}

@oscar-b I just do this:

    "test": {
      "plugins": [
        // Jest runs in Node and needs CommonJS modules. For normal builds,
        // webpack supports ES modules.
        ["transform-es2015-modules-commonjs", { "loose": true }]
      ]
    }

You don't need to re-specify all the existing presets.

@cpojer You want this as a PR to https://facebook.github.io/jest/docs/tutorial-webpack.html? I can add a paragraph there if that's what you mean.

Also, while you are changing your babelrc, I recommend running jest with --no-cache until you are done.

@taion yeah that would be great. Maybe can you add a note to the bottom that talks about webpack two and state it is experimental?

Why not just cache bust using .babelrc contents and Babel version like babel-loader? https://github.com/babel/babel-loader/blob/fca4b92cd09efdaf94b5c422c4f0e1b7bb26997d/index.js#L43-L50

I was under the impression there could be many nested .babelrc files. I guess I could copy https://github.com/babel/babel-loader/blob/fca4b92cd09efdaf94b5c422c4f0e1b7bb26997d/lib/resolve-rc.js into Jest and add it to the cache key? I've been meaning to fix this for a while but was worried about not finding all the babelrc files.

There could be, but they don't stack, so you only need the single .babelrc corresponding to the file in question.

that's good to know :) Thanks! I'll include it in the cache key then.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

stephenlautier picture stephenlautier  ยท  3Comments

rosiakr picture rosiakr  ยท  3Comments

paularmstrong picture paularmstrong  ยท  3Comments

Secretmapper picture Secretmapper  ยท  3Comments

samzhang111 picture samzhang111  ยท  3Comments