Skip to content

Commit 1bd7a2e

Browse files
JakobJingleheimeraduh95
authored andcommitted
test_runner: support mocking json modules
PR-URL: #58007 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Pietro Marchini <[email protected]> Reviewed-By: Marco Ippolito <[email protected]> Reviewed-By: Chemi Atlow <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent ffe7e1a commit 1bd7a2e

File tree

5 files changed

+57
-9
lines changed

5 files changed

+57
-9
lines changed

doc/api/test.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,6 +2108,11 @@ test('spies on an object method', (t) => {
21082108

21092109
<!-- YAML
21102110
added: v22.3.0
2111+
changes:
2112+
- version:
2113+
- REPLACEME
2114+
pr-url: https://github.com/nodejs/node/pull/58007
2115+
description: Support JSON modules.
21112116
-->
21122117

21132118
> Stability: 1.0 - Early development
@@ -2131,10 +2136,10 @@ added: v22.3.0
21312136
mock will throw an exception when used as a CJS or builtin module.
21322137
* Returns: {MockModuleContext} An object that can be used to manipulate the mock.
21332138

2134-
This function is used to mock the exports of ECMAScript modules, CommonJS
2135-
modules, and Node.js builtin modules. Any references to the original module
2136-
prior to mocking are not impacted. In order to enable module mocking, Node.js must
2137-
be started with the [`--experimental-test-module-mocks`][] command-line flag.
2139+
This function is used to mock the exports of ECMAScript modules, CommonJS modules, JSON modules, and
2140+
Node.js builtin modules. Any references to the original module prior to mocking are not impacted. In
2141+
order to enable module mocking, Node.js must be started with the
2142+
[`--experimental-test-module-mocks`][] command-line flag.
21382143

21392144
The following example demonstrates how a mock is created for a module.
21402145

lib/internal/test_runner/mock/loader.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,17 @@ async function load(url, context, nextLoad) {
118118
// Treat builtins as commonjs because customization hooks do not allow a
119119
// core module to be replaced.
120120
// Also collapse 'commonjs-sync' and 'require-commonjs' to 'commonjs'.
121-
const format = (
122-
original.format === 'builtin' ||
123-
original.format === 'commonjs-sync' ||
124-
original.format === 'require-commonjs') ? 'commonjs' : original.format;
121+
let format = original.format;
122+
switch (original.format) {
123+
case 'builtin': // Deliberate fallthrough
124+
case 'commonjs-sync': // Deliberate fallthrough
125+
case 'require-commonjs':
126+
format = 'commonjs';
127+
break;
128+
case 'json':
129+
format = 'module';
130+
break;
131+
}
125132

126133
const result = {
127134
__proto__: null,

lib/internal/test_runner/mock/mock.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,14 @@ const kMockUnknownMessage = 3;
7070
const kWaitTimeout = 5_000;
7171
const kBadExportsMessage = 'Cannot create mock because named exports ' +
7272
'cannot be applied to the provided default export.';
73-
const kSupportedFormats = ['builtin', 'commonjs', 'module', 'module-typescript', 'commonjs-typescript'];
73+
const kSupportedFormats = [
74+
'builtin',
75+
'commonjs-typescript',
76+
'commonjs',
77+
'json',
78+
'module-typescript',
79+
'module',
80+
];
7481
let sharedModuleState;
7582

7683
class MockFunctionContext {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"foo":"bar"}

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,34 @@ test('ESM mocking with namedExports option', async (t) => {
365365
});
366366
});
367367

368+
test('JSON mocking', async (t) => {
369+
await t.test('with defaultExport', async (t) => {
370+
const fixturePath = fixtures.path('module-mocking', 'basic.json');
371+
const fixture = pathToFileURL(fixturePath);
372+
const { default: original } = await import(fixture, { with: { type: 'json' } });
373+
374+
assert.deepStrictEqual(original, { foo: 'bar' });
375+
376+
const defaultExport = { qux: 'zed' };
377+
378+
t.mock.module(fixture, { defaultExport });
379+
380+
const { default: mocked } = await import(fixture, { with: { type: 'json' } });
381+
382+
assert.deepStrictEqual(mocked, defaultExport);
383+
});
384+
385+
await t.test('throws without appropriate import attributes', async (t) => {
386+
const fixturePath = fixtures.path('module-mocking', 'basic.json');
387+
const fixture = pathToFileURL(fixturePath);
388+
389+
const defaultExport = { qux: 'zed' };
390+
t.mock.module(fixture, { defaultExport });
391+
392+
await assert.rejects(() => import(fixture), /import attribute/);
393+
});
394+
});
395+
368396
test('modules cannot be mocked multiple times at once', async (t) => {
369397
await t.test('CJS', async (t) => {
370398
const fixture = fixtures.path('module-mocking', 'basic-cjs.js');

0 commit comments

Comments
 (0)