Skip to content

Commit 86f3c89

Browse files
authored
feat: support async createTransformer (#13762)
1 parent 2993a4f commit 86f3c89

File tree

7 files changed

+50
-18
lines changed

7 files changed

+50
-18
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- `[jest-runtime]` Add `jest.isolateModulesAsync` for scoped module initialization of asynchronous functions ([#13680](https://github.com/facebook/jest/pull/13680))
1111
- `[jest-runtime]` Add `jest.isEnvironmentTornDown` function ([#13698](https://github.com/facebook/jest/pull/13698))
1212
- `[jest-test-result]` Added `skipped` and `focused` status to `FormattedTestResult` ([#13700](https://github.com/facebook/jest/pull/13700))
13+
- `[jest-transform]` Support for asynchronous `createTransformer` ([#13762](https://github.com/facebook/jest/pull/13762))
1314

1415
### Fixes
1516

packages/babel-jest/src/__tests__/getCacheKey.test.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
*/
77

88
import type {TransformOptions as BabelTransformOptions} from '@babel/core';
9-
import type {TransformOptions} from '@jest/transform';
9+
import type {SyncTransformer, TransformOptions} from '@jest/transform';
1010
import babelJest from '../index';
1111

12-
const {getCacheKey} = babelJest.createTransformer();
12+
const {getCacheKey} =
13+
babelJest.createTransformer() as SyncTransformer<BabelTransformOptions>;
1314

1415
const processVersion = process.version;
1516
const nodeEnv = process.env.NODE_ENV;
@@ -47,15 +48,15 @@ describe('getCacheKey', () => {
4748
expect(oldCacheKey).toHaveLength(32);
4849
});
4950

50-
test('if `THIS_FILE` value is changing', () => {
51+
test('if `THIS_FILE` value is changing', async () => {
5152
jest.doMock('graceful-fs', () => ({
5253
readFileSync: () => 'new this file',
5354
}));
5455

5556
const {createTransformer} =
5657
require('../index') as typeof import('../index');
5758

58-
const newCacheKey = createTransformer().getCacheKey!(
59+
const newCacheKey = (await createTransformer()).getCacheKey!(
5960
sourceText,
6061
sourcePath,
6162
transformOptions,
@@ -64,7 +65,7 @@ describe('getCacheKey', () => {
6465
expect(oldCacheKey).not.toEqual(newCacheKey);
6566
});
6667

67-
test('if `babelOptions.options` value is changing', () => {
68+
test('if `babelOptions.options` value is changing', async () => {
6869
jest.doMock('../loadBabelConfig', () => {
6970
const babel = require('@babel/core') as typeof import('@babel/core');
7071

@@ -79,7 +80,7 @@ describe('getCacheKey', () => {
7980
const {createTransformer} =
8081
require('../index') as typeof import('../index');
8182

82-
const newCacheKey = createTransformer().getCacheKey!(
83+
const newCacheKey = (await createTransformer()).getCacheKey!(
8384
sourceText,
8485
sourcePath,
8586
transformOptions,
@@ -117,7 +118,7 @@ describe('getCacheKey', () => {
117118
expect(oldCacheKey).not.toEqual(newCacheKey);
118119
});
119120

120-
test('if `babelOptions.config` value is changing', () => {
121+
test('if `babelOptions.config` value is changing', async () => {
121122
jest.doMock('../loadBabelConfig', () => {
122123
const babel = require('@babel/core') as typeof import('@babel/core');
123124

@@ -132,7 +133,7 @@ describe('getCacheKey', () => {
132133
const {createTransformer} =
133134
require('../index') as typeof import('../index');
134135

135-
const newCacheKey = createTransformer().getCacheKey!(
136+
const newCacheKey = (await createTransformer()).getCacheKey!(
136137
sourceText,
137138
sourcePath,
138139
transformOptions,
@@ -141,7 +142,7 @@ describe('getCacheKey', () => {
141142
expect(oldCacheKey).not.toEqual(newCacheKey);
142143
});
143144

144-
test('if `babelOptions.babelrc` value is changing', () => {
145+
test('if `babelOptions.babelrc` value is changing', async () => {
145146
jest.doMock('../loadBabelConfig', () => {
146147
const babel = require('@babel/core') as typeof import('@babel/core');
147148

@@ -156,7 +157,7 @@ describe('getCacheKey', () => {
156157
const {createTransformer} =
157158
require('../index') as typeof import('../index');
158159

159-
const newCacheKey = createTransformer().getCacheKey!(
160+
const newCacheKey = (await createTransformer()).getCacheKey!(
160161
sourceText,
161162
sourcePath,
162163
transformOptions,

packages/babel-jest/src/__tests__/index.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type {
1010
TransformOptions as BabelTransformOptions,
1111
} from '@babel/core';
1212
import {makeProjectConfig} from '@jest/test-utils';
13-
import type {TransformOptions} from '@jest/transform';
13+
import type {SyncTransformer, TransformOptions} from '@jest/transform';
1414
import babelJest, {createTransformer} from '../index';
1515
import {loadPartialConfig} from '../loadBabelConfig';
1616

@@ -28,7 +28,8 @@ jest.mock('../loadBabelConfig', () => {
2828
};
2929
});
3030

31-
const defaultBabelJestTransformer = babelJest.createTransformer();
31+
const defaultBabelJestTransformer =
32+
babelJest.createTransformer() as SyncTransformer<BabelTransformOptions>;
3233

3334
//Mock data for all the tests
3435
const sourceString = `
@@ -163,8 +164,8 @@ describe('caller option correctly merges from defaults and options', () => {
163164
});
164165
});
165166

166-
test('can pass null to createTransformer', () => {
167-
const transformer = createTransformer();
167+
test('can pass null to createTransformer', async () => {
168+
const transformer = await createTransformer();
168169
transformer.process(sourceString, 'dummy_path.js', {
169170
cacheFS: new Map<string, string>(),
170171
config: makeProjectConfig(),

packages/jest-transform/src/ScriptTransformer.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,9 @@ class ScriptTransformer {
283283
throw new Error(makeInvalidTransformerError(transformPath));
284284
}
285285
if (isTransformerFactory(transformer)) {
286-
transformer = transformer.createTransformer(transformerConfig);
286+
transformer = await transformer.createTransformer(
287+
transformerConfig,
288+
);
287289
}
288290
if (
289291
typeof transformer.process !== 'function' &&

packages/jest-transform/src/__tests__/ScriptTransformer.test.ts

+27
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,18 @@ jest.mock(
234234
{virtual: true},
235235
);
236236

237+
jest.mock(
238+
'async-factory',
239+
() => ({
240+
createTransformer() {
241+
return Promise.resolve({
242+
process: jest.fn().mockReturnValue({code: 'code'}),
243+
});
244+
},
245+
}),
246+
{virtual: true},
247+
);
248+
237249
jest.mock(
238250
'factory-for-async-preprocessor',
239251
() => {
@@ -551,6 +563,21 @@ describe('ScriptTransformer', () => {
551563
).toBeDefined();
552564
});
553565

566+
it('handle async createTransformer', async () => {
567+
config = {
568+
...config,
569+
transform: [['\\.js$', 'async-factory', {}]],
570+
};
571+
const scriptTransformer = await createScriptTransformer(config);
572+
expect(
573+
await scriptTransformer.transformSourceAsync(
574+
'sample.js',
575+
'',
576+
getTransformOptions(false),
577+
),
578+
).toBeDefined();
579+
});
580+
554581
it('throws an error if createTransformer returns object without `process` method', async () => {
555582
config = {
556583
...config,

packages/jest-transform/src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ export type Transformer<TransformerConfig = unknown> =
149149
export type TransformerCreator<
150150
X extends Transformer<TransformerConfig>,
151151
TransformerConfig = unknown,
152-
> = (transformerConfig?: TransformerConfig) => X;
152+
> = (transformerConfig?: TransformerConfig) => X | Promise<X>;
153153

154154
/**
155155
* Instead of having your custom transformer implement the Transformer interface

website/versioned_docs/version-29.3/CodeTransformation.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ type Transformer<TransformerConfig = unknown> =
125125
type TransformerCreator<
126126
X extends Transformer<TransformerConfig>,
127127
TransformerConfig = unknown,
128-
> = (transformerConfig?: TransformerConfig) => X;
128+
> = (transformerConfig?: TransformerConfig) => X | Promise<X>;
129129

130130
type TransformerFactory<X extends Transformer> = {
131131
createTransformer: TransformerCreator<X>;
@@ -146,7 +146,7 @@ Semi-related to this are the supports flags we pass (see `CallerTransformOptions
146146

147147
Though not required, we _highly recommend_ implementing `getCacheKey` as well, so we do not waste resources transpiling when we could have read its previous result from disk. You can use [`@jest/create-cache-key-function`](https://www.npmjs.com/package/@jest/create-cache-key-function) to help implement it.
148148

149-
Instead of having your custom transformer implement the `Transformer` interface directly, you can choose to export `createTransformer`, a factory function to dynamically create transformers. This is to allow having a transformer config in your jest config.
149+
Instead of having your custom transformer implement the `Transformer` interface directly, you can choose to export `createTransformer`, a possibly asynchronous factory function to dynamically create transformers. This is to allow having a transformer config in your jest config.
150150

151151
:::note
152152

0 commit comments

Comments
 (0)