GeezerVison is showing github.com — test_runner: support mocking json modules · nodejs/node@99e4685
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: doc/api/test.md +9-4Lines changed: 9 additions & 4 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -2168,6 +2168,11 @@ test('spies on an object method', (t) => { | 2168 | 2168 | added: | 2169 | 2169 | - v22.3.0 | 2170 | 2170 | - v20.18.0 | | 2171 | +changes: | | 2172 | + - version: | | 2173 | + - REPLACEME | | 2174 | + pr-url: https://github.com/nodejs/node/pull/58007 | | 2175 | + description: Support JSON modules. | 2171 | 2176 | --> | 2172 | 2177 |
| 2173 | 2178 | > Stability: 1.0 - Early development | @@ -2191,10 +2196,10 @@ added: | 2191 | 2196 | mock will throw an exception when used as a CJS or builtin module. | 2192 | 2197 | * Returns: {MockModuleContext} An object that can be used to manipulate the mock. | 2193 | 2198 |
| 2194 | | -This function is used to mock the exports of ECMAScript modules, CommonJS | 2195 | | -modules, and Node.js builtin modules. Any references to the original module | 2196 | | -prior to mocking are not impacted. In order to enable module mocking, Node.js must | 2197 | | -be started with the [`--experimental-test-module-mocks`][] command-line flag. | | 2199 | +This function is used to mock the exports of ECMAScript modules, CommonJS modules, JSON modules, and | | 2200 | +Node.js builtin modules. Any references to the original module prior to mocking are not impacted. In | | 2201 | +order to enable module mocking, Node.js must be started with the | | 2202 | +[`--experimental-test-module-mocks`][] command-line flag. | 2198 | 2203 |
| 2199 | 2204 | The following example demonstrates how a mock is created for a module. | 2200 | 2205 |
| |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/test_runner/mock/loader.js +11-4Lines changed: 11 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -118,10 +118,17 @@ async function load(url, context, nextLoad) { | 118 | 118 | // Treat builtins as commonjs because customization hooks do not allow a | 119 | 119 | // core module to be replaced. | 120 | 120 | // 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 | + } | 125 | 132 |
| 126 | 133 | const result = { | 127 | 134 | __proto__: null, | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/test_runner/mock/mock.js +8-1Lines changed: 8 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -70,7 +70,14 @@ const kMockUnknownMessage = 3; | 70 | 70 | const kWaitTimeout = 5_000; | 71 | 71 | const kBadExportsMessage = 'Cannot create mock because named exports ' + | 72 | 72 | '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 | +]; | 74 | 81 | let sharedModuleState; | 75 | 82 |
| 76 | 83 | class MockFunctionContext { | |
Collapse file Copy file name to clipboard +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +{"foo":"bar"} |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-runner-module-mocking.js +28Lines changed: 28 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -365,6 +365,34 @@ test('ESM mocking with namedExports option', async (t) => { | 365 | 365 | }); | 366 | 366 | }); | 367 | 367 |
| | 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 | + | 368 | 396 | test('modules cannot be mocked multiple times at once', async (t) => { | 369 | 397 | await t.test('CJS', async (t) => { | 370 | 398 | const fixture = fixtures.path('module-mocking', 'basic-cjs.js'); | |
|