1.1.0 ā€¢ Published 2 years ago

@mapbox/esbuild-jest v1.1.0

Weekly downloads
-
License
MIT
Repository
-
Last release
2 years ago

@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

How do I use jest.mock()?

https://github.com/evanw/esbuild/issues/412

@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