diff --git a/README.md b/README.md index aed99f6a..82b9683e 100644 --- a/README.md +++ b/README.md @@ -97,49 +97,41 @@ test('should mock modules and local files at same time', async t => { }); ``` -## Examle, mocking await import( 'modulename' ) +## Example, mocking await import('modulename') -When `esmock` loads and returns a module it deletes mocking definitions from a cache by default. Disable this behaviour when using 'await import', so that mocked definitions can be loaded during test runtime. A function can be called later to clear the cache. +Before `esmock` returns a module, by default it deletes mocked definitions for that module. To use 'await import', call `esmock.p( ... )` instead of `esmock( ... )` so that async imports may use mock definitions during test runtime and after the module is returned. +Foe example, let's test this file using `await import('eslint')`, ``` javascript export default async function usesAwaitImport (config) { - const eslint = (await import('eslint')); + const eslint = await import('eslint'); - return new eslint.ESLint({ baseConfig : config }); + return new eslint.ESLint(config); }; ``` -In the test file, define an 'options' object before local and global mock definitions, `{ isPurge: false }`, +Use `esmock.p()` rather than `esmock()` to load that file, ``` javascript -test('mocks inline `async import("name")`', async t => { - const writeJSConfigFile = await esmock('./local/usesAwaitImport.mjs', { - isPurge : false - }, { +test('should mock module using inline async import`', async t => { + const usesAwaitImport = await esmock.p('./local/usesAwaitImport.mjs', { eslint : { - ESLint : function (o) { - this.stringify = () => JSON.stringify(o); - - return this; - } + ESLint : o => o } }); - t.is((await writeJSConfigFile('config')).stringify(), JSON.stringify({ - baseConfig : 'config' - })); + t.is(await usesAwaitImport('config'), 'config'); - // clear the cache - esmock.purge(writeJSConfigFile); + esmock.purge(usesAwaitImport); // esmock.purge clears the cache }); ``` -If there are not many tests or if each test completes in a separate process, skipping `esmock.purge()` is OK +If there are not many tests or if tests complete in separate processes, skipping `esmock.purge()` is OK (if you don't have hundreds of tests, its OK to skip) ### changelog - * 1.2.0 _Nov.26.2021_ - * add support for await import + * 1.3.0 _Nov.26.2021_ + * add support for await import, update README * 1.1.0 _Nov.25.2021_ * add windows-latest to testing pipeline and begin windows support * removed files and functions no longer needed diff --git a/package.json b/package.json index b6e4f6cb..87a0c5c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "esmock", - "version": "1.2.0", + "version": "1.3.0", "license": "MIT", "readmeFilename": "README.md", "description": "mock esm modules for unit-tests", diff --git a/spec/esmock.spec.js b/spec/esmock.spec.js index eb154418..22d2ab92 100644 --- a/spec/esmock.spec.js +++ b/spec/esmock.spec.js @@ -256,9 +256,7 @@ test('returns spread-imported [object Module] default export', async t => { }); test('mocks inline `async import("name")`', async t => { - const writeJSConfigFile = await esmock('./local/usesInlineImport.mjs', { - isPurge : false - }, { + const writeJSConfigFile = await esmock.p('./local/usesInlineImport.mjs', { eslint : { ESLint : function (...o) { this.stringify = () => JSON.stringify(...o); diff --git a/src/esmock.js b/src/esmock.js index 12a8747f..5b7026ec 100644 --- a/src/esmock.js +++ b/src/esmock.js @@ -11,29 +11,27 @@ import { const argHasKey = (arg, key) => ( arg && !/number|boolean/.test(typeof arg) && key in arg); -const esmock = async (modulePath, mockDefs, globalDefs, opt) => { - // this functions caller is stack item '2' - const calleePath = new Error().stack.split('\n')[2] +const esmock = async (modulePath, mockDefs, globalDefs, opt = {}, err) => { + // callee path is stack item '2' + const calleePath = (err || new Error()).stack.split('\n')[2] .replace(/^.*file:\/\//, '') // rm everything before filepathfe .replace(/:[\d]*:[\d]*.*$/, '') // rm line and row number .replace(/^.*:/, ''); // rm windows-style drive locations - // remap params in case options are provided as first arg - [ opt, mockDefs, globalDefs ] = argHasKey(mockDefs, 'isPurge') - ? [ mockDefs || {}, globalDefs || {}, opt || {} ] - : [ opt || {}, mockDefs || {}, globalDefs || {} ]; - const modulePathKey = await esmockModuleMock( - calleePath, modulePath, mockDefs || {}, globalDefs || {}, opt || {}); + calleePath, modulePath, mockDefs || {}, globalDefs || {}, opt); const importedModule = await import(modulePathKey); - if (opt.isPurge !== false) + if (opt.purge !== false) esmockModuleImportedPurge(modulePathKey); - + return esmockModuleImportedSanitize(importedModule, modulePathKey); }; +esmock.p = async (modulePath, mockDefs, globalDefs) => ( + esmock(modulePath, mockDefs, globalDefs, { purge : false }, new Error())); + esmock.purge = mockModule => { if (argHasKey(mockModule, 'esmockKey')) esmockModuleImportedPurge(mockModule.esmockKey);