Skip to content

iambumblehead/esmock

This branch is up to date with main.

Folders and files

NameName
Last commit message
Last commit date
Oct 18, 2024
Oct 18, 2024
Oct 18, 2024
Jul 24, 2022
Oct 18, 2024
Nov 13, 2023
Jul 22, 2022
Oct 17, 2024
Oct 17, 2024
Oct 18, 2024

Repository files navigation

+                                                ██╗
+ ██████╗  ███████╗ █████═████╗  ██████╗  ██████╗██║   ██╗
+██╔═══██╗██╔═════╝██╔══██╔══██╗██╔═══██╗██╔════╝██║  ██╔╝
+████████║╚██████╗ ██║  ██║  ██║██║   ██║██║     ██████╔╝
+██╔═════╝ ╚════██╗██║  ██║  ██║██║   ██║██║     ██╔══██╗
+╚███████╗███████╔╝██║  ██║  ██║╚██████╔╝╚██████╗██║  ╚██╗
+ ╚══════╝╚══════╝ ╚═╝  ╚═╝  ╚═╝ ╚═════╝  ╚═════╝╚═╝   ╚═╝

npm coverage install size downloads

esmock provides native ESM import and globals mocking for unit tests. Use examples below as a quick-start guide, see the descriptive and friendly esmock guide here, or browse esmock's test runner examples.

Note: For versions of node prior to v20.6.0, "--loader" command line arguments must be used with esmock as demonstrated in the wiki. Current versions of node do not require "--loader".

Note: due to --loader issues, support for ava and jest are dropped.

esmock has the below signature

await esmock(
  './to/module.js', // path to target module being tested
  { ...childmocks }, // mock definitions imported by target module
  { ...globalmocks }) // mock definitions imported everywhere

esmock examples

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'), '☕🥓🧂')
})

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')
})

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)
})

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
})

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'
  })
})