Skip to content

Commit

Permalink
fix: repair caching of typescript compiler instances
Browse files Browse the repository at this point in the history
  • Loading branch information
zebreus committed Aug 7, 2022
1 parent 0998187 commit 0c06a79
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,7 @@

### Fixes

- `[jest-config]` Fix testing multiple projects with TypeScript config files ([#13099](https://github.com/facebook/jest/pull/13099))
- `[@jest/expect-utils]` Fix deep equality of ImmutableJS Record ([#13055](https://github.com/facebook/jest/pull/13055))
- `[jest-haste-map]` Increase the maximum possible file size that jest-haste-map can handle ([#13094](https://github.com/facebook/jest/pull/13094))
- `[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))
Expand Down
109 changes: 109 additions & 0 deletions e2e/__tests__/typescriptConfigFile.test.ts
@@ -0,0 +1,109 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {tmpdir} from 'os';
import * as path from 'path';
import {cleanup, writeFiles} from '../Utils';
import runJest from '../runJest';

const DIR = path.resolve(tmpdir(), 'typescript-config-file');

beforeEach(() => cleanup(DIR));
afterEach(() => cleanup(DIR));

test('works with single typescript config that imports something', () => {
writeFiles(DIR, {
'__tests__/mytest.alpha.js': "test('alpha', () => expect(1).toBe(1));",
'__tests__/mytest.common.js': "test('common', () => expect(1).toBe(1));",
'alpha.config.ts': `
import commonRegex from './common';
export default {
testRegex: [ commonRegex, '__tests__/mytest.alpha.js' ]
};`,
'common.ts': "export default '__tests__/mytest.common.js$';",
});

const {stdout, stderr, exitCode} = runJest(
DIR,
['--projects', 'alpha.config.ts'],
{
skipPkgJsonCheck: true,
},
);

expect(stderr).toContain('PASS __tests__/mytest.alpha.js');
expect(stderr).toContain('PASS __tests__/mytest.common.js');
expect(stderr).toContain('Test Suites: 2 passed, 2 total');
expect(exitCode).toBe(0);
expect(stdout).toBe('');
});

test('works with multiple typescript configs', () => {
writeFiles(DIR, {
'__tests__/mytest.alpha.js': "test('alpha', () => expect(1).toBe(1));",
'__tests__/mytest.beta.js': "test('beta', () => expect(1).toBe(1));",
'alpha.config.ts': `
export default {
testRegex: '__tests__/mytest.alpha.js'
};`,
'beta.config.ts': `
export default {
testRegex: '__tests__/mytest.beta.js'
};`,
});

const {stdout, stderr, exitCode} = runJest(
DIR,
['--projects', 'alpha.config.ts', 'beta.config.ts'],
{
skipPkgJsonCheck: true,
},
);

expect(stderr).toContain('PASS __tests__/mytest.alpha.js');
expect(stderr).toContain('PASS __tests__/mytest.beta.js');
expect(stderr).toContain('Test Suites: 2 passed, 2 total');
expect(exitCode).toBe(0);
expect(stdout).toBe('');
});

test('works with multiple typescript configs that import something', () => {
writeFiles(DIR, {
'__tests__/mytest.alpha.js': "test('alpha', () => expect(1).toBe(1));",
'__tests__/mytest.beta.js': "test('beta', () => expect(1).toBe(1));",
'__tests__/mytest.common.js': "test('common', () => expect(1).toBe(1));",
'alpha.config.ts': `
import commonRegex from './common';
export default {
testRegex: [ commonRegex, '__tests__/mytest.alpha.js' ]
};`,
'beta.config.ts': `
import commonRegex from './common';
export default {
testRegex: [ commonRegex, '__tests__/mytest.beta.js' ]
};`,
'common.ts': "export default '__tests__/mytest.common.js$';",
});

const {stdout, stderr, exitCode} = runJest(
DIR,
['--projects', 'alpha.config.ts', 'beta.config.ts'],
{
skipPkgJsonCheck: true,
},
);

expect(stderr).toContain('PASS __tests__/mytest.alpha.js');
expect(stderr).toContain('PASS __tests__/mytest.beta.js');
expect(stderr).toContain('PASS __tests__/mytest.common.js');
expect(stderr.replace('PASS __tests__/mytest.common.js', '')).toContain(
'PASS __tests__/mytest.common.js',
);
expect(stderr).toContain('Test Suites: 4 passed, 4 total');
expect(exitCode).toBe(0);
expect(stdout).toBe('');
});
28 changes: 15 additions & 13 deletions packages/jest-config/src/readConfigFileAndSetRootDir.ts
Expand Up @@ -77,16 +77,14 @@ export default async function readConfigFileAndSetRootDir(
return configObject;
}

let registerer: Service;

// Load the TypeScript configuration
const loadTSConfigFile = async (
configPath: string,
): Promise<Config.InitialOptions> => {
// Register TypeScript compiler instance
await registerTsNode();
// Get registered TypeScript compiler instance
const registeredCompiler = await getRegisteredCompiler();

registerer.enabled(true);
registeredCompiler.enabled(true);

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

Expand All @@ -95,27 +93,31 @@ const loadTSConfigFile = async (
configObject = await configObject();
}

registerer.enabled(false);
registeredCompiler.enabled(false);

return configObject;
};

async function registerTsNode(): Promise<Service> {
if (registerer) {
return registerer;
}
let registeredCompilerPromise: Promise<Service>;

const getRegisteredCompiler = async () => {
// Cache the promise to avoid multiple registrations
registeredCompilerPromise = registeredCompilerPromise ?? registerTsNode();
return registeredCompilerPromise;
};

const registerTsNode = async () => {
try {
// Register TypeScript compiler instance
const tsNode = await import('ts-node');
registerer = tsNode.register({
return tsNode.register({
compilerOptions: {
module: 'CommonJS',
},
moduleTypes: {
'**': 'cjs',
},
});
return registerer;
} catch (e: any) {
if (e.code === 'ERR_MODULE_NOT_FOUND') {
throw new Error(
Expand All @@ -125,4 +127,4 @@ async function registerTsNode(): Promise<Service> {

throw e;
}
}
};

0 comments on commit 0c06a79

Please sign in to comment.