Skip to content

Commit 0cf78aa

Browse files
aduh95RafaelGSS
authored andcommitted
test_runner: refactor mock_loader
PR-URL: #54223 Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Chemi Atlow <[email protected]> Reviewed-By: Moshe Atlow <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent a5ce241 commit 0cf78aa

File tree

3 files changed

+22
-42
lines changed

3 files changed

+22
-42
lines changed

lib/internal/test_runner/mock/loader.js

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,16 @@ const {
1010
},
1111
} = primordials;
1212
const {
13-
ensureNodeScheme,
1413
kBadExportsMessage,
1514
kMockSearchParam,
1615
kMockSuccess,
1716
kMockExists,
1817
kMockUnknownMessage,
1918
} = require('internal/test_runner/mock/mock');
20-
const { pathToFileURL, URL } = require('internal/url');
21-
const { normalizeReferrerURL } = require('internal/modules/helpers');
19+
const { URL, URLParse } = require('internal/url');
2220
let debug = require('internal/util/debuglog').debuglog('test_runner', (fn) => {
2321
debug = fn;
2422
});
25-
const { createRequire, isBuiltin } = require('module');
26-
const { defaultGetFormatWithoutErrors } = require('internal/modules/esm/get_format');
27-
const { defaultResolve } = require('internal/modules/esm/resolve');
2823

2924
// TODO(cjihrig): The mocks need to be thread aware because the exports are
3025
// evaluated on the thread that creates the mock. Before marking this API as
@@ -79,46 +74,18 @@ async function initialize(data) {
7974

8075
async function resolve(specifier, context, nextResolve) {
8176
debug('resolve hook entry, specifier = "%s", context = %o', specifier, context);
82-
let mockSpecifier;
8377

84-
if (isBuiltin(specifier)) {
85-
mockSpecifier = ensureNodeScheme(specifier);
86-
} else {
87-
let format;
88-
89-
if (context.parentURL) {
90-
format = defaultGetFormatWithoutErrors(pathToFileURL(context.parentURL));
91-
}
92-
93-
try {
94-
if (format === 'module') {
95-
specifier = defaultResolve(specifier, context).url;
96-
} else {
97-
specifier = pathToFileURL(
98-
createRequire(context.parentURL).resolve(specifier),
99-
).href;
100-
}
101-
} catch {
102-
const parentURL = normalizeReferrerURL(context.parentURL);
103-
const parsedURL = URL.parse(specifier, parentURL)?.href;
104-
105-
if (parsedURL) {
106-
specifier = parsedURL;
107-
}
108-
}
109-
110-
mockSpecifier = specifier;
111-
}
78+
const nextResolveResult = await nextResolve(specifier, context);
79+
const mockSpecifier = nextResolveResult.url;
11280

11381
const mock = mocks.get(mockSpecifier);
11482
debug('resolve hook, specifier = "%s", mock = %o', specifier, mock);
11583

11684
if (mock?.active !== true) {
117-
return nextResolve(specifier, context);
85+
return nextResolveResult;
11886
}
11987

12088
const url = new URL(mockSpecifier);
121-
12289
url.searchParams.set(kMockSearchParam, mock.localVersion);
12390

12491
if (!mock.cache) {
@@ -127,13 +94,14 @@ async function resolve(specifier, context, nextResolve) {
12794
mock.localVersion++;
12895
}
12996

130-
debug('resolve hook finished, url = "%s"', url.href);
131-
return nextResolve(url.href, context);
97+
const { href } = url;
98+
debug('resolve hook finished, url = "%s"', href);
99+
return { __proto__: null, url: href, format: nextResolveResult.format };
132100
}
133101

134102
async function load(url, context, nextLoad) {
135103
debug('load hook entry, url = "%s", context = %o', url, context);
136-
const parsedURL = URL.parse(url);
104+
const parsedURL = URLParse(url);
137105
if (parsedURL) {
138106
parsedURL.searchParams.delete(kMockSearchParam);
139107
}

lib/internal/test_runner/mock/mock.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@ const {
3434
} = require('internal/errors');
3535
const esmLoader = require('internal/modules/esm/loader');
3636
const { getOptionValue } = require('internal/options');
37-
const { fileURLToPath, toPathIfFileURL, URL, isURL } = require('internal/url');
37+
const {
38+
fileURLToPath,
39+
isURL,
40+
pathToFileURL,
41+
toPathIfFileURL,
42+
URL,
43+
} = require('internal/url');
3844
const {
3945
emitExperimentalWarning,
4046
getStructuredStack,
@@ -511,7 +517,7 @@ class MockTracker {
511517

512518
// Get the file that called this function. We need four stack frames:
513519
// vm context -> getStructuredStack() -> this function -> actual caller.
514-
const caller = getStructuredStack()[3]?.getFileName();
520+
const caller = pathToFileURL(getStructuredStack()[3]?.getFileName()).href;
515521
const { format, url } = sharedState.moduleLoader.resolveSync(
516522
mockSpecifier, caller, null,
517523
);

test/parallel/test-runner-module-mocking.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,12 @@ test('modules cannot be mocked multiple times at once', async (t) => {
407407

408408
assert.strictEqual(mocked.fn(), 42);
409409
});
410+
411+
await t.test('Importing a Windows path should fail', { skip: !common.isWindows }, async (t) => {
412+
const fixture = fixtures.path('module-mocking', 'wrong-path.js');
413+
t.mock.module(fixture, { namedExports: { fn() { return 42; } } });
414+
await assert.rejects(import(fixture), { code: 'ERR_UNSUPPORTED_ESM_URL_SCHEME' });
415+
});
410416
});
411417

412418
test('mocks are automatically restored', async (t) => {

0 commit comments

Comments
 (0)