'ReferenceError: jest is not defined' when running unit test - javascript

I'm in the early stages of a new app that so far just uses vanilla JS. I'm trying to use ES6 modules for my Jest unit tests, so I followed the 2020 updated instructions on making this possible.
However, after following those instructions, I get the error ReferenceError: jest is not defined when running my unit test.
Here's my package.json:
{
"version": "1.0.0",
"main": "app.js",
"type": "module",
"jest": {
"testEnvironment": "jest-environment-node",
"transform": {}
},
"scripts": {
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
"start": "node server.js"
},
"license": "ISC",
"devDependencies": {
"express": "^4.17.1",
"jest": "^26.6.3",
"jest-environment-node": "^26.6.2",
"open": "^7.3.0"
},
"dependencies": {}
}
Below is my test file. The error occurs due to the jest.fn call:
import { getTotalNumPeople } from "./app.js";
test("Get total number of people", async () => {
global.fetch = jest.fn(() => Promise.resolve({
json: () => Promise.resolve({count: 15})
})
)
expect(await getTotalNumPeople()).toBe(15);
});
Any ideas on why this is happening? I'm confident that the issue has to do with the steps I followed to support ES6 modules. Prior to these changes, my test ran fine when I simply pasted the getTotalNumPeople function in my test file.
If I comment out mocking my function, I then get a ReferenceError about fetch not being defined (since getTotalNumPeople uses fetch). So it's not just jest that's not defined.
I notice that if I do not specify jest-environment-node as my test environment, the error changes to ReferenceError: global is not defined due to referring to global.fetch in my test. Just thought I'd note that in case that helps.

It looks like you didn’t import jest, so you have to just add this line to the top of the file:
import {jest} from '#jest/globals'
For more details, see this issue on native support for ES6 modules in Jest.

while essentially the same as the answer of Rupesh - you can expose jest globally without having to import it in each test file - by adding a setup-file to the jest configuration:
"jest": {
"setupFiles": [
"<rootDir>/test-setup.js"
]
}
then add this to test-setup.js:
import { jest } from '#jest/globals';
global.jest = jest;
also in general ESM support for jest is improved by a test script in package.json as so:
"scripts": {
"test": "node --no-warnings --experimental-vm-modules $( [ -f ./node_modules/.bin/jest ] && echo ./node_modules/.bin/jest || which jest )"
},

Related

Mocha and Import Syntax: Cannot find module

Maintainer of multiple npm packages here. Been using mocha with the require syntax and wanting to migrate to the import syntax.
The error I am getting is
Cannot find module '<project>/src/index' imported from <project>/test/index.spec.js
Steps to Reproduce
With the following three files
src/index.js
export const sum = (a, b) => a + b;
test/index.spec.js
import { sum } from '../src/index';
const expect = require('chai').expect;
describe('Testing Index', () => {
it('Testing sum', () => {
expect(sum(7, 13)).to.equal(20);
});
});
package.json
{
"name": "mocha-debug",
"type": "module",
"main": "index.js",
"scripts": {
"test": "mocha \"./test/**/*.spec.js\""
},
"license": "ISC",
"devDependencies": {
"chai": "4.3.4",
"mocha": "9.1.4"
}
}
and using node v14.18.2, run yarn install and
yarn test
> `Cannot find module '<project>/src/index' imported from <project>/test/index.spec.js`
Notes
I've found a related issue that recommends using babel with --require #babel/register, but wasn't able to get over the error.
I've set up a test repo to make it easy to reproduce the issue
https://github.com/simlu/mocha-debug
Question
What am I doing wrong here? How do I get the tests to run successfully?
I solved it by just adding the file extension in my case I was importing my mongodb model so I imported with the file extension .ts
var Employee = require('../models/Employee.ts')
Which solved the issue

Unable to run JEST test

I'm facing an issue when I try to import something using require() function in jest test file.
script2.test.js
const fetch = require('node-fetch');
it('test function', () => {
expect(4).toEqual(4);
});
Package.json
{
"name": "jest-test",
"version": "1.0.0",
"description": "",
"type": "module",
"scripts": {
"test": "jest --watchAll"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/cli": "^7.15.7",
"#babel/core": "^7.15.8",
"#babel/plugin-transform-async-to-generator": "^7.14.5",
"#babel/preset-env": "^7.15.8",
"jest": "^27.3.1"
},
"dependencies": {
"node-fetch": "^3.0.0"
},
"jest": {
"transform": {
"^.+\\.(js|jsx)$": "babel-jest"
}
}
}
babel.config.cjs
module.exports = {presets: ['#babel/preset-env']}
I'm getting following errors when I run the test using npm test
FAIL ./script2.test.js
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
Details:
C:\work\jest-udemy\node_modules\node-fetch\src\index.js:9
import http from 'http';
^^^^^^
SyntaxError: Cannot use import statement outside a module
> 1 | const fetch = require('node-fetch');
| ^
I'm new to JEST, any help is much appreciated.
My Node version is 14.17.3
Thanks you.
It seems that one still needs to jump through the hoops to make jest work with ESM.
In package.json change your script to:
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watchAll"
And in script2.test.js use import:
import fetch from 'node-fetch';
P.S. This was tested with node 14.15.1

how can I use top level "await" in typescript next.js

When I use "await" on top-level like this:
const LuckyDrawInstance=await new web3.eth.Contract(abi)
I got a warning on the terminal: "set experiments.topLevelAwait true". When I tried to add this to "tsconfig.json", it still does not work. it says "experiments" property does not exist.
I could wrap it inside an async function but I want to set it without a wrapped function.
It is nothing to do with the tsconfig.json. You have to set it inside next.config.js. New version of next.js uses webpack5 and webpack5 supports top level await.
module.exports = {
webpack: (config) => {
// this will override the experiments
config.experiments = { ...config.experiments, topLevelAwait: true };
// this will just update topLevelAwait property of config.experiments
// config.experiments.topLevelAwait = true
return config;
},
};
NOTE
You have to use it outside the functional component:
export default function Navbar() {
// this will throw error
// Syntax error: Unexpected reserved word 'await'.
const provider=await customFunction()
return (
<section>
</section>
);
}
Warning
Since it is experimental, it might be broken in some versions
The latest solution as of writing this post that worked for me is using Babel instead of SWC since Next.js does not allow custom SWC configuration, therefore, you cannot allow topLevelAwait through .swcrc file.
Add Babel plugin called #babel/plugin-syntax-top-level-await into your package.json.
eg.
{
"devDependencies": {
"#babel/plugin-syntax-top-level-await": "^7.14.5"
}
}
Create .babelrc file in the root directory of your project where package.json lives.
Inside .babelrc make sure to include next/babel preset and the topLevelAwait plugin.
eg.
{
"presets": ["next/babel"],
"plugins": [
"#babel/plugin-syntax-top-level-await"
]
}
This is the easiest solution until Next.js team allows us to include SWC configuration. Note that by doing this you will not have SWC performance benefit since it will be disabled in favor of Babel.
I have been struggling with this for 2-3 days. Here is a solution that works. Please follow the following steps.
1. Copy paste the following in your package.json
{
"name": "projectname",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "mocha",
"dev": "next dev"
},
"author": "",
"license": "ISC",
"dependencies": {
"#truffle/hdwallet-provider": "^2.0.1",
"fs-extra": "^10.0.0",
"ganache-cli": "^6.12.2",
"mocha": "^9.1.4",
"next": "^12.0.8",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"solc": "^0.8.9",
"web3": "^1.7.0",
"#babel/plugin-syntax-top-level-await": "^7.14.5"
},
"devDependencies": {
"#babel/plugin-syntax-top-level-await": "^7.14.5"
}
}
2. Delete your node_modules folder
3. Goto your project's root directory and reinstall all the packages using npm install command
4. Create a new file in your project's root directory and call it "next.config.js"
5. Copy paste following code in next.config.js file and save.
module.exports = {
// target: 'experimental-serverless-trace',
webpack: (config) => {
config.experiments = config.experiments || {};
config.experiments.topLevelAwait = true;
return config;
},
};

Accessing jasmine with testRunner set to jest-circus results in: ReferenceError: jasmine is not defined

On default jest allows you to simply access jasmine globally. But as soon as you switch the testRunner to jest-circus, jasmine is undefined. Following is a minimal, reproducible example:
babel.config.js
module.exports = {
presets: [["#babel/preset-env", { targets: { node: "current" } }]],
};
jasmine.spec.js
it("check jasmine", () => {
console.log(jasmine);
});
jest.config.js
module.exports = {
rootDir: ".",
testRunner: "jest-circus/runner",
};
package.json
{
"name": "test-jest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest"
},
"author": "",
"license": "ISC",
"dependencies": {
"#babel/core": "^7.12.10",
"#babel/preset-env": "^7.12.11",
"babel-jest": "^26.6.3",
"jest": "^26.6.3",
"jest-circus": "^26.6.3"
}
}
Running this test will cause following output:
$ npm test
> test-jest#1.0.0 test /Users/yusufaran/Projects/test/test-jest
> jest
FAIL ./jasmine.spec.js
✕ check jasmine (1 ms)
● check jasmine
ReferenceError: jasmine is not defined
1 | it("check jasmine", () => {
> 2 | console.log(jasmine);
| ^
3 | });
4 |
at Object.<anonymous> (jasmine.spec.js:2:15)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 1.01 s
Ran all test suites.
npm ERR! Test failed. See above for more details.
If you remove/comment the testRunner line in jest.config.js (so it fallbacks to the default runner) it works as expected.
Question
How can I access global jasmine object with testRunner set to jest-circus/runner? If I can't, why?
You can’t access jasmine when you use jest-circus. This is by design. jest-circus is a new test runner that was built from scratch. It mimics jasmine functionality for defining tests (i.e., describe, it, everything except expect assertions and spies).
If you depend on jasmine, then npm install -D jest-jasmine2 and use it in your jest config:
{
testRunner: 'jest-jasmine2'
}
Just adding testRunner: 'jasmine2' to jest.config.js did the trick for me

Jest testing with ES6 Modules (without babel) [duplicate]

Is it possible to test ES6 Modules with Jest without esm or babel? Since node v13 supports es6 natively have tried:
//package.json
{
…
"type": "module"
…
}
//__tests__/a.js
import Foo from '../src/Foo.js';
$ npx jest
Jest encountered an unexpected token
…
Details:
/home/node/xxx/__tests__/a.js:1
import Foo from '../src/Foo.js';
^^^^^^
SyntaxError: Cannot use import statement outside a module
When babel is added a transpiler, it works, but can es6 modules be used natively as well?
Yes, it is possible from jest#25.4.0. From this version, there is a native support of esm, so you will not have to transpile your code with babel anymore.
It is not documented yet, but according to this issue you have to do 3 easy steps to achieve that (At the time of writing this answer):
Make sure you don't transform away import statements by setting transform: {} in your jest 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 config 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 from package.json as follows (I hope this will change in the future):
"scripts": {
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
}
I hope, this answer was helpful to you.
Note that this is is still experimental, but we have documented how to test this, so there's hopefully less confusion.
https://jestjs.io/docs/en/ecmascript-modules
The steps in https://stackoverflow.com/a/61653104/1850276 are correct
I followed the tips provided in the accepted answer, but I added the property "type": "module" in my package.json in order to jest works properly. This is what I done:
In package.json:
"devDependencies": {
"jest": "^26.1.0",
"jest-environment-jsdom-sixteen": "^1.0.3",
"jest-environment-node": "^26.1.0"
},
"scripts": {
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
},
"type": "module",
"jest": {
"transform": {},
"testEnvironment": "jest-environment-jsdom-sixteen"
}
To run jest from "jest" extension in VSCode with "--experimental-vm-modules" flags, put this config in your global or workspaces settings.json:
"jest.nodeEnv": {
"NODE_OPTIONS": "--experimental-vm-modules"
}
In addition to #Radovan Kuka's answer, here's how to run Jest with ES modules, using npx:
"test:monitoring": "npx --node-arg=--experimental-vm-modules jest -f monitoring.test.js --detectOpenHandles",
The benefit is that one doesn't need to provide the absolute node_modules path.
Without Babel, here's a complete, minimal example that works on recent Jest versions. Run with npm test.
$ tree -I node_modules
.
├── package.json
├── src
│   └── foo.js
└── __tests__
└── foo.spec.js
package.json:
{
"type": "module",
"scripts": {
"test": "NODE_OPTIONS=--experimental-vm-modules jest"
},
"devDependencies": {
"jest": "^29.3.1"
}
}
src/foo.js:
export const bar = () => 42;
__tests__/foo.spec.js:
import {bar} from "../src/foo";
describe("foo.bar()", () => {
it("should return 42", () => {
expect(bar()).toBe(42);
});
});
The secret sauce is in the package.json: "type": "module" and NODE_OPTIONS=--experimental-vm-modules jest.
If you want to add a mock, it's a bit complicated. See this answer.

Categories