Skip to content

Commit

Permalink
feat(haste-map): watchman crawler now includes dotfiles (#10075)
Browse files Browse the repository at this point in the history
  • Loading branch information
grosto committed Jul 30, 2020
1 parent e3f4f93 commit e270997
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@

- `[jest-core, jest-circus, jest-reporter, jest-runner]` Added support for reporting individual test cases using jest-circus ([#10227](https://github.com/facebook/jest/pull/10227))
- `[jest-config, jest-reporter, jest-runner, jest-test-sequencer]` Add `slowTestThreshold` configuration option ([#9366](https://github.com/facebook/jest/pull/9366))
- `[jest-haste-map]` Watchman crawler now includes dotfiles ([#10075](https://github.com/facebook/jest/pull/10075))
- `[jest-worker]` Added support for workers to send custom messages to parent in jest-worker ([#10293](https://github.com/facebook/jest/pull/10293))
- `[jest-worker]` Support passing `resourceLimits` ([#10335](https://github.com/facebook/jest/pull/10335))
- `[pretty-format]` Added support for serializing custom elements (web components) ([#10217](https://github.com/facebook/jest/pull/10237))
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Expand Up @@ -49,6 +49,7 @@ module.exports = {
'/packages/jest-cli/src/init/__tests__/fixtures/',
'/packages/jest-haste-map/src/__tests__/haste_impl.js',
'/packages/jest-haste-map/src/__tests__/dependencyExtractor.js',
'/packages/jest-haste-map/src/__tests__/test_dotfiles_root/',
'/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/',
'/packages/jest-runtime/src/__tests__/defaultResolver.js',
'/packages/jest-runtime/src/__tests__/module_dir/',
Expand Down
1 change: 1 addition & 0 deletions packages/jest-haste-map/package.json
Expand Up @@ -16,6 +16,7 @@
"anymatch": "^3.0.3",
"fb-watchman": "^2.0.0",
"graceful-fs": "^4.2.4",
"jest-regex-util": "^26.0.0",
"jest-serializer": "^26.1.0",
"jest-util": "^26.1.0",
"jest-worker": "^26.1.0",
Expand Down
48 changes: 48 additions & 0 deletions packages/jest-haste-map/src/__tests__/includes_dotfiles.test.ts
@@ -0,0 +1,48 @@
/**
* 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 path from 'path';
import HasteMap from '../index';

const rootDir = path.join(__dirname, './test_dotfiles_root');

const commonOptions = {
extensions: ['js'],
maxWorkers: 1,
platforms: [],
resetCache: true,
retainAllFiles: true,
rootDir,
roots: [rootDir],
};

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

const hasteMapWithNode = new HasteMap({
...commonOptions,
name: 'withNode',
useWatchman: false,
});

const [builtHasteMapWithWatchman, builtHasteMapWithNode] = await Promise.all([
hasteMapWithWatchman.build(),
hasteMapWithNode.build(),
]);

expect(
builtHasteMapWithWatchman.hasteFS.matchFiles('.eslintrc.js'),
).toHaveLength(1);

expect(builtHasteMapWithWatchman.hasteFS.getAllFiles().sort()).toEqual(
builtHasteMapWithNode.hasteFS.getAllFiles().sort(),
);
});
39 changes: 39 additions & 0 deletions packages/jest-haste-map/src/__tests__/index.test.js
Expand Up @@ -294,6 +294,45 @@ describe('HasteMap', () => {
});
});

it('ignores vcs directories without ignore pattern', () => {
mockFs['/project/fruits/.git/fruit-history.js'] = `
// test
`;
return new HasteMap(defaultConfig).build().then(({hasteFS}) => {
expect(hasteFS.matchFiles('.git')).toEqual([]);
});
});

it('ignores vcs directories with ignore pattern regex', () => {
const config = {...defaultConfig, ignorePattern: /Kiwi/};
mockFs['/project/fruits/Kiwi.js'] = `
// Kiwi!
`;

mockFs['/project/fruits/.git/fruit-history.js'] = `
// test
`;
return new HasteMap(config).build().then(({hasteFS}) => {
expect(hasteFS.matchFiles(/Kiwi/)).toEqual([]);
expect(hasteFS.matchFiles('.git')).toEqual([]);
});
});

it('ignores vcs directories with ignore pattern function', () => {
const config = {...defaultConfig, ignorePattern: f => /Kiwi/.test(f)};
mockFs['/project/fruits/Kiwi.js'] = `
// Kiwi!
`;

mockFs['/project/fruits/.git/fruit-history.js'] = `
// test
`;
return new HasteMap(config).build().then(({hasteFS}) => {
expect(hasteFS.matchFiles(/Kiwi/)).toEqual([]);
expect(hasteFS.matchFiles('.git')).toEqual([]);
});
});

it('builds a haste map on a fresh cache', () => {
// Include these files in the map
mockFs['/project/fruits/node_modules/react/React.js'] = `
Expand Down
@@ -0,0 +1,6 @@
/**
* 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.
*/
@@ -0,0 +1,6 @@
/**
* 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.
*/
2 changes: 1 addition & 1 deletion packages/jest-haste-map/src/crawlers/watchman.ts
Expand Up @@ -126,7 +126,7 @@ export = async function watchmanCrawl(
? // Use the `since` generator if we have a clock available
{expression, fields, since: clocks.get(relativeRoot)}
: // Otherwise use the `glob` filter
{expression, fields, glob};
{expression, fields, glob, glob_includedotfiles: true};

const response = await cmd('query', root, query);

Expand Down
32 changes: 25 additions & 7 deletions packages/jest-haste-map/src/index.ts
Expand Up @@ -15,6 +15,7 @@ import {NodeWatcher, Watcher as SaneWatcher} from 'sane';
import type {Config} from '@jest/types';
import serializer from 'jest-serializer';
import Worker from 'jest-worker';
import {escapePathForRegex} from 'jest-regex-util';
import {getSha1, worker} from './worker';
import getMockName from './getMockName';
import getPlatformExtension from './lib/getPlatformExtension';
Expand Down Expand Up @@ -113,6 +114,9 @@ const CHANGE_INTERVAL = 30;
const MAX_WAIT_TIME = 240000;
const NODE_MODULES = path.sep + 'node_modules' + path.sep;
const PACKAGE_JSON = path.sep + 'package.json';
const VCS_DIRECTORIES = ['.git', '.hg']
.map(vcs => escapePathForRegex(path.sep + vcs + path.sep))
.join('|');

// TypeScript doesn't like us importing from outside `rootDir`, but it doesn't
// understand `require`.
Expand Down Expand Up @@ -233,7 +237,6 @@ class HasteMap extends EventEmitter {
extensions: options.extensions,
forceNodeFilesystemAPI: !!options.forceNodeFilesystemAPI,
hasteImplModulePath: options.hasteImplModulePath,
ignorePattern: options.ignorePattern,
maxWorkers: options.maxWorkers,
mocksPattern: options.mocksPattern
? new RegExp(options.mocksPattern)
Expand All @@ -250,11 +253,26 @@ class HasteMap extends EventEmitter {
watch: !!options.watch,
};
this._console = options.console || global.console;
if (options.ignorePattern && !(options.ignorePattern instanceof RegExp)) {
this._console.warn(
'jest-haste-map: the `ignorePattern` options as a function is being ' +
'deprecated. Provide a RegExp instead. See https://github.com/facebook/jest/pull/4063.',
);

if (options.ignorePattern) {
if (options.ignorePattern instanceof RegExp) {
this._options.ignorePattern = new RegExp(
options.ignorePattern.source.concat('|' + VCS_DIRECTORIES),
options.ignorePattern.flags,
);
} else {
const ignorePattern = options.ignorePattern;
const vcsIgnoreRegExp = new RegExp(VCS_DIRECTORIES);
this._options.ignorePattern = (filePath: string) =>
vcsIgnoreRegExp.test(filePath) || ignorePattern(filePath);

this._console.warn(
'jest-haste-map: the `ignorePattern` options as a function is being ' +
'deprecated. Provide a RegExp instead. See https://github.com/facebook/jest/pull/4063.',
);
}
} else {
this._options.ignorePattern = new RegExp(VCS_DIRECTORIES);
}

const rootDirHash = createHash('md5').update(options.rootDir).digest('hex');
Expand Down Expand Up @@ -790,7 +808,7 @@ class HasteMap extends EventEmitter {
const createWatcher = (root: Config.Path): Promise<Watcher> => {
// @ts-expect-error: TODO how? "Cannot use 'new' with an expression whose type lacks a call or construct signature."
const watcher = new Watcher(root, {
dot: false,
dot: true,
glob: extensions.map(extension => '**/*.' + extension),
ignored: ignorePattern,
});
Expand Down
5 changes: 3 additions & 2 deletions packages/jest-haste-map/tsconfig.json
Expand Up @@ -5,9 +5,10 @@
"outDir": "build"
},
"references": [
{"path": "../jest-worker"},
{"path": "../jest-regex-util"},
{"path": "../jest-serializer"},
{"path": "../jest-types"},
{"path": "../jest-util"},
{"path": "../jest-types"}
{"path": "../jest-worker"}
]
}
1 change: 1 addition & 0 deletions yarn.lock
Expand Up @@ -11220,6 +11220,7 @@ fsevents@^1.2.7:
fb-watchman: ^2.0.0
fsevents: ^2.1.2
graceful-fs: ^4.2.4
jest-regex-util: ^26.0.0
jest-serializer: ^26.1.0
jest-util: ^26.1.0
jest-worker: ^26.1.0
Expand Down

0 comments on commit e270997

Please sign in to comment.