test_runner: support mocking json modules

PR-URL: https://github.com/nodejs/node/pull/58007
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
Jacob Smith 2025-04-26 16:56:24 +02:00 committed by Antoine du Hamel
parent ffe7e1ace0
commit 1bd7a2edf9
No known key found for this signature in database
GPG Key ID: 21D900FFDB233756
5 changed files with 57 additions and 9 deletions

View File

@ -2108,6 +2108,11 @@ test('spies on an object method', (t) => {
<!-- YAML
added: v22.3.0
changes:
- version:
- REPLACEME
pr-url: https://github.com/nodejs/node/pull/58007
description: Support JSON modules.
-->
> Stability: 1.0 - Early development
@ -2131,10 +2136,10 @@ added: v22.3.0
mock will throw an exception when used as a CJS or builtin module.
* Returns: {MockModuleContext} An object that can be used to manipulate the mock.
This function is used to mock the exports of ECMAScript modules, CommonJS
modules, and Node.js builtin modules. Any references to the original module
prior to mocking are not impacted. In order to enable module mocking, Node.js must
be started with the [`--experimental-test-module-mocks`][] command-line flag.
This function is used to mock the exports of ECMAScript modules, CommonJS modules, JSON modules, and
Node.js builtin modules. Any references to the original module prior to mocking are not impacted. In
order to enable module mocking, Node.js must be started with the
[`--experimental-test-module-mocks`][] command-line flag.
The following example demonstrates how a mock is created for a module.

View File

@ -118,10 +118,17 @@ async function load(url, context, nextLoad) {
// Treat builtins as commonjs because customization hooks do not allow a
// core module to be replaced.
// Also collapse 'commonjs-sync' and 'require-commonjs' to 'commonjs'.
const format = (
original.format === 'builtin' ||
original.format === 'commonjs-sync' ||
original.format === 'require-commonjs') ? 'commonjs' : original.format;
let format = original.format;
switch (original.format) {
case 'builtin': // Deliberate fallthrough
case 'commonjs-sync': // Deliberate fallthrough
case 'require-commonjs':
format = 'commonjs';
break;
case 'json':
format = 'module';
break;
}
const result = {
__proto__: null,

View File

@ -70,7 +70,14 @@ const kMockUnknownMessage = 3;
const kWaitTimeout = 5_000;
const kBadExportsMessage = 'Cannot create mock because named exports ' +
'cannot be applied to the provided default export.';
const kSupportedFormats = ['builtin', 'commonjs', 'module', 'module-typescript', 'commonjs-typescript'];
const kSupportedFormats = [
'builtin',
'commonjs-typescript',
'commonjs',
'json',
'module-typescript',
'module',
];
let sharedModuleState;
class MockFunctionContext {

View File

@ -0,0 +1 @@
{"foo":"bar"}

View File

@ -365,6 +365,34 @@ test('ESM mocking with namedExports option', async (t) => {
});
});
test('JSON mocking', async (t) => {
await t.test('with defaultExport', async (t) => {
const fixturePath = fixtures.path('module-mocking', 'basic.json');
const fixture = pathToFileURL(fixturePath);
const { default: original } = await import(fixture, { with: { type: 'json' } });
assert.deepStrictEqual(original, { foo: 'bar' });
const defaultExport = { qux: 'zed' };
t.mock.module(fixture, { defaultExport });
const { default: mocked } = await import(fixture, { with: { type: 'json' } });
assert.deepStrictEqual(mocked, defaultExport);
});
await t.test('throws without appropriate import attributes', async (t) => {
const fixturePath = fixtures.path('module-mocking', 'basic.json');
const fixture = pathToFileURL(fixturePath);
const defaultExport = { qux: 'zed' };
t.mock.module(fixture, { defaultExport });
await assert.rejects(() => import(fixture), /import attribute/);
});
});
test('modules cannot be mocked multiple times at once', async (t) => {
await t.test('CJS', async (t) => {
const fixture = fixtures.path('module-mocking', 'basic-cjs.js');