Skip to content

Commit

Permalink
feat(babel-jest): add option excludeJestPreset (#15164)
Browse files Browse the repository at this point in the history
  • Loading branch information
latin-1 committed Jul 5, 2024
1 parent 5c59f73 commit 1775865
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Features

- `[babel-jest]` Add option `excludeJestPreset` to allow opting out of `babel-preset-jest` ([#15164](https://github.com/jestjs/jest/pull/15164))
- `[jest-circus, jest-cli, jest-config]` Add `waitNextEventLoopTurnForUnhandledRejectionEvents` flag to minimise performance impact of correct detection of unhandled promise rejections introduced in [#14315](https://github.com/jestjs/jest/pull/14315) ([#14681](https://github.com/jestjs/jest/pull/14681))
- `[jest-circus]` Add a `waitBeforeRetry` option to `jest.retryTimes` ([#14738](https://github.com/jestjs/jest/pull/14738))
- `[jest-circus]` Add a `retryImmediately` option to `jest.retryTimes` ([#14696](https://github.com/jestjs/jest/pull/14696))
Expand Down
12 changes: 12 additions & 0 deletions docs/CodeTransformation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ Jest will cache the result of a transformation and attempt to invalidate that re

Jest ships with one transformer out of the box – [`babel-jest`](https://github.com/jestjs/jest/tree/main/packages/babel-jest#setup). It will load your project's Babel configuration and transform any file matching the `/\.[jt]sx?$/` RegExp (in other words, any `.js`, `.jsx`, `.ts` or `.tsx` file). In addition, `babel-jest` will inject the Babel plugin necessary for mock hoisting talked about in [ES Module mocking](ManualMocks.md#using-with-es-module-imports).

:::note

By default, `babel-jest` includes `babel-preset-jest`. You can disable this behavior by specifying `excludeJestPreset: true` to `babel-jest`. Note that this will also stop hoisting `jest.mock`, which may break your tests.

```json
"transform": {
"\\.[jt]sx?$": ["babel-jest", { "excludeJestPreset": true }],
}
```

:::

:::tip

Remember to include the default `babel-jest` transformer explicitly, if you wish to use it alongside with additional code preprocessors:
Expand Down
8 changes: 8 additions & 0 deletions packages/babel-jest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,11 @@ You can also pass further [babel options](https://babeljs.io/docs/options)
"\\.[jt]sx?$": ["babel-jest", { "extends": "./babel.config.js", "plugins": ["babel-plugin-transform-import-meta"] }]
},
```

By default, `babel-jest` includes `babel-preset-jest`. In addition to the babel options, we introduce a new option, `excludeJestPreset`, which allows you to disable this behavior. Note that this will break `jest.mock` hoisting.

```json
"transform": {
"\\.[jt]sx?$": ["babel-jest", { "excludeJestPreset": true }],
}
```
31 changes: 31 additions & 0 deletions packages/babel-jest/src/__tests__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,34 @@ test('can pass null to createTransformer', async () => {
}),
);
});

test('include babel-preset-jest by default', () => {
defaultBabelJestTransformer.process(sourceString, 'dummy_path.js', {
cacheFS: new Map<string, string>(),
config: makeProjectConfig(),
configString: JSON.stringify(makeProjectConfig()),
instrument: false,
transformerConfig: {},
} as TransformOptions<BabelTransformOptions>);

expect(loadPartialConfig).toHaveBeenCalledTimes(1);
expect(loadPartialConfig).toHaveBeenCalledWith(
expect.objectContaining({presets: [require.resolve('babel-preset-jest')]}),
);
});

test('can opting out of babel-preset-jest by passing excludeJestPreset: true', async () => {
const transformer = await createTransformer({excludeJestPreset: true});
transformer.process(sourceString, 'dummy_path.js', {
cacheFS: new Map<string, string>(),
config: makeProjectConfig(),
configString: JSON.stringify(makeProjectConfig()),
instrument: false,
transformerConfig: {},
} as TransformOptions<BabelTransformOptions>);

expect(loadPartialConfig).toHaveBeenCalledTimes(1);
expect(loadPartialConfig).toHaveBeenCalledWith(
expect.objectContaining({presets: []}),
);
});
41 changes: 24 additions & 17 deletions packages/babel-jest/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import {createHash} from 'crypto';
import * as path from 'path';
import {
type TransformOptions as BabelTransformOptions,
type PartialConfig,
type TransformOptions,
transformSync as babelTransform,
transformAsync as babelTransformAsync,
} from '@babel/core';
Expand All @@ -23,6 +23,10 @@ import type {
} from '@jest/transform';
import {loadPartialConfig, loadPartialConfigAsync} from './loadBabelConfig';

interface TransformerConfig extends BabelTransformOptions {
excludeJestPreset?: boolean;
}

const THIS_FILE = fs.readFileSync(__filename);
const jestPresetPath = require.resolve('babel-preset-jest');
const babelIstanbulPlugin = require.resolve('babel-plugin-istanbul');
Expand All @@ -44,11 +48,11 @@ function assertLoadedBabelConfig(
}

function addIstanbulInstrumentation(
babelOptions: TransformOptions,
babelOptions: BabelTransformOptions,
transformOptions: JestTransformOptions,
): TransformOptions {
): BabelTransformOptions {
if (transformOptions.instrument) {
const copiedBabelOptions: TransformOptions = {...babelOptions};
const copiedBabelOptions: BabelTransformOptions = {...babelOptions};
copiedBabelOptions.auxiliaryCommentBefore = ' istanbul ignore next ';
// Copied from jest-runtime transform.js
copiedBabelOptions.plugins = [
Expand Down Expand Up @@ -106,7 +110,7 @@ function getCacheKeyFromConfig(
function loadBabelConfig(
cwd: string,
filename: string,
transformOptions: TransformOptions,
transformOptions: BabelTransformOptions,
): PartialConfig {
const babelConfig = loadPartialConfig(transformOptions);

Expand All @@ -118,7 +122,7 @@ function loadBabelConfig(
async function loadBabelConfigAsync(
cwd: string,
filename: string,
transformOptions: TransformOptions,
transformOptions: BabelTransformOptions,
): Promise<PartialConfig> {
const babelConfig = await loadPartialConfigAsync(transformOptions);

Expand All @@ -130,9 +134,9 @@ async function loadBabelConfigAsync(
function loadBabelOptions(
cwd: string,
filename: string,
transformOptions: TransformOptions,
transformOptions: BabelTransformOptions,
jestTransformOptions: JestTransformOptions,
): TransformOptions {
): BabelTransformOptions {
const {options} = loadBabelConfig(cwd, filename, transformOptions);

return addIstanbulInstrumentation(options, jestTransformOptions);
Expand All @@ -141,19 +145,19 @@ function loadBabelOptions(
async function loadBabelOptionsAsync(
cwd: string,
filename: string,
transformOptions: TransformOptions,
transformOptions: BabelTransformOptions,
jestTransformOptions: JestTransformOptions,
): Promise<TransformOptions> {
): Promise<BabelTransformOptions> {
const {options} = await loadBabelConfigAsync(cwd, filename, transformOptions);

return addIstanbulInstrumentation(options, jestTransformOptions);
}

export const createTransformer: TransformerCreator<
SyncTransformer<TransformOptions>,
TransformOptions
> = userOptions => {
const inputOptions = userOptions ?? {};
SyncTransformer<TransformerConfig>,
TransformerConfig
> = transformerConfig => {
const {excludeJestPreset, ...inputOptions} = transformerConfig ?? {};

const options = {
...inputOptions,
Expand All @@ -167,14 +171,17 @@ export const createTransformer: TransformerCreator<
},
compact: false,
plugins: inputOptions.plugins ?? [],
presets: [...(inputOptions.presets ?? []), jestPresetPath],
presets: [
...(inputOptions.presets ?? []),
...(excludeJestPreset === true ? [] : [jestPresetPath]),
],
sourceMaps: 'both',
} satisfies TransformOptions;
} satisfies BabelTransformOptions;

function mergeBabelTransformOptions(
filename: string,
transformOptions: JestTransformOptions,
): TransformOptions {
): BabelTransformOptions {
const {cwd, rootDir} = transformOptions.config;
// `cwd` and `root` first to allow incoming options to override it
return {
Expand Down

0 comments on commit 1775865

Please sign in to comment.