Skip to content

Commit

Permalink
Prevents watchers from being awake by created folders (#6818)
Browse files Browse the repository at this point in the history
  • Loading branch information
arcanis authored and mjesun committed Aug 10, 2018
1 parent 674eaa9 commit ede0fe3
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- `[jest-snapshot]` Correctly merge property matchers with the rest of the snapshot in `toMatchSnapshot`. ([#6528](https://github.com/facebook/jest/pull/6528))
- `[jest-snapshot]` Add error messages for invalid property matchers. ([#6528](https://github.com/facebook/jest/pull/6528))
- `[jest-cli]` Show open handles from inside test files as well ([#6263](https://github.com/facebook/jest/pull/6263))
- `[jest-haste-map]` Fix a problem where creating folders ending with `.js` could cause a crash ([#6818](https://github.com/facebook/jest/pull/6818))

### Chore & Maintenance

Expand Down
1 change: 1 addition & 0 deletions packages/jest-haste-map/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"dependencies": {
"fb-watchman": "^2.0.0",
"graceful-fs": "^4.1.11",
"invariant": "^2.2.4",
"jest-docblock": "^23.2.0",
"jest-serializer": "^23.0.1",
"jest-worker": "^23.2.0",
Expand Down
74 changes: 57 additions & 17 deletions packages/jest-haste-map/src/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,15 @@ describe('HasteMap', () => {
expect(moduleMap.getModule('Banana')).toBeNull();
});

const MOCK_STAT = {mtime: {getTime: () => 45}};
const MOCK_STAT_FILE = {
isDirectory: () => false,
mtime: {getTime: () => 45},
};

const MOCK_STAT_FOLDER = {
isDirectory: () => true,
mtime: {getTime: () => 45},
};

hm_it('handles several change events at once', async hm => {
mockFs['/fruits/tomato.js'] = [
Expand All @@ -1084,18 +1092,18 @@ describe('HasteMap', () => {
' */',
].join('\n');
const e = mockEmitters['/fruits'];
e.emit('all', 'add', 'tomato.js', '/fruits', MOCK_STAT);
e.emit('all', 'change', 'pear.js', '/fruits', MOCK_STAT);
e.emit('all', 'add', 'tomato.js', '/fruits', MOCK_STAT_FILE);
e.emit('all', 'change', 'pear.js', '/fruits', MOCK_STAT_FILE);
const {eventsQueue, hasteFS, moduleMap} = await waitForItToChange(hm);
expect(eventsQueue).toEqual([
{
filePath: '/fruits/tomato.js',
stat: MOCK_STAT,
stat: MOCK_STAT_FILE,
type: 'add',
},
{
filePath: '/fruits/pear.js',
stat: MOCK_STAT,
stat: MOCK_STAT_FILE,
type: 'change',
},
]);
Expand All @@ -1107,8 +1115,8 @@ describe('HasteMap', () => {

hm_it('does not emit duplicate change events', async hm => {
const e = mockEmitters['/fruits'];
e.emit('all', 'change', 'tomato.js', '/fruits', MOCK_STAT);
e.emit('all', 'change', 'tomato.js', '/fruits', MOCK_STAT);
e.emit('all', 'change', 'tomato.js', '/fruits', MOCK_STAT_FILE);
e.emit('all', 'change', 'tomato.js', '/fruits', MOCK_STAT_FILE);
const {eventsQueue} = await waitForItToChange(hm);
expect(eventsQueue).toHaveLength(1);
});
Expand All @@ -1117,11 +1125,19 @@ describe('HasteMap', () => {
'emits a change even if a file in node_modules has changed',
async hm => {
const e = mockEmitters['/fruits'];
e.emit('all', 'add', 'apple.js', '/fruits/node_modules/', MOCK_STAT);
e.emit(
'all',
'add',
'apple.js',
'/fruits/node_modules/',
MOCK_STAT_FILE,
);
const {eventsQueue, hasteFS} = await waitForItToChange(hm);
const filePath = '/fruits/node_modules/apple.js';
expect(eventsQueue).toHaveLength(1);
expect(eventsQueue).toEqual([{filePath, stat: MOCK_STAT, type: 'add'}]);
expect(eventsQueue).toEqual([
{filePath, stat: MOCK_STAT_FILE, type: 'add'},
]);
expect(hasteFS.getModuleName(filePath)).toBeDefined();
},
);
Expand All @@ -1133,15 +1149,25 @@ describe('HasteMap', () => {
expect(initMM.getModule('Orange', 'ios')).toBeTruthy();
expect(initMM.getModule('Orange', 'android')).toBeTruthy();
const e = mockEmitters['/fruits'];
e.emit('all', 'change', 'Orange.ios.js', '/fruits/', MOCK_STAT);
e.emit('all', 'change', 'Orange.android.js', '/fruits/', MOCK_STAT);
e.emit('all', 'change', 'Orange.ios.js', '/fruits/', MOCK_STAT_FILE);
e.emit(
'all',
'change',
'Orange.android.js',
'/fruits/',
MOCK_STAT_FILE,
);
const {eventsQueue, hasteFS, moduleMap} = await waitForItToChange(hm);
expect(eventsQueue).toHaveLength(2);
expect(eventsQueue).toEqual([
{filePath: '/fruits/Orange.ios.js', stat: MOCK_STAT, type: 'change'},
{
filePath: '/fruits/Orange.ios.js',
stat: MOCK_STAT_FILE,
type: 'change',
},
{
filePath: '/fruits/Orange.android.js',
stat: MOCK_STAT,
stat: MOCK_STAT_FILE,
type: 'change',
},
]);
Expand Down Expand Up @@ -1182,8 +1208,8 @@ describe('HasteMap', () => {
' */',
].join('\n');
const e = mockEmitters['/fruits'];
e.emit('all', 'change', 'pear.js', '/fruits', MOCK_STAT);
e.emit('all', 'add', 'blueberry.js', '/fruits', MOCK_STAT);
e.emit('all', 'change', 'pear.js', '/fruits', MOCK_STAT_FILE);
e.emit('all', 'add', 'blueberry.js', '/fruits', MOCK_STAT_FILE);
const {hasteFS, moduleMap} = await waitForItToChange(hm);
expect(hasteFS.exists('/fruits/blueberry.js')).toBe(true);
try {
Expand Down Expand Up @@ -1215,7 +1241,7 @@ describe('HasteMap', () => {
' */',
].join('\n');
const e = mockEmitters['/fruits'];
e.emit('all', 'change', 'pear.js', '/fruits', MOCK_STAT);
e.emit('all', 'change', 'pear.js', '/fruits', MOCK_STAT_FILE);
const {moduleMap} = await waitForItToChange(hm);
expect(moduleMap.getModule('Pear')).toBe('/fruits/blueberry.js');
expect(moduleMap.getModule('OldPear')).toBe('/fruits/pear.js');
Expand All @@ -1231,11 +1257,25 @@ describe('HasteMap', () => {
' */',
].join('\n');
const e = mockEmitters['/fruits'];
e.emit('all', 'change', 'blueberry.js', '/fruits', MOCK_STAT);
e.emit('all', 'change', 'blueberry.js', '/fruits', MOCK_STAT_FILE);
const {moduleMap} = await waitForItToChange(hm);
expect(moduleMap.getModule('Pear')).toBe('/fruits/pear.js');
expect(moduleMap.getModule('Blueberry')).toBe('/fruits/blueberry.js');
});

hm_it('ignore directories', async hm => {
const e = mockEmitters['/fruits'];
e.emit('all', 'change', 'tomato.js', '/fruits', MOCK_STAT_FOLDER);
e.emit(
'all',
'change',
'tomato.js',
'/fruits/tomato.js/index.js',
MOCK_STAT_FILE,
);
const {eventsQueue} = await waitForItToChange(hm);
expect(eventsQueue).toHaveLength(1);
});
});
});
});
9 changes: 8 additions & 1 deletion packages/jest-haste-map/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import {version as VERSION} from '../package.json';
import {getSha1, worker} from './worker';
import crypto from 'crypto';
import EventEmitter from 'events';
import fs from 'fs';
import getMockName from './get_mock_name';
import getPlatformExtension from './lib/get_platform_extension';
import H from './constants';
import HasteFS from './haste_fs';
import HasteModuleMap from './module_map';
import invariant from 'invariant';
// eslint-disable-next-line import/default
import nodeCrawl from './crawlers/node';
import normalizePathSep from './lib/normalize_path_sep';
Expand Down Expand Up @@ -719,10 +721,11 @@ class HasteMap extends EventEmitter {
type: string,
filePath: Path,
root: Path,
stat: {mtime: Date},
stat: ?fs.Stats,
) => {
filePath = path.join(root, normalizePathSep(filePath));
if (
(stat && stat.isDirectory()) ||
this._ignore(filePath) ||
!extensions.some(extension => filePath.endsWith(extension))
) {
Expand Down Expand Up @@ -792,6 +795,10 @@ class HasteMap extends EventEmitter {
// If the file was added or changed,
// parse it and update the haste map.
if (type === 'add' || type === 'change') {
invariant(
stat,
'since the file exists or changed, it should have stats',
);
const fileMetadata = ['', stat.mtime.getTime(), 0, [], null];
hasteMap.files[filePath] = fileMetadata;
const promise = this._processFile(
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5495,7 +5495,7 @@ interpret@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"

invariant@^2.2.0, invariant@^2.2.2:
invariant@^2.2.0, invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
dependencies:
Expand Down

0 comments on commit ede0fe3

Please sign in to comment.