Skip to content

Commit 0b679b8

Browse files
authored
fix: repair caching of typescript compiler instances (#13099)
1 parent 0998187 commit 0b679b8

File tree

3 files changed

+124
-12
lines changed

3 files changed

+124
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
### Fixes
1111

12+
- `[jest-config]` Fix testing multiple projects with TypeScript config files ([#13099](https://github.com/facebook/jest/pull/13099))
1213
- `[@jest/expect-utils]` Fix deep equality of ImmutableJS Record ([#13055](https://github.com/facebook/jest/pull/13055))
1314
- `[jest-haste-map]` Increase the maximum possible file size that jest-haste-map can handle ([#13094](https://github.com/facebook/jest/pull/13094))
1415
- `[jest-worker]` When a process runs out of memory worker exits correctly and doesn't spin indefinitely ([#13054](https://github.com/facebook/jest/pull/13054))
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import {tmpdir} from 'os';
9+
import * as path from 'path';
10+
import {cleanup, writeFiles} from '../Utils';
11+
import runJest from '../runJest';
12+
13+
const DIR = path.resolve(tmpdir(), 'typescript-config-file');
14+
15+
beforeEach(() => cleanup(DIR));
16+
afterEach(() => cleanup(DIR));
17+
18+
test('works with single typescript config that imports something', () => {
19+
writeFiles(DIR, {
20+
'__tests__/mytest.alpha.js': "test('alpha', () => expect(1).toBe(1));",
21+
'__tests__/mytest.common.js': "test('common', () => expect(1).toBe(1));",
22+
'alpha.config.ts': `
23+
import commonRegex from './common';
24+
export default {
25+
testRegex: [ commonRegex, '__tests__/mytest.alpha.js' ]
26+
};`,
27+
'common.ts': "export default '__tests__/mytest.common.js$';",
28+
});
29+
30+
const {stdout, stderr, exitCode} = runJest(
31+
DIR,
32+
['--projects', 'alpha.config.ts'],
33+
{
34+
skipPkgJsonCheck: true,
35+
},
36+
);
37+
38+
expect(stderr).toContain('PASS __tests__/mytest.alpha.js');
39+
expect(stderr).toContain('PASS __tests__/mytest.common.js');
40+
expect(stderr).toContain('Test Suites: 2 passed, 2 total');
41+
expect(exitCode).toBe(0);
42+
expect(stdout).toBe('');
43+
});
44+
45+
test('works with multiple typescript configs', () => {
46+
writeFiles(DIR, {
47+
'__tests__/mytest.alpha.js': "test('alpha', () => expect(1).toBe(1));",
48+
'__tests__/mytest.beta.js': "test('beta', () => expect(1).toBe(1));",
49+
'alpha.config.ts': `
50+
export default {
51+
testRegex: '__tests__/mytest.alpha.js'
52+
};`,
53+
'beta.config.ts': `
54+
export default {
55+
testRegex: '__tests__/mytest.beta.js'
56+
};`,
57+
});
58+
59+
const {stdout, stderr, exitCode} = runJest(
60+
DIR,
61+
['--projects', 'alpha.config.ts', 'beta.config.ts'],
62+
{
63+
skipPkgJsonCheck: true,
64+
},
65+
);
66+
67+
expect(stderr).toContain('PASS __tests__/mytest.alpha.js');
68+
expect(stderr).toContain('PASS __tests__/mytest.beta.js');
69+
expect(stderr).toContain('Test Suites: 2 passed, 2 total');
70+
expect(exitCode).toBe(0);
71+
expect(stdout).toBe('');
72+
});
73+
74+
test('works with multiple typescript configs that import something', () => {
75+
writeFiles(DIR, {
76+
'__tests__/mytest.alpha.js': "test('alpha', () => expect(1).toBe(1));",
77+
'__tests__/mytest.beta.js': "test('beta', () => expect(1).toBe(1));",
78+
'__tests__/mytest.common.js': "test('common', () => expect(1).toBe(1));",
79+
'alpha.config.ts': `
80+
import commonRegex from './common';
81+
export default {
82+
testRegex: [ commonRegex, '__tests__/mytest.alpha.js' ]
83+
};`,
84+
'beta.config.ts': `
85+
import commonRegex from './common';
86+
export default {
87+
testRegex: [ commonRegex, '__tests__/mytest.beta.js' ]
88+
};`,
89+
'common.ts': "export default '__tests__/mytest.common.js$';",
90+
});
91+
92+
const {stdout, stderr, exitCode} = runJest(
93+
DIR,
94+
['--projects', 'alpha.config.ts', 'beta.config.ts'],
95+
{
96+
skipPkgJsonCheck: true,
97+
},
98+
);
99+
100+
expect(stderr).toContain('PASS __tests__/mytest.alpha.js');
101+
expect(stderr).toContain('PASS __tests__/mytest.beta.js');
102+
expect(stderr).toContain('PASS __tests__/mytest.common.js');
103+
expect(stderr.replace('PASS __tests__/mytest.common.js', '')).toContain(
104+
'PASS __tests__/mytest.common.js',
105+
);
106+
expect(stderr).toContain('Test Suites: 4 passed, 4 total');
107+
expect(exitCode).toBe(0);
108+
expect(stdout).toBe('');
109+
});

packages/jest-config/src/readConfigFileAndSetRootDir.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,14 @@ export default async function readConfigFileAndSetRootDir(
7777
return configObject;
7878
}
7979

80-
let registerer: Service;
81-
8280
// Load the TypeScript configuration
8381
const loadTSConfigFile = async (
8482
configPath: string,
8583
): Promise<Config.InitialOptions> => {
86-
// Register TypeScript compiler instance
87-
await registerTsNode();
84+
// Get registered TypeScript compiler instance
85+
const registeredCompiler = await getRegisteredCompiler();
8886

89-
registerer.enabled(true);
87+
registeredCompiler.enabled(true);
9088

9189
let configObject = interopRequireDefault(require(configPath)).default;
9290

@@ -95,27 +93,31 @@ const loadTSConfigFile = async (
9593
configObject = await configObject();
9694
}
9795

98-
registerer.enabled(false);
96+
registeredCompiler.enabled(false);
9997

10098
return configObject;
10199
};
102100

103-
async function registerTsNode(): Promise<Service> {
104-
if (registerer) {
105-
return registerer;
106-
}
101+
let registeredCompilerPromise: Promise<Service>;
107102

103+
function getRegisteredCompiler() {
104+
// Cache the promise to avoid multiple registrations
105+
registeredCompilerPromise = registeredCompilerPromise ?? registerTsNode();
106+
return registeredCompilerPromise;
107+
}
108+
109+
async function registerTsNode(): Promise<Service> {
108110
try {
111+
// Register TypeScript compiler instance
109112
const tsNode = await import('ts-node');
110-
registerer = tsNode.register({
113+
return tsNode.register({
111114
compilerOptions: {
112115
module: 'CommonJS',
113116
},
114117
moduleTypes: {
115118
'**': 'cjs',
116119
},
117120
});
118-
return registerer;
119121
} catch (e: any) {
120122
if (e.code === 'ERR_MODULE_NOT_FOUND') {
121123
throw new Error(

0 commit comments

Comments
 (0)