Does Jest support ES6 import/export? - ecmascript-6

If I use import/export from ES6 then all my Jest tests fail with error:
Unexpected reserved word
I convert my object under test to use old school IIFE syntax and suddenly my tests pass. Or, take an even simpler test case:
var Validation = require('../src/components/validation/validation'); // PASS
//import * as Validation from '../src/components/validation/validation' // FAIL
Same error. Obviously there's a problem with import/export here. It's not practical for me to rewrite my code using ES5 syntax just to make my test framework happy.
I have babel-jest. I tried various suggestions from GitHub issues. It is no go so far.
File package.json
"scripts": {
"start": "webpack-dev-server",
"test": "jest"
},
"jest": {
"testPathDirs": [
"__tests__"
],
"testPathIgnorePatterns": [
"/node_modules/"
],
"testFileExtensions": ["es6", "js"],
"moduleFileExtensions": ["js", "json", "es6"]
},
File babelrc
{
"presets": ["es2015", "react"],
"plugins": ["transform-decorators-legacy"]
}
Is there a fix for this?

From my answer to another question, this can be simpler:
The only requirement is to configure your test environment to Babel, and add the ECMAScript 6 transform plugin:
Step 1:
Add your test environment to .babelrc in the root of your project:
{
"env": {
"test": {
"plugins": ["#babel/plugin-transform-modules-commonjs"]
}
}
}
Step 2:
Install the ECMAScript 6 transform plugin:
npm install --save-dev #babel/plugin-transform-modules-commonjs
And that's it. Jest will enable compilation from ECMAScript modules to CommonJS automatically, without having to inform additional options to your jest property inside package.json.

UPDATE 2020 - native support of ECMAScript modules (ESM)
According to this issue, there is native support of ESM from jest#25.4.0. So you won't have to use babel anymore. At the time of writing this answer (05/2020), to activate that you need to do three simple things:
Make sure you don't transform away import statements by setting transform: {} in config file
Run node#^12.16.0 || >=13.2.0 with --experimental-vm-modules flag
Run your test with jest-environment-node or jest-environment-jsdom-sixteen.
So your Jest configuration file should contain at least this:
export default {
testEnvironment: 'jest-environment-node',
transform: {}
...
};
And to set --experimental-vm-modules flag, you will have to run Jest as follows:
node --experimental-vm-modules node_modules/jest/bin/jest.js
Also note in the Github issue that this approach does not yet support the jest object. So you may need to import it manually:
import {jest} from '#jest/globals'
(I hope this will change in the future)

For an updated configuration, I'm using https://babeljs.io/setup#installation
Select JEST and be happy:
As a reference, the current configuration:
npm install --save-dev babel-jest
In your package.json file, make the following changes:
{
"scripts": {
"test": "jest"
},
"jest": {
"transform": {
"^.+\\.jsx?$": "babel-jest"
}
}
}
Install babel preset:
npm install #babel/preset-env --save-dev
Create a .babelrc file:
{
"presets": ["#babel/preset-env"]
}
Run your tests:
npm run test

In package.json, kindly set like this one: "test": "node --experimental-vm-modules node_modules/.bin/jest"
Should be good!

It's a matter of adding stage-0 to your .babelrc file. Here is an example:
{
"presets": ["es2015", "react", "stage-0"],
"plugins": ["transform-decorators-legacy"]
}

I encountered the same issue.
These are what I did:
yarn add --dev babel-jest #babel/core #babel/preset-env
Make file jest.config.js in rootDir.
module.exports = {
moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "json"],
transform: {
'^.+\\.(js|jsx)?$': 'babel-jest'
},
testEnvironment: 'node',
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/$1'
},
testMatch: [
'<rootDir>/**/*.test.(js|jsx|ts|tsx)', '<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
],
transformIgnorePatterns: ['<rootDir>/node_modules/']
};
Then make file babal.config.js in rootDir.
Go like this:
module.exports = {
"presets": ["#babel/preset-env"]
}

Below is how I setup jest, typescript and ES Modules for my project.
jest.config.js
/**
* #type {import('ts-jest/dist/types').InitialOptionsTsJest}
* To configure ESM support, see: https://kulshekhar.github.io/ts-jest/docs/guides/esm-support
*
**/
export default {
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
extensionsToTreatAsEsm: ['.ts'],
globals: {
'ts-jest': {
useESM: true
}
},
setupFiles: ['<rootDir>/__tests__/setup.ts'],
};
tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"outDir": "./dist",
"moduleResolution": "node",
// "strict": true,
"esModuleInterop": true,
"inlineSourceMap": true,
}
}
package.json scripts and devDependencies
"scripts": {
"start": "node ./dist/server.js",
"dev": "tsc-watch --onSuccess \"node ./dist/server.js\"",
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
},
"devDependencies": {
"#jest/globals": "^27.4.4",
"#types/express": "^4.17.13",
"#types/jest": "^27.4.0",
"#types/supertest": "^2.0.11",
"cross-env": "^7.0.3",
"supertest": "^6.2.1",
"ts-jest": "^27.1.3"
}
__tests__/setup.ts
import dotenv from 'dotenv';
dotenv.config({
path: './.env.test'
});

all is explained in the jest docs: jest docs
1.
npm install --save-dev babel-jest #babel/core #babel/preset-env
in file: babel.config.js
module.exports = {
presets: [['#babel/preset-env', {targets: {node: 'current'}}]],
};

In addition to installing babel-jest (which comes with Jest by default now) be sure to install regenerator-runtime.

To add support for React and react-testing-library it may be useful to eject CreateReactApp and take all needed Jest configuration from the package.json. It is ready to use with another bundler, Rollup in my case.

Related

gulp-eslint Environment key "es2021" is unknown

I have a project with the following dependencies;
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"browser-sync": "^2.26.13",
"del": "^6.0.0",
"eslint": "^7.16.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"gulp": "^4.0.2",
"gulp-cssmin": "^0.2.0",
"gulp-eslint": "^6.0.0",
"gulp-htmllint": "0.0.19",
"gulp-htmlmin": "^5.0.1",
"gulp-imagemin": "^7.1.0",
"gulp-jsmin": "^0.1.5"
When I try to run a gulp task that lints javascript, using eslint/gulp-eslint;
function javascript() {
return src('private/script/**')
//.pipe(jsmin())
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError())
.pipe(dest('public/script'));
}
I get the following error;
Error: .eslintrc.json » eslint-config-standard:
Environment key "es2021" is unknown
I used npx eslint --init to generate the following configuration file;
{
"env": {
"browser": true,
"commonjs": true,
"es6": true
},
"extends": [
"standard"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
}
}
i have done an npm install, to make sure I have the latest version of the dependencies. I have also read on guthub that the error might have something to do with gulp-eslint as it is an old version and might not be using the current version of eslint, however, in I have changed gulp-eslint package.json to use the latest version of eslint and no luck. I also updated node/npm to their latest lts versions.
I fixed this by deleting the eslint folder in the node_modules folder for gulp-eslint. this forces node to use the version you have as a dependency rather than the version the project maintainer wants to use.
it appears this is a known issue.
I solve it by upgrading eslint version to version 7
This is what my package json looks like
The problem is that gulp-eslint works with ESLint 6 under the hub, and ESLint 6 does not support the es2021 environment (see the supported environments of ESLint 6).
I'm going to show three options to handle this. The best solution will depend on your setup and requirements.
Method 1: Replace es2021 with an equivalent definition
The es2021 environment is the same as es2020 with the addition of the globals AggregateError, FinalizationRegistry and WeakRef (see the definition of es2021), so you could enter these settings in your .eslintrc configuration file instead to obtain the same result.
{
...
"env": {
...
"es2020": true
},
...
"globals": {
...
"AggregateError": "readonly",
"FinalizationRegistry": "readonly",
"WeakRef": "readonly"
},
...
}
Method 2: Force gulp-eslint to use ESLint 7
If you are using npm >= 8.3 < 9.0 (check this with npm -v), you can override the version of ESLint used by gulp-eslint.
To do so, first add an override entry to your package.json file like this:
{
...
"overrides": {
"gulp-eslint": {
"eslint": "7"
}
},
...
}
then run:
npm install
Now, gulp-eslint will work with the latest version of ESLint 7 which does recognize the es2021 environment (it exists in ESLint >= 7.8).
Note that gulp-eslint does still not support ESLint 7, so some things may not work as expected. Particularly, some plugins may fail to load or produce runtime errors.
Method 3: Use gulp-eslint-new
gulp-eslint-new works with ESLint 8 and can be used in most situations as a drop-in replacement for gulp-eslint, provided that the configuration is compatible with both versions.
Uninstall gulp-eslint with
npm uninstall gulp-eslint
Install gulp-eslint-new with
npm install -D gulp-eslint-new
In your gulpfile, replace the import of gulp-eslint with gulp-eslint-new.
DISCLAIMER: I am currently the only maintainer of gulp-eslint-new.

Cannot read property 'runCLI' of undefined in gulp-jest

I am trying to run jest tests with gulp using gulp-jest.
Installed these packages from npm:
"gulp-jest": "^4.0.3",
"jest-cli": "^25.3.0"
and provided the following configuration to jest:
"jest": {
"setupFilesAfterEnv": [
"<rootDir>/jest.setup.js"
],
"collectCoverage": true,
"coverageDirectory": "./test/unit-test-coverage",
"coverageReporters": [
"text",
"lcov"
]
}
I have written a basic method in my gulpfile.js, referred this link:
function runJsTests() {
process.env.NODE_ENV = 'test';
const __dirname = "Features/Components";
return gulp.src(__dirname).pipe(jest({
}));
}
However, I am getting the following error when I run the gulp task:
TypeError: Cannot read property 'runCLI' of undefined
I had the same trouble last friday, to resolve it, I finally had to downgrade version used of jest-cli :
"#types/jest": "24.9.0",
"jest": "24.9.0",
"ts-jest": "24.3.0
"jest-cli": "24.9.0",
"jest-html-reporter": "2.5.0",
A bug known on new version of Jest-cli
-> think to remove all node_modules and package_lock.json!
Good luck ;)

"SyntaxError: Unexpected token export" using Jest with babel 7+

I'm trying to cover basic reducer with a test but it throws the error for export in my constants file:
FAIL jest/spec/reducers/RootReducer.spec.js
● Test suite failed to run
Jest encountered an unexpected token
Details:
project-root\js\src\constants\ActionTypes.js:2
export const LOCALE_REQUEST = 'ROOT/LOCALE_REQUEST';
^^^^^^
SyntaxError: Unexpected token export
1 | 'use strict';
2 |
> 3 | import { LOCALE_REQUEST_SUCCESS, ROUTING_REQUEST_SUCCESS } from '/js/src/constants/ActionTypes';
| ^
4 |
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17)
at Object.<anonymous> (jest/spec/reducers/RootReducer.spec.js:3:1)
I'm running the tests from 'project-root\tests' folder
The js files that I want to test are located in 'project-root\js' folder
I believe this is the reason for the bug. Because the file I'm trying to import is outside of the tests folder it looks like it's not being transpiled
this is my package.json:
{
"name": "jest",
"version": "0.0.0",
"scripts": {
"test": "jest"
},
"devDependencies": {
"#babel/core": "^7.2.2",
"#babel/plugin-transform-modules-commonjs": "^7.2.0",
"#babel/preset-env": "^7.2.3",
"babel-core": "7.0.0-bridge.0",
"jest": "^23.6.0"
}
}
this is .babelrc:
{
"presets": [
"#babel/preset-env"
],
"plugins": [
"#babel/plugin-transform-modules-commonjs"
]
}
this is jest.config.js:
module.exports = {
verbose: true,
transform: {
"^.+\\.jsx?$": "babel-jest"
},
bail: true,
browser: true,
cacheDirectory: '/tmp/jest',
collectCoverage: false,
roots: [
'<rootDir>/../js',
'<rootDir>/jest'
],
moduleNameMapper: {
'^(.*)/js/(.*)$': '<rootDir>/../js/$2'
},
testRegex: '(jest/spec/.*|(\\.|/)(test|spec))\\.js$',
testPathIgnorePatterns: [
'<rootDir>/node_modules'
],
transformIgnorePatterns: [
'/node_modules/'
]
};
So I've tried to look for similar cases around the web but in most cases the problems come from /node_modules or something missing in the jest config. But I can't find what's wrong in my case, would really appreciate any hints what can I try
up: someone suggested that I need to add babel-jest to my package.json but it's already in /node_modules - it is added with jest package
The problem surrounds the fact that you have no babel-loader setup so the project will blow up on import and export commands that do not get removed from the source code during compilation as babel has no idea how to handle that without babel-loader installed and configured.
For a quick example of how to get started with ES6 transpiling and module loading you can check out this example.
youtube.com/watch?v=X5wTsHRsbIA

Custom local npm module as dependency

I created a project using npm scripts in order to avoid the use of gulp. The thing is, my project has two scripts:
prepare.sh (uses wget to download some files and do mkdirs)
process.js (transform a json file into another overriding some keys)
package.json
{
"scripts": {
"process": "./process.js",
"prepare": "./prepare.sh $npm_package_config_source $npm_config_env",
"config": "npm run prepare && npm run process"
},
"config": {
"source": "https://myurl"
},
"devDependencies": {
"fs": "0.0.1-security",
"json-override": "^0.2.0"
}
}
So, if I want to apply the transform in this project I run npm run config, but I want this project to be part of another as a local module of a front-end project.
How can I set up my project? And when I add it as a dependency of my front project, how can I call the config script from the package.json of the front project?
You can add a bin object to your package.json which will result in files installed into the node_modules/.bin folder docs.npmjs.com/files/package.json#bin
example
{
"bin": {
"process": "./process.js",
"prepare": "./prepare.sh"
},
"scripts": {
"config": "prepare && process"
},
"devDependencies": {
"fs": "0.0.1-security",
"json-override": "^0.2.0"
}
}
Also since npm runs scripts with node_modules/.bin as part of the path you can simply call them by name only. Just remember to add #!/usr/bin/env node to the top of process.js

Gulp doesn't work on Ubuntu 16.04 [duplicate]

As shown in the screen shot below I am not able to run gulp to concat the JavaScript files. Its saying that gulp is not defined.
I have tried the following commands:
npm install -g gulp
npm install gulp
npm install gulp --save-dev
I have also set the environment variables as following:
C:\Users\<user>\AppData\Roaming\npm;C:\Python27;C:\Users\<user>\AppData\Roaming\npm\node_modules;C:\Users\<user>\AppData\Roaming\npm\node_modules\gulp;
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
//script paths
var jsFiles = 'scripts/*.js',
jsDest = 'dist/scripts';
gulp.task('scripts', function() {
return gulp.src(jsFiles)
.pipe(concat('scripts.js'))
.pipe(gulp.dest(jsDest));
});
you just need to install and require gulp locally, you probably only installed it globally
At the command line
cd <project-root> && npm install --save-dev gulp
In your gulpfile.js
var gulp = require('gulp');
this is a different dependency than the command line dependency (that you installed globally). More specifically, it is the same NPM package, but the command line program will execute code usually from a different entry point in the NPM package then what require('X') will return.
If we go to the package.json file in the Gulp project on Github, it will tell the whole story:
{
"name": "gulp",
"description": "The streaming build system",
"version": "3.9.1",
"homepage": "http://gulpjs.com",
"repository": "gulpjs/gulp",
"author": "Fractal <contact#wearefractal.com> (http://wearefractal.com/)",
"tags": [ ],
"files": [
// ...
],
"bin": {
"gulp": "./bin/gulp.js"
},
"man": "gulp.1",
"dependencies": {
// ...
},
"devDependencies": {
// ...
},
"scripts": {
"prepublish": "marked-man --name gulp docs/CLI.md > gulp.1",
"lint": "eslint . && jscs *.js bin/ lib/ test/",
"pretest": "npm run lint",
},
"engines": {
"node": ">= 0.9"
},
"license": "MIT"
}
so at the command line:
$ gulp default
will execute this:
"bin": {
"gulp": "./bin/gulp.js"
},
on the other hand, require('gulp') in your code will return the value of this:
https://github.com/gulpjs/gulp/blob/master/index.js
normally we see this in a package.json file as:
"main": "index.js"
but since this is the default, they just omitted it (which is dumb IMO, better to be explicit, but they aren't the first project I have seen take the lame shorthand route.).
Its occurs on Windows and usually one of the following fixes it:
If you didn't, run npm install gulp on the project folder, even if
you have gulp installed globally.
Normally, It isn't a problem on Windows, but it could be a issue with
the PATH. The package will try to get the PATH from the environment,
but you can override it by adding exec_args to your gulp settings.
For example, on Ubuntu:
"exec_args": {
"path": "/bin:/usr/bin:/usr/local/bin"
}
Hope It will be OK.
Source: https://github.com/NicoSantangelo/sublime-gulp/issues/12