### ESM Import Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example showing the correct way to import esmock using ESM syntax. ```javascript // Must use ESM import import esmock from 'esmock' // βœ“ ESM import ``` -------------------------------- ### Hello World example Source: https://github.com/iambumblehead/esmock/wiki/Home A basic example demonstrating how to mock a module's dependency using esmock. ```javascript import test from 'node:test' import assert from 'node:assert/strict' import esmock from 'esmock' test('should mock hello world', async () => { const hello = await esmock('../src/hello.js', { '../src/icons': { world: '🌎' } }) assert.strictEqual(hello('world'), '🌎') }) ``` -------------------------------- ### Absolute Path Resolution Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example of resolving absolute paths when using esmock. ```javascript // Resolved as absolute file paths esmock('/absolute/path/to/module.js', {...}) ``` -------------------------------- ### Relative Path Resolution Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example of resolving relative paths when using esmock. ```javascript // Resolved relative to parent module esmock('../src/target.js', { './dep.js': {...} }) ``` -------------------------------- ### Package Name Resolution Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example of resolving package names from node_modules when using esmock. ```javascript // Resolved from node_modules via package.json exports esmock('./target.js', { 'lodash': {...} }) ``` -------------------------------- ### Options Usage Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/types.md An example demonstrating the use of custom resolvers and disabling module not found errors. ```javascript import esmock from 'esmock' // Use custom resolver const customResolver = (id, parent) => { if (id.startsWith('#')) { return resolveAlias(id, parent) } return defaultResolver(id, parent) } const module = await esmock('../src/target.js', { 'dep': { getValue: () => 42 } }, {}, { resolver: customResolver, isModuleNotFoundError: false // Allow missing modules }) ``` -------------------------------- ### Running Tests with --loader (Pre-v20.6) Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Command-line examples for running tests with AVA, Mocha, and native node:test using the --loader flag for versions prior to Node.js v20.6. ```bash # AVA ave --node-arguments="--loader=esmock" tests/**/*.test.js # Mocha mocha --loader=esmock tests/**/*.test.js # Native node:test node --loader=esmock --test tests/**/*.test.js ``` -------------------------------- ### Core Module Resolution Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example of resolving core Node.js modules (with or without 'node:' prefix) when using esmock. ```javascript // With or without node: prefix (both work) esmock('./target.js', { 'fs': {...} }) esmock('./target.js', { 'node:fs': {...} }) ``` -------------------------------- ### Install esmock Source: https://github.com/iambumblehead/esmock/wiki/Home Install esmock using npm. ```shell $ npm install --save-dev esmock ``` -------------------------------- ### Basic esmock call example Source: https://github.com/iambumblehead/esmock/wiki/Home A practical example of using esmock to mock a local file and a package dependency. ```javascript test('should mock modules and local files', async t => { const main = await esmock('../src/main.js', { serializepkg: { default: obj => JSON.stringify(obj) }, '../src/someModule.js' : { default: () => ({ foo: 'bar' }) } }) // Because `serializepkg` is mocked as a function calling JSON.stringify() // and `someDefaultExport` is mocked as a function returning { foo: 'bar' } t.is(main(), JSON.stringify({ foo: 'bar' })) }) ``` -------------------------------- ### package, alias and local file mocks Source: https://github.com/iambumblehead/esmock/blob/main/README.md Example demonstrating how to mock packages, aliases, and local files. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('package, alias and local file mocks', async () => { const cookup = await esmock('../src/cookup.js', { addpkg: (a, b) => a + b, '#icon': { coffee: 'β˜•', bacon: 'πŸ₯“' }, '../src/breakfast.js': { default: () => ['coffee', 'bacon'], addSalt: meal => meal + 'πŸ§‚' } }) assert.equal(cookup('breakfast'), 'β˜•πŸ₯“πŸ§‚') }) ``` -------------------------------- ### Manual Cache Management Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example demonstrating manual cache management with esmock.p() or esmock.strict.p(), where the cache is retained and manual purging is required. ```javascript const module = await esmock.p('./target.js', { ... }) // Cache retained // Dynamic imports use cached definitions esmock.purge(module) // Manual purge required ``` -------------------------------- ### Combined Options Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/configuration.md Demonstrates how to use esmock with custom resolvers, module mocks, and options like `purge`. ```javascript import esmock from 'esmock' import { pathToFileURL } from 'node:url' const customResolver = (id, parent) => { if (id.startsWith('#')) { // Handle custom protocol return `file://${process.cwd()}/aliases/${id.slice(1)}.js` } return null } const module = await esmock.p('../src/target.js', { 'fs': { readFileSync: () => 'mocked' }, '#utils': { helper: () => 'help' } }, { 'lodash': { debounce: (fn) => fn } }, { resolver: customResolver, isModuleNotFoundError: false, purge: false // Keep cache for esmock.p }) // Use module... esmock.purge(module) // Cleanup ``` -------------------------------- ### MockMap Usage Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/types.md An example demonstrating how to define mock definitions for various module specifiers. ```javascript const mockDefinitions = { 'fs': { readFileSync: () => 'content' }, 'path': { dirname: () => '/mocked/path' }, './local-module.js': { getValue: () => 42 }, '#alias': { data: 'aliased mock' } } const module = await esmock('../src/target.js', mockDefinitions) ``` -------------------------------- ### Install Dependencies and Run Tests Source: https://github.com/iambumblehead/esmock/blob/main/CONTRIBUTING.md Commands to install dependencies and run tests from the esmock root folder and a specific test folder. ```bash npm install && npm run test:install npm test ``` -------------------------------- ### Cannot Mock CommonJS Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example showing that using 'require' to import esmock from CommonJS is not supported. ```javascript // This does NOT work const esmock = require('esmock') // ❌ CommonJS require ``` -------------------------------- ### Running Tests without --loader (v20.6+) Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Command-line examples for running tests with AVA, Mocha, and native node:test without the --loader flag for Node.js v20.6 and later. ```bash # AVA ave tests/**/*.test.js # Mocha mocha tests/**/*.test.js # Native node:test node --test tests/**/*.test.js ``` -------------------------------- ### Subpath Import Resolution Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example of resolving subpath imports (e.g., '#alias') when using esmock, respecting package.json imports. ```javascript // Respects package.json imports field esmock('./target.js', { '#alias': {...} }) ``` -------------------------------- ### Loader Registration for Node.js < 16.12 Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example of registering the esmock loader via the command line for older Node.js versions. ```bash node --loader=esmock test.js ``` -------------------------------- ### Partial Mocking Example Source: https://github.com/iambumblehead/esmock/wiki/Home Example illustrating partial mocking where original module definitions are merged with mock definitions. ```javascript mockPartial = Object.assign(await import('/module.js'), mockDefs) ``` -------------------------------- ### Cache Control with esmock.p Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/configuration.md Example showing how to use esmock.p for cache control, which automatically sets purge: false. ```javascript import esmock from 'esmock' // esmock.p automatically sets purge: false internally const module = await esmock.p('../src/dynamicLoader.js', { 'some-pkg': { create: () => ({})} }) // Cache is retained, supporting await import() inside target module // Manually purge when done esmock.purge(module) ``` -------------------------------- ### Example Mocking JSON Import (Node 21.2+) Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example of how to mock a JSON import using esmock for Node.js versions 21.2 and later. ```javascript test('mock json import', async () => { const module = await esmock('../src/loader.js', { './config.json': { setting: 'value' } }) }) ``` -------------------------------- ### Loader Registration for Node.js 20.6.0 - Current Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example of registering the esmock loader at runtime using module.register() for newer Node.js versions. ```bash node test.js # No --loader needed ``` -------------------------------- ### Resolver Usage Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/types.md An example of a custom resolver that handles package aliases and falls back to default resolution. ```javascript import esmock from 'esmock' import { pathToFileURL } from 'node:url' // Custom resolver that handles package aliases const customResolver = (id, parent) => { // Handle @ aliases if (id.startsWith('@alias/')) { const realPath = `/workspace/modules/${id.slice(7)}` return pathToFileURL(realPath).href } // Fall back to default resolution return null // Return null to use default resolver } const module = await esmock('../src/target.js', { // ... mocks }, {}, { resolver: customResolver }) ``` -------------------------------- ### Test Framework Integration: With AVA Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Provides an example of using `esmock` with the AVA testing framework. ```javascript import test from 'ava' import esmock from 'esmock' test('should mock dependencies', async (t) => { const module = await esmock('../src/module.js', { './dep.js': { fn: () => 'mocked' } }) t.is(module.fn(), 'mocked') }) ``` -------------------------------- ### MockFunction Usage Example Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/types.md An example showing how to use esmock with explicit type parameters for better IDE support. ```javascript import esmock from 'esmock' // Type the generic parameter for better IDE support const typedModule: { getValue: () => number } = await esmock<{ getValue: () => number }>('../src/module.js', { './dep.js': { get: () => 42 } }) ``` -------------------------------- ### PnP Resolver Path Handling Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Shows how the pnpResolver converts a path to a file:// URL. ```javascript // pnpResolver converts to file:// URL const resolved = pathToFileURL(path).href ``` -------------------------------- ### Strict Mocking Example Source: https://github.com/iambumblehead/esmock/wiki/Home Example illustrating strict mocking where original module definitions are replaced. ```javascript mockStrict = mockDefs ``` -------------------------------- ### Custom Module Resolver Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/configuration.md Example of implementing a custom module resolver for aliased imports and specific file types. ```javascript import esmock from 'esmock' import { pathToFileURL } from 'node:url' // Custom resolver for aliased imports const aliasResolver = (id, parent) => { // Handle @app alias if (id.startsWith('@app/')) { const relativePath = id.slice(5) const resolved = new URL(`./src/${relativePath}`, parent) return resolved.href } // Handle .json files explicitly if (id.endsWith('.json')) { const resolved = new URL(id, parent) return resolved.href } // Return null to use default resolver return null } const module = await esmock('../src/app.js', { '@app/utils': { helper: () => 'help' }, './config.json': { setting: 'value' } }, {}, { resolver: aliasResolver }) ``` -------------------------------- ### Automatic Cache Purge Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Example showing that the cache is automatically purged after an import completes when using esmock() or esmock.strict(). ```javascript const module = await esmock('./target.js', { ... }) // Cache purged automatically // module.esmkTreeId still available but cache removed ``` -------------------------------- ### Initialization Flow Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/module-map.md Details the steps involved in initializing esmock, including the creation of the esmock function, loader registration, and global state setup. ```javascript import esmock from 'esmock' esmockGo() creates function ↓ esmockRegister() checks for module.register β”œβ†’ v20.6+: register() returns true β”‚ Loader registered via module.register β”‚ β””β†’ { try { const module = await esmock('../src/target.js', { // Intentionally incomplete mocks }) } catch (err) { if (err.message.includes('invalid moduleId')) { // Handle missing module console.log('Module resolution failed:', err.message) } else if (err.message.includes('loader')) { // Handle loader issues console.log('Loader not configured properly') } throw err } }) ``` -------------------------------- ### Mock definitions structure Source: https://github.com/iambumblehead/esmock/wiki/Home An example of how to structure mock definitions for packages, core modules, global variables, local files, subpaths, and default/named exports. ```javascript const mocks = { // package eslint: { ESLint: cfg => cfg }, // core module fs: { readFileSync: () => 'returns this globally' }, // global variable import: { fetch: () => ({ res: 200 }) }, // local file '../src/main.js': { start: 'go' }, // subpath '#feature': { release: () => 'release time' }, // default and/or named exports '../src/hello.js': { default: () => 'world', exportedFunction: () => 'foo' }, // short-hand default exports '../src/init.js': () => 'init' } ``` -------------------------------- ### mock fetch, Date, setTimeout and any globals Source: https://github.com/iambumblehead/esmock/blob/main/README.md Example demonstrating how to mock global objects like fetch, Date, and setTimeout. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('mock fetch, Date, setTimeout and any globals', async () => { // https://github.com/iambumblehead/esmock/wiki#call-esmock-globals const { userCount } = await esmock('../Users.js', { '../req.js': await esmock('../req.js', { import: { // define globals like 'fetch' on the import namespace fetch: async () => ({ status: 200, json: async () => [['jim','πŸ˜„'],['jen','😊']] }) } }) }) assert.equal(await userCount(), 2) }) ``` -------------------------------- ### Default Behavior (Merge Definitions) Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/configuration.md Example demonstrating the default behavior where mocks are merged with original module definitions. ```javascript import esmock from 'esmock' // Uses all defaults const module = await esmock('../src/target.js', { './helper.js': { getValue: () => 42 } }) // Mocks are merged with original module definitions // If original exports other functions, they're still available ``` -------------------------------- ### Mocking an absent module Source: https://github.com/iambumblehead/esmock/wiki/Home Demonstrates how to mock a package (e.g., 'vue') that is not installed using the 'isModuleNotFoundError: false' option. ```javascript test('should mock vue package, even when package is not installed', async () => { const component = await esmock('../local/notinstalledVueComponent.js', { vue: { h: (...args) => args } }, {}, { isModuleNotFoundError: false }) assert.strictEqual(component()[0], 'svg') }) ``` -------------------------------- ### Error Handling: Allow Missing Modules Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates how to configure `esmock` to allow unmocked modules that are installed in `node_modules`. ```javascript import test from 'node:test' import esmock from 'esmock' test('allow unmocked but installed modules', async () => { const module = await esmock( '../src/module.js', { 'mocked-pkg': { fn: () => {} } }, {}, { isModuleNotFoundError: false } ) // 'unmocked-pkg' can be imported and uses real implementation }) ``` -------------------------------- ### Runtime Loader Registration using module.register() Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md JavaScript code demonstrating how to register the esmock loader at runtime using module.register() for Node.js 20.6.0+. ```javascript if (typeof module.register === 'function') { module.register('./esmockLoader.js', { parentURL: import.meta.url, data: { port: channel.port2 }, transferList: [channel.port2] }) } ``` -------------------------------- ### Example of using strict mode Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/api-reference/strict-strictest.md Demonstrates how to use the strict named export for mocking. ```javascript import test from 'node:test' import assert from 'node:assert' import { strict } from 'esmock' test('use strict mode via named export', async () => { const module = await strict('../src/math.js', { './add.js': { add: (a, b) => a + b } }) assert.equal(module.calculate(), expected) }) ``` -------------------------------- ### Windows Path Conversion Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Illustrates the conversion of Windows absolute paths to file:// URL format and how URL parsing handles drive letters. ```javascript // Windows absolute path 'C:\\Users\\file.js' β†’ 'file:///C:/Users/file.js' // URL parsing handles drive letters correctly ``` -------------------------------- ### Context Parameter Handling Solution Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md JavaScript code demonstrating the solution for handling context parameters in nextResolve to avoid recursion in new Node.js versions. ```javascript const nextResolveCall = async (nextResolve, specifier, context) => ( context.parentURL && (context.conditions.slice(-1)[0] === 'node-addons' || context.importAssertions || isLT1612) ? nextResolve(specifier, context) : nextResolve(specifier)) ``` -------------------------------- ### full import tree mocks β€”third param Source: https://github.com/iambumblehead/esmock/blob/main/README.md Example showing how to mock the entire import tree using the third parameter of esmock. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('full import tree mocks β€”third param', async () => { const { getFile } = await esmock('../src/main.js', {}, { // mocks *every* fs.readFileSync inside the import tree fs: { readFileSync: () => 'returned to 🌲 every caller in the tree' } }) assert.equal(getFile(), 'returned to 🌲 every caller in the tree') }) ``` -------------------------------- ### Catch Module Not Found Error Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/errors.md Example of how to catch a 'Module Not Found Error' using assert.rejects. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('catch module not found error', async () => { assert.rejects( () => esmock('../src/target.js', { // Missing mock for './missing-file.js' }), { name: 'Error', message: /invalid moduleId: "\.\/missing-file\.js"/ } ) }) ``` -------------------------------- ### Direct Cache Access (Advanced) Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/api-reference/internal-api.md Example demonstrating how to access esmock's internal cache for debugging purposes. ```javascript import { esmockCacheGet, esmockTreeIdGet } from 'esmock/src/esmockCache.js' // Not typically needed, but available for debugging const treeSpec = esmockTreeIdGet('123') // Get tree specification const mockDef = esmockCacheGet(key) // Get cached mock ``` -------------------------------- ### mocks "await import()" using esmock.p Source: https://github.com/iambumblehead/esmock/blob/main/README.md Example of mocking dynamic imports using esmock.p, which keeps mock definitions in cache. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('mocks "await import()" using esmock.p', async () => { // using esmock.p, mock definitions are kept in cache const doAwaitImport = await esmock.p('../awaitImportLint.js', { eslint: { ESLint: cfg => cfg } }) // mock definition is returned from cache, when import is called assert.equal(await doAwaitImport('cfgπŸ› οΈ'), 'cfgπŸ› οΈ') // a bit more info are found in the wiki guide }) ``` -------------------------------- ### Feature Detection Checks Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Code snippets for detecting loader availability, worker threads, Node.js version, and Yarn PnP availability. ```javascript // Loader availability typedof module.register === 'function' // v20.6+ // Worker threads typedof threads.MessageChannel === 'function' // Available // Node version const [major, minor] = process.versions.node.split('.') const isLT1612 = major < 16 || (major === 16 && minor < 12) // PnP availability process.versions.pnp // Yarn PnP active ``` -------------------------------- ### Yarn PnP Behavior Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Demonstrates how esmock uses the pnpapi module for resolving module requests when Yarn PnP is active. ```javascript const pnpapi = process.versions.pnp && (await import('pnpapi')).default if (pnpapi) { // Use pnpapi for resolution const path = pnpapi.resolveRequest(id, parent) return pathToFileURL(path).href } // Falls back to resolvewithplus ``` -------------------------------- ### Node 22.1 Regression Details Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Details from the Node.js CHANGELOG regarding a regression in module loading for Node 22.1. ```text Regression in Node 22.1 related to module loading Pinned to Node 22.1 in early releases Now uses latest 22.x after fixes ``` -------------------------------- ### Example of using strictest mode Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/api-reference/strict-strictest.md Demonstrates how to use the strictest named export for mocking, including error handling for unmocked modules. ```javascript import test from 'node:test' import assert from 'node:assert' import { strictest } from 'esmock' test('strictest mode via named export', async () => { // Will throw if any import in the tree is unmocked const module = await strictest('../src/module.js', { 'fs': { readFileSync: () => 'content' }, './helper.js': { help: () => 'help' } }) // test code... }) test('strictest without all mocks throws', async () => { assert.rejects( () => strictest('../src/module.js', {}), { message: /un-mocked moduleId/ } ) }) ``` -------------------------------- ### Require All Imports to Be Mocked Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Example demonstrating the `strictest` function, which ensures all module imports are explicitly mocked. It shows how to mock dependencies and how the function throws an error if any dependency is not mocked. ```javascript import test from 'node:test' import assert from 'node:assert' import { strictest } from 'esmock' // File: src/app.js // import { readFile } from 'fs/promises' // import { join } from 'path' // export const run = () => 'ok' test('strictest requires all mocks', async () => { const app = await strictest('../src/app.js', { 'fs/promises': { readFile: () => 'content' }, 'path': { join: (...parts) => parts.join('/') } }) assert.equal(app.run(), 'ok') }) test('strictest throws on unmocked', async () => { assert.rejects( () => strictest('../src/app.js', { // Missing 'path' mock 'fs/promises': { readFile: () => 'content' } }), { message: /un-mocked moduleId: "path"/ } ) }) ``` -------------------------------- ### Esmock Module Resolution Behavior for TypeScript Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Illustrative JavaScript code showing how esmock detects and handles TypeScript files during module resolution. ```javascript // esmockModule.js detects TypeScript const isTypescript = /\.ts$/i.test(fileURL) // When detected, searches for .ts files in addition to .js ``` -------------------------------- ### Custom Resolver with pnpResolver Fallback Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/api-reference/internal-api.md Example of creating a custom resolver that prioritizes custom logic, falls back to Yarn PnP, and then to the default resolver. ```javascript import esmock from 'esmock' import pnpResolver from 'esmock/src/pnpResolver.js' import resolvewithplus from 'resolvewithplus' const customResolver = (id, parent) => { // Custom logic first if (id.startsWith('@alias/')) { return resolveAlias(id, parent) } // Fall back to Yarn PnP if available if (pnpResolver) { const result = pnpResolver(id, parent) if (result !== null) return result } // Fall back to default resolver return resolvewithplus.resolve(id, parent) } const module = await esmock('../src/target.js', {}, {}, { resolver: customResolver }) ``` -------------------------------- ### Allowing Missing Modules Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/configuration.md Illustrates how to handle cases where modules might not be resolvable. ```javascript import esmock from 'esmock' // Normal behavior: throws on missing modules try { await esmock('../src/target.js', { 'installed-package': { fn: () => {} } // 'uninstalled-package' not mocked }) // Throws: invalid moduleId: "uninstalled-package" } catch (err) { console.log(err) } // Allow missing modules const module = await esmock('../src/target.js', { 'installed-package': { fn: () => {} } }, {}, { isModuleNotFoundError: false }) // 'uninstalled-package' can now be imported // Uses original implementation if module is found, or mock if provided ``` -------------------------------- ### Mock Core Modules Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates how to mock core Node.js modules. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' // File: src/fileReader.js // import fs from 'fs' // export const read = (path) => fs.readFileSync(path, 'utf-8') test('mock core fs module', async () => { const fileReader = await esmock('../src/fileReader.js', { 'fs': { readFileSync: () => 'mocked file content' } }) assert.equal(fileReader.read('/any/path'), 'mocked file content') }) ``` -------------------------------- ### Mock a Single File Dependency Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates how to mock a local file dependency. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' // File: src/calculator.js // import { add } from './math.js' // export const calculate = () => add(2, 3) test('mock local file', async () => { const calculator = await esmock('../src/calculator.js', { './math.js': { add: (a, b) => 10 // Always return 10 } }) assert.equal(calculator.calculate(), 10) }) ``` -------------------------------- ### Mock Package Dependencies Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates how to mock an npm package dependency. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' // File: src/logger.js // import winston from 'winston' // export const log = (msg) => winston.info(msg) test('mock npm package', async () => { const logger = await esmock('../src/logger.js', { 'winston': { info: (msg) => `logged: ${msg}` } }) assert.equal(logger.log('hello'), 'logged: hello') }) ``` -------------------------------- ### Mock Core Modules with node: Prefix Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates mocking core Node.js modules using the 'node:' prefix. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('mock with node: prefix', async () => { const fileReader = await esmock('../src/fileReader.js', { 'node:fs': { readFileSync: () => 'mocked content' } }) assert.equal(fileReader.read('/path'), 'mocked content') }) ``` -------------------------------- ### esmock.strict mocks Source: https://github.com/iambumblehead/esmock/blob/main/README.md Example of using esmock.strict to replace original module definitions without merging them. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('esmock.strict mocks', async () => { // replace original module definitions and do not merge them const pathWrapper = await esmock.strict('../src/pathWrapper.js', { path: { dirname: () => '/path/to/file' } }) // error, because "path" mock above does not define path.basename assert.rejects(() => pathWrapper.basename('/dog.🐢.png'), { name: 'TypeError', message: 'path.basename is not a function' }) }) ``` -------------------------------- ### Mock Multiple Global Dependencies Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates mocking multiple global dependencies simultaneously. ```javascript import test from 'node:test' import esmock from 'esmock' test('mock multiple globals', async () => { const module = await esmock('../src/module.js', {}, { 'fs': { readFileSync: () => 'file' }, 'path': { join: (...parts) => parts.join('/') }, 'http': { createServer: () => ({}) }, 'node:process': { cwd: () => '/current' } }) // All globals mocked across entire import tree }) ``` -------------------------------- ### Multiple Tests with esmock.p Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Illustrates using esmock.p across multiple tests, leveraging test.before to load and cache a module, and test.after to purge it. ```javascript import test from 'node:test' import esmock from 'esmock' let cachedModule test.before(async () => { cachedModule = await esmock.p('../src/module.js', { 'pkg': { fn: () => {} } }) }) test('uses cached module', () => { // Test with cachedModule... }) test.after(() => { esmock.purge(cachedModule) }) ``` -------------------------------- ### Mock Code Using await import() Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates mocking code that uses dynamic imports with `esmock.p`. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' // File: src/pluginLoader.js // export const load = async (pluginName) => { // const plugin = await import(`./plugins/${pluginName}.js`) // return plugin.default() // } test('mock dynamic imports with esmock.p', async () => { const loader = await esmock.p('../src/pluginLoader.js', { './plugins/auth.js': { default: () => ({ auth: true }) } }) const plugin = await loader.load('auth') assert.deepEqual(plugin, { auth: true }) // Clean up cache when done esmock.purge(loader) }) ``` -------------------------------- ### Resolve Un-mocked Module Error Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/errors.md Example of how to resolve an 'Un-mocked Module Error' by providing mocks for all imports. ```javascript import { strictest } from 'esmock' // Provide mocks for all imports const module = await strictest('../src/target.js', { 'fs': { readFileSync: () => 'content' }, 'path': { join: (...parts) => parts.join('/') }, './helper.js': { help: () => 'help' } }) ``` -------------------------------- ### Mock Globals Across the Import Tree Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates mocking global objects like 'fetch' across the entire import tree. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' // File: src/fetcher.js // import axios from 'axios' // export const getData = async () => { // const response = await fetch('/api/data') // return response.json() // } test('mock fetch globally', async () => { const fetcher = await esmock('../src/fetcher.js', { // Local mocks (empty) }, { // Global mocks applied everywhere 'node:fetch': { default: async () => ({ json: async () => ({ success: true }) }) } }) const result = await fetcher.getData() assert.deepEqual(result, { success: true }) }) ``` -------------------------------- ### Single Test with esmock.p Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Shows how to use esmock.p within a single test case, including mocking dependencies and purging the module cache after the test. ```javascript import test from 'node:test' import esmock from 'esmock' test('cache cleanup in single test', async () => { const module = await esmock.p('../src/module.js', { 'pkg': { fn: () => {} } }) // Use module... // Always purge at end esmock.purge(module) }) ``` -------------------------------- ### Suppress Module Not Found Error Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/errors.md Example of how to suppress 'Module Not Found Error' by setting isModuleNotFoundError to false. ```javascript const module = await esmock('../src/target.js', { // ... mocks }, {}, { isModuleNotFoundError: false // Allow missing modules }) ``` -------------------------------- ### esmock call without parentUrl Source: https://github.com/iambumblehead/esmock/wiki/Home An example of calling esmock without a parentUrl, suitable for scenarios without separated transpiling steps. ```typescript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' import type Rabbit from '../rabbit.js' test('specify the type of export returned', async () => { const rabbit = await esmock('../rabbit.js', { '../util.js': { multiply: (numbers: number[]): number => ( numbers.reduce((acc, n) => acc *= n, 1)) } }) assert.equal(rabbit.makebabies(), 'πŸ‡πŸ‡πŸ‡πŸ‡πŸ‡πŸ‡πŸ‡πŸ‡πŸ‡πŸ‡πŸ‡πŸ‡πŸ‡') }) ``` -------------------------------- ### Resolve No Mocks Provided Error Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/errors.md Example of how to resolve 'No Mocks Provided Error' by providing mock definitions. ```javascript import { strictest } from 'esmock' // Provide at least some mock definitions const module = await strictest('../src/target.js', { 'fs': { readFileSync: () => 'content' } }) ``` -------------------------------- ### Catch Un-mocked Module Error in Strictest Mode Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/errors.md Example of how to catch an 'Un-mocked Module Error' when using esmock.strictest(). ```javascript import test from 'node:test' import assert from 'node:assert' import { strictest } from 'esmock' test('catch unmocked module in strictest', async () => { assert.rejects( () => strictest('../src/target.js', { // Only mocking 'fs', but module also imports 'path' 'fs': { readFileSync: () => 'content' } }), { name: 'Error', message: /un-mocked moduleId: "path"/ } ) }) ``` -------------------------------- ### Test Framework Integration: With Mocha Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates how to use `esmock` with the Mocha testing framework, including assertions with Chai. ```javascript import esmock from 'esmock' import { expect } from 'chai' describe('My Module', () => { it('should mock dependencies', async () => { const module = await esmock('../src/module.js', { './dep.js': { fn: () => 'mocked' } }) expect(module.fn()).to.equal('mocked') }) }) ``` -------------------------------- ### Custom Loader Chain Registration Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/api-reference/loader-hooks.md Example of registering esmock loader first, then other custom loaders. ```javascript // register.mjs - Custom loader registration import { register } from 'node:module' // Register esmock loader first register('esmock/src/esmockLoader.js', { parentURL: import.meta.url }) // Then register other loaders register('your-custom-loader.js', { parentURL: import.meta.url }) ``` -------------------------------- ### esmock.js Data Flow Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/module-map.md Illustrates the data flow for the main esmock.js entry point, showing how it orchestrates module mocking. ```text esmock(targetModule, defs, gdefs, opts) β†’ esmockModule(targetModule, parent, defs, gdefs, opts) β†’ resolver(targetModule, parent) [via opt.resolver] β†’ esmockModuleId() for each def β†’ resolver(id, parent) for each import β†’ esmockModuleCreate() for each resolved module β†’ Returns modified URL with embedded tree ID ``` -------------------------------- ### Conditional getSource Hook for Node.js < 16.12 Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/node-compatibility.md Conditional JavaScript code to determine if the getSource hook is needed based on Node.js version. ```javascript const isLT1612 = major < 16 || (major === 16 && minor < 12) const getSource = isLT1612 && load ``` -------------------------------- ### Import Options Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/api-reference/strict-strictest.md Shows recommended ways to import the strict and strictest named exports. ```javascript // Recommended: Named imports import { strict, strictest } from 'esmock' // Or destructure from default import esmock from 'esmock' const { strict, strictest } = esmock ``` -------------------------------- ### Catch Empty Mocks in Strictest Mode Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/errors.md Example of how to catch 'No Mocks Provided Error' when using esmock.strictest() with empty mock definitions. ```javascript import test from 'node:test' import assert from 'node:assert' import { strictest } from 'esmock' test('catch empty mocks in strictest', async () => { assert.rejects( () => strictest('../src/target.js', {}, {}), { name: 'Error', message: /no mocks provided for module/ } ) }) ``` -------------------------------- ### Error Handling: Catch Module Not Found Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Shows how to catch errors when a required module is not found or not mocked. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('handle missing modules gracefully', async () => { assert.rejects( () => esmock('../src/module.js', { // Missing './required-dep.js' mock }), { message: /invalid moduleId/ } ) }) ``` -------------------------------- ### Resolve Missing Loader Error (Node < v20.6.0) Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/errors.md Command-line examples for resolving 'Missing Loader Error' on Node.js versions prior to v20.6.0. ```bash # Using node:test node --loader=esmock tests/mytest.js # Using AVA ava --node-arguments="--loader=esmock" tests/mytest.js # Using Mocha mocha --loader=esmock tests/mytest.js ``` -------------------------------- ### Cache Lifecycle Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/module-map.md Explains the lifecycle of the esmock cache, including initial state, how mocks are created and resolved, and how the cache is purged. ```javascript Initial state: global.mockKeys = {} 1. Test starts: await esmock.p(...) β”œβ†’ esmockModule creates tree ID '123' β””β†’ global.mockKeys['123'] = treeSpec global.esmockCache.mockDefs[mockURL] = mockDef 2. Module imports: import { fn } from 'pkg' β†’ esmockLoader.resolve intercepts β†’ Looks up in global.mockKeys β†’ Returns mock URL 3. Purge: esmock.purge(module) β”œβ†’ Extracts esmkTreeId from module β””β†’ esmockModuleImportedPurge(treeId) β†’ Deletes all cache entries for tree β†’ global.mockKeys[treeId] = undefined ``` -------------------------------- ### Test Framework Integration: With node:test Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Shows how to integrate `esmock` with Node.js's built-in `test` runner for mocking dependencies. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('integration with node:test', async () => { const module = await esmock('../src/module.js', { './dep.js': { fn: () => 'mocked' } }) assert.equal(module.fn(), 'mocked') }) ``` -------------------------------- ### Multiple Mock Levels: Local and Global Mocks Together Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Illustrates how to combine local mocks (specific to the module being imported) with global mocks (applying to the entire import tree) when using `esmock`. ```javascript import test from 'node:test' import esmock from 'esmock' // File: src/userService.js // import { User } from './models/User.js' // import axios from 'axios' // import { Logger } from './logger.js' // export const getUser = async (id) => { ... } test('combine local and global mocks', async () => { const userService = await esmock( '../src/userService.js', { // Local mocks (apply only to this module) './models/User.js': { User: class { constructor(id) { this.id = id } } } }, { // Global mocks (apply to entire import tree) 'axios': { get: async () => ({ data: { name: 'John' } }) }, './logger.js': { Logger: class { log() {} } } } ) // userService can use all mocks }) ``` -------------------------------- ### Mock Application Flow Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/module-map.md Describes the process of applying mocks using esmock, from argument normalization and mock tree creation to module loading and execution with mocked imports. ```javascript await esmock(targetModule, defs, gdefs, opts) esmockArgs() normalizes arguments ↓ esmockModule() creates mock tree β”œβ†’ resolver(targetModule) β†’ fileURL β”œβ†’ for each def: β”‚ resolver(id) β†’ resolved module URL β”‚ esmockModuleCreate() β†’ creates cache entry β””β†’ returns URL with ?esmk=treeId import(fileURLKey) loads target ↓ esmockLoader.resolve() intercepts imports β†’ Checks mock tree cache β†’ Returns mock URL or delegates esmockLoader.load() intercepts load β†’ Retrieves mock from cache β†’ Injects import statements β†’ Returns transformed source Module executes with mocked imports ↓ esmockModule.sanitize() formats result β†’ Attaches esmkTreeId property β†’ Merges with default export ↓ Returns mocked module to test ``` -------------------------------- ### Message Channel Communication - Main Module Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/api-reference/loader-hooks.md Esmock uses a MessageChannel to communicate mock definitions between the main thread and the loader thread. This snippet shows the setup in the main module (esmockRegister.js). ```javascript const channel = threads.MessageChannel && new threads.MessageChannel() module.register('./esmockLoader.js', { parentURL: import.meta.url, data: { port: channel.port2 }, transferList: [channel.port2] }) ``` -------------------------------- ### Explicit Purge Control Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/configuration.md Demonstrates explicit control over cache purging using both standard esmock and esmock.p. ```javascript import esmock from 'esmock' // Option 1: Use standard esmock with purge: true (default) const m1 = await esmock('../src/module1.js', { './dep.js': { value: 1 } }, {}, { purge: true // Explicit, though this is the default }) // Option 2: Use esmock.p with manual purge const m2 = await esmock.p('../src/module2.js', { './dep.js': { value: 2 } }, {}, { purge: false // Retained by esmock.p by default }) esmock.purge(m2) // Explicit cleanup ``` -------------------------------- ### Package.json configuration for different test runners Source: https://github.com/iambumblehead/esmock/wiki/Home Configuration for package.json to integrate esmock with various test runners. Note the `--loader` argument for older Node.js versions. ```json { "name": "give-esmock-a-star", "type": "module", "scripts": { "test": "node --loader=esmock --test", "test-mocha": "mocha --loader=esmock", "test-tap": "NODE_OPTIONS=--loader=esmock tap", "test-ava": "NODE_OPTIONS=--loader=esmock ava", "test-uvu": "NODE_OPTIONS=--loader=esmock uvu spec", "test-tsm": "node --loader=tsm --loader=esmock --test *ts", "test-ts": "node --loader=ts-node/esm --loader=esmock --test *ts", "test-jest": "NODE_OPTIONS=--loader=esmock jest", "test-tsx": "⚠ https://github.com/esbuild-kit/tsx/issues/264" }, "jest": { "runner": "jest-light-runner" } } ``` -------------------------------- ### Import Statements Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/types.md Demonstrates how to import esmock types using named exports or from the TypeScript definition file. ```javascript // Import with named exports import { type MockFunction, type MockMap, type Options, type Resolver } from 'esmock' // Or from the TypeScript definition file import type { MockFunction, MockMap, Options, Resolver } from 'esmock' ``` -------------------------------- ### Test case specifying parentUrl Source: https://github.com/iambumblehead/esmock/wiki/Home A test case demonstrating how to use esmock with a parentUrl to locate modules from their transpiled location. ```javascript test('should locate modules from parentUrl, transpiled location', async () => { const indexModule = await esmock('../index.js', import.meta.url, { os: { hostname: () => 'local' } }); assert.strictEqual(indexModule.getHostname(), 'local') }) ``` -------------------------------- ### Advanced Patterns: Spy on Mock Calls Source: https://github.com/iambumblehead/esmock/blob/main/_autodocs/usage-patterns.md Demonstrates how to spy on mock function calls to verify interactions with mocked dependencies. ```javascript import test from 'node:test' import assert from 'node:assert' import esmock from 'esmock' test('verify mock was called', async () => { const calls = [] const mockAdd = (a, b) => { calls.push({ a, b }) return a + b } const calculator = await esmock('../src/calculator.js', { './math.js': { add: mockAdd } }) calculator.calculate(2, 3) assert.deepEqual(calls, [{ a: 2, b: 3 }]) }) ```