Skip to content

Commit

Permalink
Allow Windows to use compatible native find binary
Browse files Browse the repository at this point in the history
Enable detection of a compatible find binary on Windows. Fix tests
so that they run and pass on Windows.
  • Loading branch information
richardlau committed Jul 24, 2020
1 parent b3b6cdd commit 6e1dd00
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 60 deletions.
3 changes: 2 additions & 1 deletion packages/jest-haste-map/package.json
Expand Up @@ -28,7 +28,8 @@
"@types/anymatch": "^1.3.1",
"@types/fb-watchman": "^2.0.0",
"@types/micromatch": "^4.0.0",
"@types/sane": "^2.0.0"
"@types/sane": "^2.0.0",
"slash": "^3.0.0"
},
"optionalDependencies": {
"fsevents": "^2.1.2"
Expand Down
75 changes: 17 additions & 58 deletions packages/jest-haste-map/src/crawlers/__tests__/node.test.js
Expand Up @@ -8,8 +8,6 @@

'use strict';

import {skipSuiteOnWindows} from '@jest/test-utils';

jest.mock('child_process', () => ({
spawn: jest.fn((cmd, args) => {
let closeCallback;
Expand Down Expand Up @@ -39,17 +37,18 @@ jest.mock('child_process', () => ({
let mockHasReaddirWithFileTypesSupport = false;

jest.mock('graceful-fs', () => {
const slash = require('slash');
let mtime = 32;
const size = 42;
const stat = (path, callback) => {
setTimeout(
() =>
callback(null, {
isDirectory() {
return path.endsWith('/directory');
return slash(path).endsWith('/directory');
},
isSymbolicLink() {
return path.endsWith('symlink');
return slash(path).endsWith('symlink');
},
mtime: {
getTime() {
Expand All @@ -75,7 +74,7 @@ jest.mock('graceful-fs', () => {
}

if (mockHasReaddirWithFileTypesSupport) {
if (dir === '/project/fruits') {
if (slash(dir) === '/project/fruits') {
setTimeout(
() =>
callback(null, [
Expand All @@ -97,7 +96,7 @@ jest.mock('graceful-fs', () => {
]),
0,
);
} else if (dir === '/project/fruits/directory') {
} else if (slash(dir) === '/project/fruits/directory') {
setTimeout(
() =>
callback(null, [
Expand All @@ -109,18 +108,18 @@ jest.mock('graceful-fs', () => {
]),
0,
);
} else if (dir == '/error') {
} else if (slash(dir) == '/error') {
setTimeout(() => callback({code: 'ENOTDIR'}, undefined), 0);
}
} else {
if (dir === '/project/fruits') {
if (slash(dir) === '/project/fruits') {
setTimeout(
() => callback(null, ['directory', 'tomato.js', 'symlink']),
0,
);
} else if (dir === '/project/fruits/directory') {
} else if (slash(dir) === '/project/fruits/directory') {
setTimeout(() => callback(null, ['strawberry.js']), 0);
} else if (dir == '/error') {
} else if (slash(dir) == '/error') {
setTimeout(() => callback({code: 'ENOTDIR'}, undefined), 0);
}
}
Expand All @@ -130,7 +129,10 @@ jest.mock('graceful-fs', () => {
});

const pearMatcher = path => /pear/.test(path);
const createMap = obj => new Map(Object.keys(obj).map(key => [key, obj[key]]));
const normalize = path =>
process.platform === 'win32' ? path.replace(/\//g, '\\') : path;
const createMap = obj =>
new Map(Object.keys(obj).map(key => [normalize(key), obj[key]]));

const rootDir = '/project';
let mockResponse;
Expand All @@ -139,14 +141,9 @@ let nodeCrawl;
let childProcess;

describe('node crawler', () => {
skipSuiteOnWindows();

beforeEach(() => {
jest.resetModules();

// Remove the "process.platform" property descriptor so it can be writable.
delete process.platform;

mockResponse = [
'/project/fruits/pear.js',
'/project/fruits/strawberry.js',
Expand All @@ -157,8 +154,6 @@ describe('node crawler', () => {
});

it('crawls for files based on patterns', () => {
process.platform = 'linux';

childProcess = require('child_process');
nodeCrawl = require('../node');

Expand Down Expand Up @@ -209,8 +204,6 @@ describe('node crawler', () => {
});

it('updates only changed files', () => {
process.platform = 'linux';

nodeCrawl = require('../node');

// In this test sample, strawberry is changed and tomato is unchanged
Expand All @@ -235,15 +228,13 @@ describe('node crawler', () => {
);

// Make sure it is the *same* unchanged object.
expect(hasteMap.files.get('fruits/tomato.js')).toBe(tomato);
expect(hasteMap.files.get(normalize('fruits/tomato.js'))).toBe(tomato);

expect(removedFiles).toEqual(new Map());
});
});

it('returns removed files', () => {
process.platform = 'linux';

nodeCrawl = require('../node');

// In this test sample, previouslyExisted was present before and will not be
Expand Down Expand Up @@ -275,32 +266,7 @@ describe('node crawler', () => {
});
});

it('uses node fs APIs on windows', () => {
process.platform = 'win32';

nodeCrawl = require('../node');

return nodeCrawl({
data: {
files: new Map(),
},
extensions: ['js'],
ignore: pearMatcher,
rootDir,
roots: ['/project/fruits'],
}).then(({hasteMap, removedFiles}) => {
expect(hasteMap.files).toEqual(
createMap({
'fruits/directory/strawberry.js': ['', 33, 42, 0, '', null],
'fruits/tomato.js': ['', 32, 42, 0, '', null],
}),
);
expect(removedFiles).toEqual(new Map());
});
});

it('uses node fs APIs on Unix based OS with incompatible find binary', () => {
process.platform = 'linux';
it('uses node fs APIs with incompatible find binary', () => {
mockResponse = '';
mockSpawnExit = 1;
childProcess = require('child_process');
Expand All @@ -327,9 +293,7 @@ describe('node crawler', () => {
});
});

it('uses node fs APIs on Unix based OS without find binary', () => {
process.platform = 'linux';

it('uses node fs APIs without find binary', () => {
childProcess = require('child_process');
childProcess.spawn.mockImplementationOnce(() => {
throw new Error();
Expand All @@ -356,8 +320,6 @@ describe('node crawler', () => {
});

it('uses node fs APIs if "forceNodeFilesystemAPI" is set to true, regardless of platform', () => {
process.platform = 'linux';

childProcess = require('child_process');
nodeCrawl = require('../node');

Expand All @@ -382,8 +344,6 @@ describe('node crawler', () => {
});

it('completes with empty roots', () => {
process.platform = 'win32';

nodeCrawl = require('../node');

const files = new Map();
Expand All @@ -401,14 +361,13 @@ describe('node crawler', () => {
});

it('completes with fs.readdir throwing an error', () => {
process.platform = 'win32';

nodeCrawl = require('../node');

const files = new Map();
return nodeCrawl({
data: {files},
extensions: ['js'],
forceNodeFilesystemAPI: true,
ignore: pearMatcher,
rootDir,
roots: ['/error'],
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-haste-map/src/crawlers/node.ts
Expand Up @@ -24,7 +24,7 @@ type Callback = (result: Result) => void;
async function hasNativeFindSupport(
forceNodeFilesystemAPI: boolean,
): Promise<boolean> {
if (forceNodeFilesystemAPI || process.platform === 'win32') {
if (forceNodeFilesystemAPI) {
return false;
}

Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Expand Up @@ -11217,6 +11217,7 @@ fsevents@^1.2.7:
jest-worker: ^26.1.0
micromatch: ^4.0.2
sane: ^4.0.3
slash: ^3.0.0
walker: ^1.0.7
dependenciesMeta:
fsevents:
Expand Down

0 comments on commit 6e1dd00

Please sign in to comment.