@mapbox/esbuild-jest v1.1.0
@mapbox/esbuild-jest
NOTE: This is a fork of esbuild-jest with some incompatible differences.
Our Jest preset and transformer for compiling files with ESBuild and generating accurate coverage.
š¦ npm install --save-dev @mapbox/esbuild-jest esbuild
esbuild-jest is not an officially supported Mapbox product, and is developed on a best-effort basis. Issues filed from third-party contributors may not be triaged in a timely manner.
Transforms
In your Jest configuration file:
{
"transform": {
"^.+\\.(tsx?|jsx?)$": "@mapbox/esbuild-jest"
}
}
You can also specify ESBuild compatible options like so:
{
"transform": {
"^.+\\.(tsx?|jsx?|css)$": [
"@mapbox/esbuild-jest",
{
"loader": {
".css": "text"
}
}
]
}
}
Preset
If you'd like to follow Mapbox conventions, you can use our Jest preset.
In your Jest configuration file:
{
"preset": "@mapbox/esbuild-jest"
}
In this configuration, .js
, .jsx
, .ts
, and .tsx
files are transformed by ESBuild. .css
files are loaded as plaintext.
Coverage is also enabled with high (80%) thresholds.
Directory structure
Our Jest preset expects files to be laid out in a certain way:
src/
- source files for coverage in this directory.test/
- test files in this directory, with a suffix of either.test
or.spec
.- Example:
index.test.ts
- Example:
How do I use jest.mock()?
@mapbox/esbuild-jest
may require code changes in two ways:
1. Calls to jest.mock()
are not hoisted to the top of the file.
2. ESBuild marks ESM imports as read-only when converting to CommonJS, which is in line with the ECMAScript specification, but breaks certain calls to jest.spyOn
.
There are multiple ways around this.
Option 1
Stub the entire module in a separate file that is ESM imported before other files.
test_utils/myMock.ts
:
jest.mock('../../src/myFile', () => {
})
myFile.test.ts
:
// Important that these are first.
import './test_utils/myMock.ts';
import { myFunction } from '../src/myFile';
// ...
Option 2
Use the following workaround below that "allows" a module to be mocked.
Sourced from: https://github.com/evanw/esbuild/issues/412#issuecomment-723047255
export interface HasSpyOn {
spyOn(): jest.SpyInstance;
}
export function enableSpyOn<T extends Function>(fn: T): T & HasSpyOn {
if ('process' in globalThis && globalThis.process.env.NODE_ENV === 'test') {
let name = fn.name,
obj = { [name]: fn };
(fn as any) = function (this: any) {
return obj[name].apply(this, arguments);
};
(fn as any).spyOn = () => jest.spyOn(obj, name);
}
return fn as any;
}
// file.ts
import { enableSpyOn } from 'helpers/enableSpyOn';
export const fn = enableSpyOn(function fn() {});
// file_test.ts
import { fn } from './file';
let spy = fn.spyOn();
License
esbuild-jest is provided under the terms of the MIT License