Skip to content

Commit 2d0496b

Browse files
IanVSSimenB
andauthored
[jest-resolve] Add async resolver support (#11540)
Co-authored-by: Simen Bekkhus <[email protected]>
1 parent eafc350 commit 2d0496b

File tree

21 files changed

+872
-110
lines changed

21 files changed

+872
-110
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- `[jest-mock]` Improve `isMockFunction` to infer types of passed function ([#12442](https://github.com/facebook/jest/pull/12442))
1717
- `[jest-resolve]` [**BREAKING**] Add support for `package.json` `exports` ([#11961](https://github.com/facebook/jest/pull/11961), [#12373](https://github.com/facebook/jest/pull/12373))
1818
- `[jest-resolve, jest-runtime]` Add support for `data:` URI import and mock ([#12392](https://github.com/facebook/jest/pull/12392))
19+
- `[jest-resolve, jest-runtime]` Add support for async resolver ([#11540](https://github.com/facebook/jest/pull/11540))
1920
- `[@jest/schemas]` New module for JSON schemas for Jest's config ([#12384](https://github.com/facebook/jest/pull/12384))
2021
- `[jest-worker]` [**BREAKING**] Allow only absolute `workerPath` ([#12343](https://github.com/facebook/jest/pull/12343))
2122
- `[pretty-format]` New `maxWidth` parameter ([#12402](https://github.com/facebook/jest/pull/12402))

docs/Configuration.md

+8-5
Original file line numberDiff line numberDiff line change
@@ -779,13 +779,18 @@ By default, each test file gets its own independent module registry. Enabling `r
779779

780780
Default: `undefined`
781781

782-
This option allows the use of a custom resolver. This resolver must be a node module that exports a function expecting a string as the first argument for the path to resolve and an object with the following structure as the second argument:
782+
This option allows the use of a custom resolver. This resolver must be a node module that exports _either_:
783+
784+
1. a function expecting a string as the first argument for the path to resolve and an options object as the second argument. The function should either return a path to the module that should be resolved or throw an error if the module can't be found. _or_
785+
2. an object containing `async` and/or `sync` properties. The `sync` property should be a function with the shape explained above, and the `async` property should also be a function that accepts the same arguments, but returns a promise which resolves with the path to the module or rejects with an error.
786+
787+
The options object provided to resolvers has the shape:
783788

784789
```json
785790
{
786791
"basedir": string,
787792
"conditions": [string],
788-
"defaultResolver": "function(request, options)",
793+
"defaultResolver": "function(request, options) -> string",
789794
"extensions": [string],
790795
"moduleDirectory": [string],
791796
"paths": [string],
@@ -795,9 +800,7 @@ This option allows the use of a custom resolver. This resolver must be a node mo
795800
}
796801
```
797802

798-
The function should either return a path to the module that should be resolved or throw an error if the module can't be found.
799-
800-
Note: the defaultResolver passed as an option is the Jest default resolver which might be useful when you write your custom one. It takes the same arguments as your custom one, e.g. `(request, options)`.
803+
Note: the `defaultResolver` passed as an option is the Jest default resolver which might be useful when you write your custom one. It takes the same arguments as your custom synchronous one, e.g. `(request, options)` and returns a string or throws.
801804

802805
For example, if you want to respect Browserify's [`"browser"` field](https://github.com/browserify/browserify-handbook/blob/master/readme.markdown#browser-field), you can use the following configuration:
803806

e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ exports[`moduleNameMapper wrong array configuration 1`] = `
4141
12 | module.exports = () => 'test';
4242
13 |
4343
44-
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/resolver.js:572:17)
44+
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/resolver.js:897:17)
4545
at Object.require (index.js:10:1)"
4646
`;
4747

@@ -70,6 +70,6 @@ exports[`moduleNameMapper wrong configuration 1`] = `
7070
12 | module.exports = () => 'test';
7171
13 |
7272
73-
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/resolver.js:572:17)
73+
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/resolver.js:897:17)
7474
at Object.require (index.js:10:1)"
7575
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`on node >=12.16.0 runs test with native ESM 1`] = `
4+
"Test Suites: 1 passed, 1 total
5+
Tests: 1 passed, 1 total
6+
Snapshots: 0 total
7+
Time: <<REPLACED>>
8+
Ran all test suites."
9+
`;

e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ exports[`show error message with matching files 1`] = `
3737
| ^
3838
9 |
3939
40-
at Resolver.resolveModule (../../packages/jest-resolve/build/resolver.js:317:11)
40+
at Resolver._throwModNotFoundError (../../packages/jest-resolve/build/resolver.js:491:11)
4141
at Object.require (index.js:8:18)"
4242
`;

e2e/__tests__/resolveAsync.test.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import {onNodeVersions} from '@jest/test-utils';
9+
import {extractSummary} from '../Utils';
10+
import runJest from '../runJest';
11+
12+
// The versions where vm.Module exists and commonjs with "exports" is not broken
13+
onNodeVersions('>=12.16.0', () => {
14+
test('runs test with native ESM', () => {
15+
const {exitCode, stderr, stdout} = runJest('resolve-async', [], {
16+
nodeOptions: '--experimental-vm-modules --no-warnings',
17+
});
18+
19+
const {summary} = extractSummary(stderr);
20+
21+
expect(summary).toMatchSnapshot();
22+
expect(stdout).toBe('');
23+
expect(exitCode).toBe(0);
24+
});
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import greeting from '../some-file';
9+
10+
test('async resolver resolves to correct file', () => {
11+
expect(greeting).toEqual('Hello from mapped file!!');
12+
});

e2e/resolve-async/package.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"type": "module",
3+
"jest": {
4+
"resolver": "<rootDir>/resolver.cjs",
5+
"transform": {
6+
}
7+
}
8+
}

e2e/resolve-async/resolver.cjs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
'use strict';
9+
10+
const {promisify} = require('util');
11+
12+
const wait = promisify(setTimeout);
13+
14+
module.exports = {
15+
async: async (request, opts) => {
16+
await wait(500);
17+
18+
if (request === '../some-file') {
19+
request = '../some-other-file';
20+
}
21+
22+
return opts.defaultResolver(request, opts);
23+
},
24+
};

e2e/resolve-async/some-other-file.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
export default 'Hello from mapped file!!';

e2e/resolve-get-paths/__tests__/resolveGetPaths.test.js

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*/
7-
'use strict';
87

98
import {resolve} from 'path';
109

e2e/resolve-with-paths/__tests__/resolveWithPaths.test.js

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*/
7-
'use strict';
87

98
import {resolve} from 'path';
109

packages/jest-resolve/src/__mocks__/conditions/node_modules/exports/package.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"name": "__mocks__",
33
"version": "1.0.0",
4-
"dependencies": {
5-
}
4+
"dependencies": {}
65
}

packages/jest-resolve/src/__mocks__/userResolver.d.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,8 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import defaultResolver from '../defaultResolver';
8+
import type {Resolver} from '../defaultResolver';
99

10-
// todo: can be replaced with jest.MockedFunction
11-
declare const userResolver: jest.MockInstance<
12-
ReturnType<typeof defaultResolver>,
13-
Parameters<typeof defaultResolver>
14-
>;
10+
declare const userResolver: Resolver;
1511

1612
export default userResolver;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import type {Resolver} from '../defaultResolver';
9+
10+
// todo: can be replaced with jest.MockedFunction
11+
declare const userResolver: Resolver;
12+
13+
export default userResolver;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
'use strict';
9+
10+
module.exports = {
11+
async: function userResolver(path, options) {
12+
return Promise.resolve('module');
13+
},
14+
};

0 commit comments

Comments
 (0)