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 5c21bae
Show file tree
Hide file tree
Showing 10 changed files with 287 additions and 123 deletions.
58 changes: 58 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,63 @@ 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 default {
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
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 5c21bae

Please sign in to comment.