Skip to content

Commit

Permalink
feat: replace sane with chokidar
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Nov 26, 2020
1 parent 245a582 commit 22226cd
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 286 deletions.
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ module.exports = {
'packages/jest-core/src/plugins/UpdateSnapshotsInteractive.ts',
'packages/jest-fake-timers/src/legacyFakeTimers.ts',
'packages/jest-haste-map/src/index.ts',
'packages/jest-haste-map/src/lib/FSEventsWatcher.ts',
'packages/jest-jasmine2/src/jasmine/SpyStrategy.ts',
'packages/jest-jasmine2/src/jasmine/Suite.ts',
'packages/jest-leak-detector/src/index.ts',
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- `[jest-circus]` Fixed the issue of beforeAll & afterAll hooks getting executed even if it is inside a skipped `describe` block [#10451](https://github.com/facebook/jest/issues/10451)
- `[jest-circus]` Fix `testLocation` on Windows when using `test.each` ([#10871](https://github.com/facebook/jest/pull/10871))
- `[jest-console]` `console.dir` now respects the second argument correctly ([#10638](https://github.com/facebook/jest/pull/10638))
- `[jest-haste-map]` Replace `sane` with `chokidar` ([#10048](https://github.com/facebook/jest/pull/10048))
- `[jest-jasmine2]` Fixed the issue of beforeAll & afterAll hooks getting executed even if it is inside a skipped `describe` block when it has child `tests` marked as either `only` or `todo` [#10451](https://github.com/facebook/jest/issues/10451)
- `[jest-jasmine2]` Fixed the issues of child `tests` marked with `only` or `todo` getting executed even if it is inside a skipped parent `describe` block [#10451](https://github.com/facebook/jest/issues/10451)
- `[jest-reporter]` Handle empty files when reporting code coverage with V8 ([#10819](https://github.com/facebook/jest/pull/10819))
Expand Down
11 changes: 2 additions & 9 deletions packages/jest-haste-map/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,22 @@
"@jest/types": "^26.6.2",
"@types/graceful-fs": "^4.1.2",
"@types/node": "*",
"anymatch": "^3.0.3",
"chokidar": "^3.4.2",
"fb-watchman": "^2.0.0",
"graceful-fs": "^4.2.4",
"jest-regex-util": "^26.0.0",
"jest-serializer": "^26.6.2",
"jest-util": "^26.6.2",
"jest-worker": "^26.6.2",
"micromatch": "^4.0.2",
"sane": "^4.0.3",
"walker": "^1.0.7"
"micromatch": "^4.0.2"
},
"devDependencies": {
"@jest/test-utils": "^26.6.2",
"@types/anymatch": "^1.3.1",
"@types/fb-watchman": "^2.0.0",
"@types/micromatch": "^4.0.0",
"@types/sane": "^2.0.0",
"jest-snapshot-serializer-raw": "^1.1.0",
"slash": "^3.0.0"
},
"optionalDependencies": {
"fsevents": "^2.1.2"
},
"engines": {
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
},
Expand Down
7 changes: 3 additions & 4 deletions packages/jest-haste-map/src/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,13 @@ jest.mock('../crawlers/watchman', () =>
const mockWatcherConstructor = jest.fn(root => {
const EventEmitter = require('events').EventEmitter;
mockEmitters[root] = new EventEmitter();
mockEmitters[root].close = jest.fn(callback => callback());
mockEmitters[root].close = jest.fn();
setTimeout(() => mockEmitters[root].emit('ready'), 0);
return mockEmitters[root];
});

jest.mock('sane', () => ({
NodeWatcher: mockWatcherConstructor,
WatchmanWatcher: mockWatcherConstructor,
jest.mock('chokidar', () => ({
watch: jest.fn((patten, opts) => mockWatcherConstructor(opts.cwd)),
}));

jest.mock('../lib/WatchmanWatcher', () => mockWatcherConstructor);
Expand Down
62 changes: 31 additions & 31 deletions packages/jest-haste-map/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {createHash} from 'crypto';
import {EventEmitter} from 'events';
import {tmpdir} from 'os';
import * as path from 'path';
import {FSWatcher as ChokidarFsWatcher, watch as chokidarWatch} from 'chokidar';
import type {Stats} from 'graceful-fs';
import {NodeWatcher, Watcher as SaneWatcher} from 'sane';
import type {Config} from '@jest/types';
import {escapePathForRegex} from 'jest-regex-util';
import serializer from 'jest-serializer';
Expand All @@ -26,7 +26,6 @@ import H from './constants';
import nodeCrawl = require('./crawlers/node');
import watchmanCrawl = require('./crawlers/watchman');
import getMockName from './getMockName';
import FSEventsWatcher = require('./lib/FSEventsWatcher');
// @ts-expect-error: not converted to TypeScript - it's a fork: https://github.com/facebook/jest/pull/5387
import WatchmanWatcher from './lib/WatchmanWatcher';
import * as fastPath from './lib/fast_path';
Expand Down Expand Up @@ -101,7 +100,7 @@ type InternalOptions = {
};

type Watcher = {
close(callback: () => void): void;
close(): Promise<void>;
};

type WorkerInterface = {worker: typeof worker; getSha1: typeof getSha1};
Expand Down Expand Up @@ -788,14 +787,6 @@ class HasteMap extends EventEmitter {
this._options.throwOnModuleCollision = false;
this._options.retainAllFiles = true;

// WatchmanWatcher > FSEventsWatcher > sane.NodeWatcher
const Watcher: SaneWatcher =
canUseWatchman && this._options.useWatchman
? WatchmanWatcher
: FSEventsWatcher.isSupported()
? FSEventsWatcher
: NodeWatcher;

const extensions = this._options.extensions;
const ignorePattern = this._options.ignorePattern;
const rootDir = this._options.rootDir;
Expand All @@ -806,12 +797,21 @@ class HasteMap extends EventEmitter {
let mustCopy = true;

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: true,
glob: extensions.map(extension => '**/*.' + extension),
ignored: ignorePattern,
});
const useWatchman = canUseWatchman && this._options.useWatchman;
const patterns = extensions.map(extension => '**/*.' + extension);
// Prefer Watchman over Chokidar
const watcher = useWatchman
? new WatchmanWatcher(root, {
dot: true,
glob: patterns,
ignored: ignorePattern,
})
: chokidarWatch(patterns, {
alwaysStat: true,
cwd: root,
ignoreInitial: true,
ignored: ignorePattern,
});

return new Promise((resolve, reject) => {
const rejectTimeout = setTimeout(
Expand All @@ -821,7 +821,14 @@ class HasteMap extends EventEmitter {

watcher.once('ready', () => {
clearTimeout(rejectTimeout);
watcher.on('all', onChange);

if (useWatchman) {
watcher.on('all', onChange);
} else {
(watcher as ChokidarFsWatcher).on('all', (type, filePath, stat) => {
onChange(type, filePath, root, stat);
});
}
resolve(watcher);
});
});
Expand All @@ -832,10 +839,7 @@ class HasteMap extends EventEmitter {
mustCopy = true;
const changeEvent: ChangeEvent = {
eventsQueue,
hasteFS: new HasteFS({
files: hasteMap.files,
rootDir,
}),
hasteFS: new HasteFS({files: hasteMap.files, rootDir}),
moduleMap: new HasteModuleMap({
duplicates: hasteMap.duplicates,
map: hasteMap.map,
Expand Down Expand Up @@ -1051,20 +1055,16 @@ class HasteMap extends EventEmitter {
}
}

end(): Promise<void> {
async end(): Promise<void> {
// @ts-expect-error: TODO TS cannot decide if `setInterval` and `clearInterval` comes from NodeJS or the DOM
clearInterval(this._changeInterval);
if (!this._watchers.length) {
return Promise.resolve();
return;
}

return Promise.all(
this._watchers.map(
watcher => new Promise(resolve => watcher.close(resolve)),
),
).then(() => {
this._watchers = [];
});
await Promise.all(this._watchers.map(watcher => watcher.close()));

this._watchers = [];
}

/**
Expand Down
192 changes: 0 additions & 192 deletions packages/jest-haste-map/src/lib/FSEventsWatcher.ts

This file was deleted.

6 changes: 2 additions & 4 deletions packages/jest-haste-map/src/lib/WatchmanWatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,14 +278,12 @@ WatchmanWatcher.prototype.emitEvent = function (
/**
* Closes the watcher.
*
* @param {function} callback
* @private
*/

WatchmanWatcher.prototype.close = function (callback) {
WatchmanWatcher.prototype.close = function () {
this.client.removeAllListeners();
this.client.end();
callback && callback(null, true);
return Promise.resolve();
};

/**
Expand Down
Loading

0 comments on commit 22226cd

Please sign in to comment.