Skip to content

Commit 4954f46

Browse files
authored
Implements a mapper option (#6940)
* Implements a mapper option * Updates changelog * Fixes linting * Makes the mapper optional typewise * Fixes tests * Adds the plumbing to set the value from the options * Updates the error message * Linting * Fixes things
1 parent 1615a2d commit 4954f46

6 files changed

Lines changed: 83 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090

9191
- `[jest-cli]` Add `changedSince` to allowed watch mode configs ([#6955](https://github.com/facebook/jest/pull/6955))
9292
- `[babel-jest]` Add support for `babel.config.js` added in Babel 7.0.0 ([#6911](https://github.com/facebook/jest/pull/6911))
93+
- `[jest-resolve]` Add support for an experimental `mapper` option (Watchman crawler only) that adds virtual files to the Haste map ([#6940](https://github.com/facebook/jest/pull/6940))
9394

9495
### Fixes
9596

packages/jest-haste-map/src/crawlers/__tests__/watchman.test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ const STRAWBERRY_RELATIVE = path.join(FRUITS_RELATIVE, 'strawberry.js');
4444
const KIWI_RELATIVE = path.join(FRUITS_RELATIVE, 'kiwi.js');
4545
const TOMATO_RELATIVE = path.join(FRUITS_RELATIVE, 'tomato.js');
4646
const MELON_RELATIVE = path.join(VEGETABLES_RELATIVE, 'melon.json');
47+
const DURIAN_RELATIVE = path.join(VEGETABLES_RELATIVE, 'durian.zip');
48+
4749
const WATCH_PROJECT_MOCK = {
4850
[FRUITS]: {
4951
relative_path: 'fruits',
@@ -164,6 +166,53 @@ describe('watchman watch', () => {
164166
expect(client.end).toBeCalled();
165167
}));
166168

169+
test('applies the mapper when needed', () => {
170+
mockResponse = {
171+
'list-capabilities': {
172+
[undefined]: {
173+
capabilities: ['field-content.sha1hex'],
174+
},
175+
},
176+
query: {
177+
[ROOT_MOCK]: {
178+
clock: 'c:fake-clock:1',
179+
files: [
180+
{
181+
exists: true,
182+
mtime_ms: {toNumber: () => 33},
183+
name: 'vegetables/durian.zip',
184+
},
185+
],
186+
is_fresh_instance: true,
187+
version: '4.5.0',
188+
},
189+
},
190+
'watch-project': WATCH_PROJECT_MOCK,
191+
};
192+
193+
return watchmanCrawl({
194+
data: {
195+
clocks: new Map(),
196+
files: new Map(),
197+
},
198+
extensions: ['js', 'json', 'zip'],
199+
ignore: pearMatcher,
200+
mapper: n =>
201+
n.endsWith('.zip')
202+
? [path.join(n, 'foo.1.js'), path.join(n, 'foo.2.js')]
203+
: null,
204+
rootDir: ROOT_MOCK,
205+
roots: ROOTS,
206+
}).then(data => {
207+
expect(data.files).toEqual(
208+
createMap({
209+
[path.join(DURIAN_RELATIVE, 'foo.1.js')]: ['', 33, 0, [], null],
210+
[path.join(DURIAN_RELATIVE, 'foo.2.js')]: ['', 33, 0, [], null],
211+
}),
212+
);
213+
});
214+
});
215+
167216
test('updates the file object when the clock is given', () => {
168217
mockResponse = {
169218
'list-capabilities': {

packages/jest-haste-map/src/crawlers/node.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ function findNative(
128128
module.exports = function nodeCrawl(
129129
options: CrawlerOptions,
130130
): Promise<InternalHasteMap> {
131+
if (options.mapper) {
132+
throw new Error(`Option 'mapper' isn't supported by the Node crawler`);
133+
}
134+
131135
const {
132136
data,
133137
extensions,

packages/jest-haste-map/src/crawlers/watchman.js

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -175,29 +175,43 @@ module.exports = async function watchmanCrawl(
175175
typeof fileData.mtime_ms === 'number'
176176
? fileData.mtime_ms
177177
: fileData.mtime_ms.toNumber();
178+
178179
let sha1hex = fileData['content.sha1hex'];
179180
if (typeof sha1hex !== 'string' || sha1hex.length !== 40) {
180181
sha1hex = null;
181182
}
182183

183184
const existingFileData = data.files.get(relativeFilePath);
185+
let nextData;
186+
184187
if (existingFileData && existingFileData[H.MTIME] === mtime) {
185-
files.set(relativeFilePath, existingFileData);
188+
nextData = existingFileData;
186189
} else if (
187190
existingFileData &&
188191
sha1hex &&
189192
existingFileData[H.SHA1] === sha1hex
190193
) {
191-
files.set(relativeFilePath, [
192-
existingFileData[0],
193-
mtime,
194-
existingFileData[2],
195-
existingFileData[3],
196-
existingFileData[4],
197-
]);
194+
nextData = [...existingFileData];
195+
nextData[1] = mtime;
198196
} else {
199197
// See ../constants.js
200-
files.set(relativeFilePath, ['', mtime, 0, [], sha1hex]);
198+
nextData = ['', mtime, 0, [], sha1hex];
199+
}
200+
201+
const mappings = options.mapper ? options.mapper(filePath) : null;
202+
203+
if (mappings) {
204+
for (const absoluteVirtualFilePath of mappings) {
205+
if (!ignore(absoluteVirtualFilePath)) {
206+
const relativeVirtualFilePath = fastPath.relative(
207+
rootDir,
208+
absoluteVirtualFilePath,
209+
);
210+
files.set(relativeVirtualFilePath, nextData);
211+
}
212+
}
213+
} else {
214+
files.set(relativeFilePath, nextData);
201215
}
202216
}
203217
}

packages/jest-haste-map/src/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import * as fastPath from './lib/fast_path';
3333
import Worker from 'jest-worker';
3434

3535
import type {Console} from 'console';
36+
import type {Mapper} from './types';
3637
import type {Path} from 'types/Config';
3738
import type {
3839
HasteMap as HasteMapObject,
@@ -55,6 +56,7 @@ type Options = {
5556
forceNodeFilesystemAPI?: boolean,
5657
hasteImplModulePath?: string,
5758
ignorePattern?: ?HasteRegExp,
59+
mapper?: ?Mapper,
5860
maxWorkers: number,
5961
mocksPattern?: string,
6062
name: string,
@@ -77,6 +79,7 @@ type InternalOptions = {
7779
forceNodeFilesystemAPI: boolean,
7880
hasteImplModulePath?: string,
7981
ignorePattern: ?HasteRegExp,
82+
mapper?: ?Mapper,
8083
maxWorkers: number,
8184
mocksPattern: ?RegExp,
8285
name: string,
@@ -671,6 +674,7 @@ class HasteMap extends EventEmitter {
671674
extensions: options.extensions,
672675
forceNodeFilesystemAPI: options.forceNodeFilesystemAPI,
673676
ignore,
677+
mapper: options.mapper,
674678
rootDir: options.rootDir,
675679
roots: options.roots,
676680
}).catch(e => {

packages/jest-haste-map/src/types.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import type {InternalHasteMap, ModuleMetaData} from 'types/HasteMap';
1111

1212
export type IgnoreMatcher = (item: string) => boolean;
13+
export type Mapper = (item: string) => ?Array<string>;
1314

1415
export type WorkerMessage = {
1516
computeDependencies: boolean,
@@ -32,6 +33,7 @@ export type CrawlerOptions = {|
3233
extensions: Array<string>,
3334
forceNodeFilesystemAPI: boolean,
3435
ignore: IgnoreMatcher,
36+
mapper?: ?Mapper,
3537
rootDir: string,
3638
roots: Array<string>,
3739
|};

0 commit comments

Comments
 (0)