Skip to content

Commit

Permalink
feat(jest-haste-map): support dependencyExtractor written in ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
chentsulin committed Oct 28, 2021
1 parent 3d04f33 commit f59420e
Show file tree
Hide file tree
Showing 14 changed files with 297 additions and 132 deletions.
55 changes: 55 additions & 0 deletions e2e/__tests__/findRelatedFiles.test.ts
Expand Up @@ -8,6 +8,7 @@
import {tmpdir} from 'os';
import * as path from 'path';
import {wrap} from 'jest-snapshot-serializer-raw';
import {onNodeVersions} from '@jest/test-utils';
import {cleanup, extractSummary, writeFiles} from '../Utils';
import runJest from '../runJest';

Expand Down Expand Up @@ -117,6 +118,60 @@ describe('--findRelatedTests flag', () => {
expect(stderr).toMatch(summaryMsg);
});

// The versions where vm.Module exists and commonjs with "exports" is not broken
onNodeVersions('>=12.16.0', () => {
test('runs tests related to filename with a custom dependency extractor written in ESM', () => {
writeFiles(DIR, {
'.watchmanconfig': '',
'__tests__/test-skip-deps.test.js': `
const dynamicImport = path => Promise.resolve(require(path));
test('a', () => dynamicImport('../a').then(a => {
expect(a.foo).toBe(5);
}));
`,
'__tests__/test.test.js': `
const dynamicImport = path => Promise.resolve(require(path));
test('a', () => dynamicImport('../a').then(a => {
expect(a.foo).toBe(5);
}));
`,
'a.js': 'module.exports = {foo: 5};',
'dependencyExtractor.mjs': `
const DYNAMIC_IMPORT_RE = /(?:^|[^.]\\s*)(\\bdynamicImport\\s*?\\(\\s*?)([\`'"])([^\`'"]+)(\\2\\s*?\\))/g;
export function extract(code, filePath) {
const dependencies = new Set();
if (filePath.includes('skip-deps')) {
return dependencies;
}
const addDependency = (match, pre, quot, dep, post) => {
dependencies.add(dep);
return match;
};
code.replace(DYNAMIC_IMPORT_RE, addDependency);
return dependencies;
};
`,
'package.json': JSON.stringify({
jest: {
dependencyExtractor: '<rootDir>/dependencyExtractor.mjs',
testEnvironment: 'node',
},
}),
});

const {stdout} = runJest(DIR, ['a.js']);
expect(stdout).toMatch('');

const {stderr} = runJest(DIR, ['--findRelatedTests', 'a.js']);
expect(stderr).toMatch('PASS __tests__/test.test.js');
expect(stderr).not.toMatch('PASS __tests__/test-skip-deps.test.js');

const summaryMsg =
'Ran all test suites related to files matching /a.js/i.';
expect(stderr).toMatch(summaryMsg);
});
});

test('generates coverage report for filename', () => {
writeFiles(DIR, {
'.watchmanconfig': '',
Expand Down
4 changes: 2 additions & 2 deletions e2e/__tests__/hasteMapMockChanged.test.ts
Expand Up @@ -37,11 +37,11 @@ test('should not warn when a mock file changes', async () => {
writeFiles(DIR, {
'__mocks__/fs.js': '"foo fs"',
});
await new JestHasteMap(hasteConfig).build();
await (await JestHasteMap.create(hasteConfig)).build();

// This will throw if the mock file being updated triggers a warning.
writeFiles(DIR, {
'__mocks__/fs.js': '"foo fs!"',
});
await new JestHasteMap(hasteConfig).build();
await (await JestHasteMap.create(hasteConfig)).build();
});
2 changes: 1 addition & 1 deletion e2e/__tests__/hasteMapSha1.test.ts
Expand Up @@ -26,7 +26,7 @@ test('exits the process after test are done but before timers complete', async (
'node_modules/bar/index.js': '"node modules bar"',
});

const haste = new JestHasteMap({
const haste = await JestHasteMap.create({
computeSha1: true,
extensions: ['js', 'json', 'png'],
forceNodeFilesystemAPI: true,
Expand Down
4 changes: 2 additions & 2 deletions e2e/__tests__/hasteMapSize.test.ts
Expand Up @@ -37,13 +37,13 @@ const options = {
};

test('reports the correct file size', async () => {
const hasteMap = new HasteMap(options);
const hasteMap = await HasteMap.create(options);
const hasteFS = (await hasteMap.build()).hasteFS;
expect(hasteFS.getSize(path.join(DIR, 'file.js'))).toBe(5);
});

test('updates the file size when a file changes', async () => {
const hasteMap = new HasteMap({...options, watch: true});
const hasteMap = await HasteMap.create({...options, watch: true});
await hasteMap.build();

writeFiles(DIR, {
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-core/src/cli/index.ts
Expand Up @@ -134,7 +134,7 @@ const buildContextsAndHasteMaps = async (
const contexts = await Promise.all(
configs.map(async (config, index) => {
createDirectory(config.cacheDirectory);
const hasteMapInstance = Runtime.createHasteMap(config, {
const hasteMapInstance = await Runtime.createHasteMap(config, {
console: new CustomConsole(outputStream, outputStream),
maxWorkers: Math.max(
1,
Expand Down
37 changes: 37 additions & 0 deletions packages/jest-haste-map/src/__tests__/dependencyExtractor.mjs
@@ -0,0 +1,37 @@
/**
* 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.
*/

const blockCommentRe = /\/\*[^]*?\*\//g;
const lineCommentRe = /\/\/.*/g;
const LOAD_MODULE_RE =
/(?:^|[^.]\s*)(\bloadModule\s*?\(\s*?)([`'"])([^`'"]+)(\2\s*?\))/g;

export function extract(code, filePath, defaultDependencyExtractor) {
const dependencies = defaultDependencyExtractor(code);

const addDependency = (match, pre, quot, dep, post) => {
dependencies.add(dep);
return match;
};

code
.replace(blockCommentRe, '')
.replace(lineCommentRe, '')
.replace(LOAD_MODULE_RE, addDependency);

return dependencies;
}

let cacheKey;

export function getCacheKey() {
return cacheKey;
}

export function setCacheKey(key) {
cacheKey = key;
}
Expand Up @@ -21,13 +21,13 @@ const commonOptions = {
};

test('watchman crawler and node crawler both include dotfiles', async () => {
const hasteMapWithWatchman = new HasteMap({
const hasteMapWithWatchman = await HasteMap.create({
...commonOptions,
name: 'withWatchman',
useWatchman: true,
});

const hasteMapWithNode = new HasteMap({
const hasteMapWithNode = await HasteMap.create({
...commonOptions,
name: 'withNode',
useWatchman: false,
Expand Down

0 comments on commit f59420e

Please sign in to comment.