GeezerVison is showing github.com — test_runner: refactor `mock_loader` · nodejs/node@0cf78aa
File treeExpand file treeCollapse file tree Open diff view settings lib/internal/test_runner/mock
Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/test_runner/mock/loader.js +8-40Lines changed: 8 additions & 40 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -10,21 +10,16 @@ const { | 10 | 10 | }, | 11 | 11 | } = primordials; | 12 | 12 | const { | 13 | | - ensureNodeScheme, | 14 | 13 | kBadExportsMessage, | 15 | 14 | kMockSearchParam, | 16 | 15 | kMockSuccess, | 17 | 16 | kMockExists, | 18 | 17 | kMockUnknownMessage, | 19 | 18 | } = 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'); | 22 | 20 | let debug = require('internal/util/debuglog').debuglog('test_runner', (fn) => { | 23 | 21 | debug = fn; | 24 | 22 | }); | 25 | | -const { createRequire, isBuiltin } = require('module'); | 26 | | -const { defaultGetFormatWithoutErrors } = require('internal/modules/esm/get_format'); | 27 | | -const { defaultResolve } = require('internal/modules/esm/resolve'); | 28 | 23 |
| 29 | 24 | // TODO(cjihrig): The mocks need to be thread aware because the exports are | 30 | 25 | // evaluated on the thread that creates the mock. Before marking this API as | @@ -79,46 +74,18 @@ async function initialize(data) { | 79 | 74 |
| 80 | 75 | async function resolve(specifier, context, nextResolve) { | 81 | 76 | debug('resolve hook entry, specifier = "%s", context = %o', specifier, context); | 82 | | - let mockSpecifier; | 83 | 77 |
| 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; | 112 | 80 |
| 113 | 81 | const mock = mocks.get(mockSpecifier); | 114 | 82 | debug('resolve hook, specifier = "%s", mock = %o', specifier, mock); | 115 | 83 |
| 116 | 84 | if (mock?.active !== true) { | 117 | | - return nextResolve(specifier, context); | | 85 | + return nextResolveResult; | 118 | 86 | } | 119 | 87 |
| 120 | 88 | const url = new URL(mockSpecifier); | 121 | | - | 122 | 89 | url.searchParams.set(kMockSearchParam, mock.localVersion); | 123 | 90 |
| 124 | 91 | if (!mock.cache) { | @@ -127,13 +94,14 @@ async function resolve(specifier, context, nextResolve) { | 127 | 94 | mock.localVersion++; | 128 | 95 | } | 129 | 96 |
| 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 }; | 132 | 100 | } | 133 | 101 |
| 134 | 102 | async function load(url, context, nextLoad) { | 135 | 103 | debug('load hook entry, url = "%s", context = %o', url, context); | 136 | | - const parsedURL = URL.parse(url); | | 104 | + const parsedURL = URLParse(url); | 137 | 105 | if (parsedURL) { | 138 | 106 | parsedURL.searchParams.delete(kMockSearchParam); | 139 | 107 | } | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/test_runner/mock/mock.js +8-2Lines changed: 8 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -34,7 +34,13 @@ const { | 34 | 34 | } = require('internal/errors'); | 35 | 35 | const esmLoader = require('internal/modules/esm/loader'); | 36 | 36 | 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'); | 38 | 44 | const { | 39 | 45 | emitExperimentalWarning, | 40 | 46 | getStructuredStack, | @@ -511,7 +517,7 @@ class MockTracker { | 511 | 517 |
| 512 | 518 | // Get the file that called this function. We need four stack frames: | 513 | 519 | // vm context -> getStructuredStack() -> this function -> actual caller. | 514 | | - const caller = getStructuredStack()[3]?.getFileName(); | | 520 | + const caller = pathToFileURL(getStructuredStack()[3]?.getFileName()).href; | 515 | 521 | const { format, url } = sharedState.moduleLoader.resolveSync( | 516 | 522 | mockSpecifier, caller, null, | 517 | 523 | ); | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-runner-module-mocking.js +6Lines changed: 6 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -407,6 +407,12 @@ test('modules cannot be mocked multiple times at once', async (t) => { | 407 | 407 |
| 408 | 408 | assert.strictEqual(mocked.fn(), 42); | 409 | 409 | }); | | 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 | + }); | 410 | 416 | }); | 411 | 417 |
| 412 | 418 | test('mocks are automatically restored', async (t) => { | |
|