Using Node.js's test runner

Node.js has a flexible and robust built-in test runner. This guide will show you how to set up and use it.

example/
  ├ …
  ├ src/
    ├ app/…
    └ sw/…
  └ test/
    ├ globals/
      ├ …
      ├ IndexedDb.js
      └ ServiceWorkerGlobalScope.js
    ├ setup.mjs
    ├ setup.units.mjs
    └ setup.ui.mjs

Note: globs require node v21+, and the globs must themselves be wrapped in quotes (without, you'll get different behaviour than expected, wherein it may first appear to be working but isn't).

There are some things you always want, so put them in a base setup file like the following. This file will get imported by other, more bespoke setups.

General setup

import { function register<Data = any>(specifier: string | URL, parentURL?: string | URL, options?: Module.RegisterOptions<Data>): void (+1 overload)
Register a module that exports hooks that customize Node.js module resolution and loading behavior. See [Customization hooks](https://nodejs.org/docs/latest-v22.x/api/module.html#customization-hooks). This feature requires `--allow-worker` if used with the [Permission Model](https://nodejs.org/docs/latest-v22.x/api/permissions.html#permission-model).
@sincev20.6.0, v18.19.0@paramspecifier Customization hooks to be registered; this should be the same string that would be passed to `import()`, except that if it is relative, it is resolved relative to `parentURL`.@paramparentURL f you want to resolve `specifier` relative to a base URL, such as `import.meta.url`, you can pass that URL here.
register
} from 'node:module';
register<any>(specifier: string | URL, parentURL?: string | URL, options?: Module.RegisterOptions<any> | undefined): void (+1 overload)
Register a module that exports hooks that customize Node.js module resolution and loading behavior. See [Customization hooks](https://nodejs.org/docs/latest-v22.x/api/module.html#customization-hooks). This feature requires `--allow-worker` if used with the [Permission Model](https://nodejs.org/docs/latest-v22.x/api/permissions.html#permission-model).
@sincev20.6.0, v18.19.0@paramspecifier Customization hooks to be registered; this should be the same string that would be passed to `import()`, except that if it is relative, it is resolved relative to `parentURL`.@paramparentURL f you want to resolve `specifier` relative to a base URL, such as `import.meta.url`, you can pass that URL here.
register
('some-typescript-loader');
// TypeScript is supported hereafter // BUT other test/setup.*.mjs files still must be plain JavaScript!

Then for each setup, create a dedicated setup file (ensuring the base setup.mjs file is imported within each). There are a number of reasons to isolate the setups, but the most obvious reason is YAGNI + performance: much of what you may be setting up are environment-specific mocks/stubs, which can be quite expensive and will slow down test runs. You want to avoid those costs (literal money you pay to CI, time waiting for tests to finish, etc) when you don't need them.

Each example below was taken from real-world projects; they may not be appropriate/applicable to yours, but each demonstrate general concepts that are broadly applicable.

Dynamically generating test cases

Some times, you may want to dynamically generate test-cases. For instance, you want to test the same thing across a bunch of files. This is possible, albeit slightly arcane. You must use test (you cannot use describe) + testContext.test:

Simple example

import 
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
from 'node:assert/strict';
import { function test(name?: string, fn?: test.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
test
} from 'node:test';
import { import detectOsInUserAgentdetectOsInUserAgent } from ''; const
const userAgents: {
    ua: string;
    os: string;
}[]
userAgents
= [
{ ua: stringua: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3', os: stringos: 'WIN', }, // … ]; function test(name?: string, options?: test.TestOptions, fn?: test.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
test
('Detect OS via user-agent', { test.TestOptions.concurrency?: number | boolean | undefined
If a number is provided, then that many tests would run in parallel. If truthy, it would run (number of cpu cores - 1) tests in parallel. For subtests, it will be `Infinity` tests in parallel. If falsy, it would only run one test at a time. If unspecified, subtests inherit this value from their parent.
@defaultfalse
concurrency
: true }, t: test.TestContextt => {
for (const { const os: stringos, const ua: stringua } of
const userAgents: {
    ua: string;
    os: string;
}[]
userAgents
) {
t: test.TestContextt.test.TestContext.test: (name?: string, fn?: test.TestFn) => Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
test
(const ua: stringua, () =>
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
.equal: <string>(actual: unknown, expected: string, message?: string | Error) => asserts actual is string
Tests strict equality between the `actual` and `expected` parameters as determined by [`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). ```js import assert from 'node:assert/strict'; assert.strictEqual(1, 2); // AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal: // // 1 !== 2 assert.strictEqual(1, 1); // OK assert.strictEqual('Hello foobar', 'Hello World!'); // AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal: // + actual - expected // // + 'Hello foobar' // - 'Hello World!' // ^ const apples = 1; const oranges = 2; assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`); // AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2 assert.strictEqual(1, '1', new TypeError('Inputs are not identical')); // TypeError: Inputs are not identical ``` If the values are not strictly equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`.
@sincev0.1.21
equal
(import detectOsInUserAgentdetectOsInUserAgent(const ua: stringua), const os: stringos));
} });

Advanced example

import 
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
from 'node:assert/strict';
import { function test(name?: string, fn?: test.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
test
} from 'node:test';
import { import getWorkspacePJSONsgetWorkspacePJSONs } from './getWorkspacePJSONs.mjs'; const const requiredKeywords: string[]requiredKeywords = ['node.js', 'sliced bread']; function test(name?: string, options?: test.TestOptions, fn?: test.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
test
('Check package.jsons', { test.TestOptions.concurrency?: number | boolean | undefined
If a number is provided, then that many tests would run in parallel. If truthy, it would run (number of cpu cores - 1) tests in parallel. For subtests, it will be `Infinity` tests in parallel. If falsy, it would only run one test at a time. If unspecified, subtests inherit this value from their parent.
@defaultfalse
concurrency
: true }, async t: test.TestContextt => {
const const pjsons: anypjsons = await import getWorkspacePJSONsgetWorkspacePJSONs(); for (const const pjson: anypjson of const pjsons: anypjsons) { // ⚠️ `t.test`, NOT `test` t: test.TestContextt.test.TestContext.test: (name?: string, fn?: test.TestFn) => Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
test
(`Ensure fields are properly set: ${const pjson: anypjson.name}`, () => {
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
.partialDeepStrictEqual: (actual: unknown, expected: unknown, message?: string | Error) => void
Tests for partial deep equality between the `actual` and `expected` parameters. "Deep" equality means that the enumerable "own" properties of child objects are recursively evaluated also by the following rules. "Partial" equality means that only properties that exist on the `expected` parameter are going to be compared. This method always passes the same test cases as `assert.deepStrictEqual()`, behaving as a super set of it.
@sincev22.13.0
partialDeepStrictEqual
(const pjson: anypjson.keywords, const requiredKeywords: string[]requiredKeywords);
}); } });

Note: Prior to version 23.8.0, the setup is quite different because testContext.test was not automatically awaited.

ServiceWorker tests

ServiceWorkerGlobalScope contains very specific APIs that don't exist in other environments, and some of its APIs are seemingly similar to others (ex fetch) but have augmented behaviour. You do not want these to spill into unrelated tests.

import { function beforeEach(fn?: test.HookFn, options?: test.HookOptions): void
This function creates a hook that runs before each test in the current suite. ```js describe('tests', async () => { beforeEach(() => console.log('about to run a test')); it('is a subtest', () => { assert.ok('some relevant assertion here'); }); }); ```
@sincev18.8.0, v16.18.0@paramfn The hook function. If the hook uses callbacks, the callback function is passed as the second argument.@paramoptions Configuration options for the hook.
beforeEach
} from 'node:test';
import { import ServiceWorkerGlobalScopeServiceWorkerGlobalScope } from './globals/ServiceWorkerGlobalScope.js'; import './setup.mjs'; // 💡 function beforeEach(fn?: test.HookFn, options?: test.HookOptions): void
This function creates a hook that runs before each test in the current suite. ```js describe('tests', async () => { beforeEach(() => console.log('about to run a test')); it('is a subtest', () => { assert.ok('some relevant assertion here'); }); }); ```
@sincev18.8.0, v16.18.0@paramfn The hook function. If the hook uses callbacks, the callback function is passed as the second argument.@paramoptions Configuration options for the hook.
beforeEach
(function globalSWBeforeEach(): voidglobalSWBeforeEach);
function function globalSWBeforeEach(): voidglobalSWBeforeEach() { module globalThisglobalThis.var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)
self
= new import ServiceWorkerGlobalScopeServiceWorkerGlobalScope();
}
import 
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
from 'node:assert/strict';
import { function describe(name?: string, options?: it.TestOptions, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.
@paramname The name of the suite, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the suite. This supports the same options as {@link test}.@paramfn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object.@returnImmediately fulfilled with `undefined`.@sincev20.13.0
describe
, const mock: it.MockTrackermock, function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
} from 'node:test';
import { import onActivateonActivate } from './onActivate.js'; function describe(name?: string, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.
@paramname The name of the suite, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the suite. This supports the same options as {@link test}.@paramfn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object.@returnImmediately fulfilled with `undefined`.@sincev20.13.0
describe
('ServiceWorker::onActivate()', () => {
const const globalSelf: Window & typeof globalThisglobalSelf = module globalThisglobalThis.var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)
self
;
const const claim: it.Mock<() => Promise<void>>claim = const mock: it.MockTrackermock.test.MockTracker.fn<() => Promise<void>>(original?: (() => Promise<void>) | undefined, options?: it.MockFunctionOptions): it.Mock<() => Promise<void>> (+1 overload)
This function is used to create a mock function. The following example creates a mock function that increments a counter by one on each invocation. The `times` option is used to modify the mock behavior such that the first two invocations add two to the counter instead of one. ```js test('mocks a counting function', (t) => { let cnt = 0; function addOne() { cnt++; return cnt; } function addTwo() { cnt += 2; return cnt; } const fn = t.mock.fn(addOne, addTwo, { times: 2 }); assert.strictEqual(fn(), 2); assert.strictEqual(fn(), 4); assert.strictEqual(fn(), 5); assert.strictEqual(fn(), 6); }); ```
@sincev19.1.0, v18.13.0@paramoriginal An optional function to create a mock on.@paramimplementation An optional function used as the mock implementation for `original`. This is useful for creating mocks that exhibit one behavior for a specified number of calls and then restore the behavior of `original`.@paramoptions Optional configuration options for the mock function.@returnThe mocked function. The mocked function contains a special `mock` property, which is an instance of {@link MockFunctionContext}, and can be used for inspecting and changing the behavior of the mocked function.
fn
(async function function (local function) mock__claim(): Promise<void>mock__claim() {});
const const matchAll: it.Mock<() => Promise<void>>matchAll = const mock: it.MockTrackermock.test.MockTracker.fn<() => Promise<void>>(original?: (() => Promise<void>) | undefined, options?: it.MockFunctionOptions): it.Mock<() => Promise<void>> (+1 overload)
This function is used to create a mock function. The following example creates a mock function that increments a counter by one on each invocation. The `times` option is used to modify the mock behavior such that the first two invocations add two to the counter instead of one. ```js test('mocks a counting function', (t) => { let cnt = 0; function addOne() { cnt++; return cnt; } function addTwo() { cnt += 2; return cnt; } const fn = t.mock.fn(addOne, addTwo, { times: 2 }); assert.strictEqual(fn(), 2); assert.strictEqual(fn(), 4); assert.strictEqual(fn(), 5); assert.strictEqual(fn(), 6); }); ```
@sincev19.1.0, v18.13.0@paramoriginal An optional function to create a mock on.@paramimplementation An optional function used as the mock implementation for `original`. This is useful for creating mocks that exhibit one behavior for a specified number of calls and then restore the behavior of `original`.@paramoptions Optional configuration options for the mock function.@returnThe mocked function. The mocked function contains a special `mock` property, which is an instance of {@link MockFunctionContext}, and can be used for inspecting and changing the behavior of the mocked function.
fn
(async function function (local function) mock__matchAll(): Promise<void>mock__matchAll() {});
class class ActivateEventActivateEvent extends
var Event: {
    new (type: string, eventInitDict?: EventInit): Event;
    prototype: Event;
    readonly NONE: 0;
    readonly CAPTURING_PHASE: 1;
    readonly AT_TARGET: 2;
    readonly BUBBLING_PHASE: 3;
}
An event which takes place in the DOM. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event)
Event
{
constructor(...args: any[]args) { super('activate', ...args: any[]args); } } before(() => { module globalThisglobalThis.var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)
self
= {
clients: {
    claim: it.Mock<() => Promise<void>>;
    matchAll: it.Mock<() => Promise<void>>;
}
clients
: { claim: it.Mock<() => Promise<void>>claim, matchAll: it.Mock<() => Promise<void>>matchAll },
}; }); after(() => { var global: typeof globalThisglobal.var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)
self
= const globalSelf: Window & typeof globalThisglobalSelf;
}); function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
('should claim all clients', async () => {
await import onActivateonActivate(new constructor ActivateEvent(...args: any[]): ActivateEventActivateEvent());
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
.equal: <1>(actual: unknown, expected: 1, message?: string | Error) => asserts actual is 1
Tests strict equality between the `actual` and `expected` parameters as determined by [`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). ```js import assert from 'node:assert/strict'; assert.strictEqual(1, 2); // AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal: // // 1 !== 2 assert.strictEqual(1, 1); // OK assert.strictEqual('Hello foobar', 'Hello World!'); // AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal: // + actual - expected // // + 'Hello foobar' // - 'Hello World!' // ^ const apples = 1; const oranges = 2; assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`); // AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2 assert.strictEqual(1, '1', new TypeError('Inputs are not identical')); // TypeError: Inputs are not identical ``` If the values are not strictly equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`.
@sincev0.1.21
equal
(const claim: it.Mock<() => Promise<void>>claim.mock: it.MockFunctionContext<() => Promise<void>>mock.test.MockFunctionContext<() => Promise<void>>.callCount(): number
This function returns the number of times that this mock has been invoked. This function is more efficient than checking `ctx.calls.length` because `ctx.calls` is a getter that creates a copy of the internal call tracking array.
@sincev19.1.0, v18.13.0@returnThe number of times that this mock has been invoked.
callCount
(), 1);
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
.equal: <1>(actual: unknown, expected: 1, message?: string | Error) => asserts actual is 1
Tests strict equality between the `actual` and `expected` parameters as determined by [`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). ```js import assert from 'node:assert/strict'; assert.strictEqual(1, 2); // AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal: // // 1 !== 2 assert.strictEqual(1, 1); // OK assert.strictEqual('Hello foobar', 'Hello World!'); // AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal: // + actual - expected // // + 'Hello foobar' // - 'Hello World!' // ^ const apples = 1; const oranges = 2; assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`); // AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2 assert.strictEqual(1, '1', new TypeError('Inputs are not identical')); // TypeError: Inputs are not identical ``` If the values are not strictly equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`.
@sincev0.1.21
equal
(const matchAll: it.Mock<() => Promise<void>>matchAll.mock: it.MockFunctionContext<() => Promise<void>>mock.test.MockFunctionContext<() => Promise<void>>.callCount(): number
This function returns the number of times that this mock has been invoked. This function is more efficient than checking `ctx.calls.length` because `ctx.calls` is a getter that creates a copy of the internal call tracking array.
@sincev19.1.0, v18.13.0@returnThe number of times that this mock has been invoked.
callCount
(), 1);
}); });

Snapshot tests

These were popularised by Jest; now, many libraries implement such functionality, including Node.js as of v22.3.0. There are several use-cases such as verifying component rendering output and Infrastructure as Code config. The concept is the same regardless of use-case.

There is no specific configuration required except enabling the feature via --experimental-test-snapshots. But to demonstrate the optional configuration, you would probably add something like the following to one of your existing test config files.

By default, node generates a filename that is incompatible with syntax highlighting detection: .js.snapshot. The generated file is actually a CJS file, so a more appropriate file name would end with .snapshot.cjs (or more succinctly .snap.cjs as below); this will also handle better in ESM projects.

import { function (method) basename(path: string, suffix?: string): string
Return the last portion of a path. Similar to the Unix basename command. Often used to extract the file name from a fully qualified path.
@parampath the path to evaluate.@paramsuffix optionally, an extension to remove from the result.@throws{TypeError} if `path` is not a string or if `ext` is given and is not a string.
basename
, function (method) dirname(path: string): string
Return the directory name of a path. Similar to the Unix dirname command.
@parampath the path to evaluate.@throws{TypeError} if `path` is not a string.
dirname
, function (method) extname(path: string): string
Return the extension of the path, from the last '.' to end of string in the last portion of the path. If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string.
@parampath the path to evaluate.@throws{TypeError} if `path` is not a string.
extname
, function (method) join(...paths: string[]): string
Join all arguments together and normalize the resulting path.
@parampaths paths to join.@throws{TypeError} if any of the path segments is not a string.
join
} from 'node:path';
import { snapshot } from 'node:test'; snapshot.function test.snapshot.setResolveSnapshotPath(fn: (path: string | undefined) => string): void
This function is used to set a custom resolver for the location of the snapshot file used for snapshot testing. By default, the snapshot filename is the same as the entry point filename with `.snapshot` appended.
@sincev22.3.0@paramfn A function used to compute the location of the snapshot file. The function receives the path of the test file as its only argument. If the test is not associated with a file (for example in the REPL), the input is undefined. `fn()` must return a string specifying the location of the snapshot file.
setResolveSnapshotPath
(function generateSnapshotPath(testFilePath: string): string
@paramtestFilePath '/tmp/foo.test.js'@returns'/tmp/foo.test.snap.cjs'
generateSnapshotPath
);
/** * @param {string} testFilePath '/tmp/foo.test.js' * @returns {string} '/tmp/foo.test.snap.cjs' */ function function generateSnapshotPath(testFilePath: string): string
@paramtestFilePath '/tmp/foo.test.js'@returns'/tmp/foo.test.snap.cjs'
generateSnapshotPath
(testFilePath: string
'/tmp/foo.test.js'
@paramtestFilePath '/tmp/foo.test.js'
testFilePath
) {
const const ext: stringext = function extname(path: string): string
Return the extension of the path, from the last '.' to end of string in the last portion of the path. If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string.
@parampath the path to evaluate.@throws{TypeError} if `path` is not a string.
extname
(testFilePath: string
'/tmp/foo.test.js'
@paramtestFilePath '/tmp/foo.test.js'
testFilePath
);
const const filename: stringfilename = function basename(path: string, suffix?: string): string
Return the last portion of a path. Similar to the Unix basename command. Often used to extract the file name from a fully qualified path.
@parampath the path to evaluate.@paramsuffix optionally, an extension to remove from the result.@throws{TypeError} if `path` is not a string or if `ext` is given and is not a string.
basename
(testFilePath: string
'/tmp/foo.test.js'
@paramtestFilePath '/tmp/foo.test.js'
testFilePath
, const ext: stringext);
const const base: stringbase = function dirname(path: string): string
Return the directory name of a path. Similar to the Unix dirname command.
@parampath the path to evaluate.@throws{TypeError} if `path` is not a string.
dirname
(testFilePath: string
'/tmp/foo.test.js'
@paramtestFilePath '/tmp/foo.test.js'
testFilePath
);
return function join(...paths: string[]): string
Join all arguments together and normalize the resulting path.
@parampaths paths to join.@throws{TypeError} if any of the path segments is not a string.
join
(const base: stringbase, `${const filename: stringfilename}.snap.cjs`);
}

The example below demonstrates snapshot testing with testing library for UI components; note the two different ways of accessing assert.snapshot):

import { function describe(name?: string, options?: it.TestOptions, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.
@paramname The name of the suite, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the suite. This supports the same options as {@link test}.@paramfn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object.@returnImmediately fulfilled with `undefined`.@sincev20.13.0
describe
, function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
} from 'node:test';
import { import prettyDOMprettyDOM } from '@testing-library/dom'; import { import renderrender } from '@testing-library/react'; // Any framework (ex svelte) import { import SomeComponentSomeComponent } from './SomeComponent.jsx'; function describe(name?: string, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.
@paramname The name of the suite, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the suite. This supports the same options as {@link test}.@paramfn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object.@returnImmediately fulfilled with `undefined`.@sincev20.13.0
describe
('<SomeComponent>', () => {
// For people preferring "fat-arrow" syntax, the following is probably better for consistency function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
('should render defaults when no props are provided', t: it.TestContextt => {
const const component: anycomponent = import renderrender(<import SomeComponentSomeComponent />).container.firstChild; t: it.TestContextt.test.TestContext.assert: it.TestContextAssert
An object containing assertion methods bound to the test context. The top-level functions from the `node:assert` module are exposed here for the purpose of creating test plans. **Note:** Some of the functions from `node:assert` contain type assertions. If these are called via the TestContext `assert` object, then the context parameter in the test's function signature **must be explicitly typed** (ie. the parameter must have a type annotation), otherwise an error will be raised by the TypeScript compiler: ```ts import { test, type TestContext } from 'node:test'; // The test function's context parameter must have a type annotation. test('example', (t: TestContext) => { t.assert.deepStrictEqual(actual, expected); }); // Omitting the type annotation will result in a compilation error. test('example', t => { t.assert.deepStrictEqual(actual, expected); // Error: 't' needs an explicit type annotation. }); ```
@sincev22.2.0, v20.15.0
assert
.test.TestContextAssert.snapshot(value: any, options?: it.AssertSnapshotOptions): void
This function implements assertions for snapshot testing. ```js test('snapshot test with default serialization', (t) => { t.assert.snapshot({ value1: 1, value2: 2 }); }); test('snapshot test with custom serialization', (t) => { t.assert.snapshot({ value3: 3, value4: 4 }, { serializers: [(value) => JSON.stringify(value)] }); }); ```
@sincev22.3.0@paramvalue A value to serialize to a string. If Node.js was started with the [`--test-update-snapshots`](https://nodejs.org/docs/latest-v22.x/api/cli.html#--test-update-snapshots) flag, the serialized value is written to the snapshot file. Otherwise, the serialized value is compared to the corresponding value in the existing snapshot file.
snapshot
(import prettyDOMprettyDOM(const component: anycomponent));
}); function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
('should consume `foo` when provided', function () {
const const component: anycomponent = import renderrender(<import SomeComponentSomeComponent foo: stringfoo="bar" />).container.firstChild; this.assert.snapshot(import prettyDOMprettyDOM(const component: anycomponent)); // `this` works only when `function` is used (not "fat arrow"). }); });

⚠️ assert.snapshot comes from the test's context (t or this), not node:assert. This is necessary because the test context has access to scope that is impossible for node:assert (you would have to manually provide it every time assert.snapshot is used, like snapshot(this, value), which would be rather tedious).

Unit tests

Unit tests are the simplest tests and generally require relatively nothing special. The vast majority of your tests will likely be unit tests, so it is important to keep this setup minimal because a small decrease to setup performance will magnify and cascade.

import { function register<Data = any>(specifier: string | URL, parentURL?: string | URL, options?: Module.RegisterOptions<Data>): void (+1 overload)
Register a module that exports hooks that customize Node.js module resolution and loading behavior. See [Customization hooks](https://nodejs.org/docs/latest-v22.x/api/module.html#customization-hooks). This feature requires `--allow-worker` if used with the [Permission Model](https://nodejs.org/docs/latest-v22.x/api/permissions.html#permission-model).
@sincev20.6.0, v18.19.0@paramspecifier Customization hooks to be registered; this should be the same string that would be passed to `import()`, except that if it is relative, it is resolved relative to `parentURL`.@paramparentURL f you want to resolve `specifier` relative to a base URL, such as `import.meta.url`, you can pass that URL here.
register
} from 'node:module';
import './setup.mjs'; // 💡 register<any>(specifier: string | URL, parentURL?: string | URL, options?: Module.RegisterOptions<any> | undefined): void (+1 overload)
Register a module that exports hooks that customize Node.js module resolution and loading behavior. See [Customization hooks](https://nodejs.org/docs/latest-v22.x/api/module.html#customization-hooks). This feature requires `--allow-worker` if used with the [Permission Model](https://nodejs.org/docs/latest-v22.x/api/permissions.html#permission-model).
@sincev20.6.0, v18.19.0@paramspecifier Customization hooks to be registered; this should be the same string that would be passed to `import()`, except that if it is relative, it is resolved relative to `parentURL`.@paramparentURL f you want to resolve `specifier` relative to a base URL, such as `import.meta.url`, you can pass that URL here.
register
('some-plaintext-loader');
// plain-text files like graphql can now be imported: // import GET_ME from 'get-me.gql'; GET_ME = '
import 
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
from 'node:assert/strict';
import { function describe(name?: string, options?: it.TestOptions, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.
@paramname The name of the suite, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the suite. This supports the same options as {@link test}.@paramfn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object.@returnImmediately fulfilled with `undefined`.@sincev20.13.0
describe
, function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
} from 'node:test';
import { import CatCat } from './Cat.js'; import { import FishFish } from './Fish.js'; import { import PlasticPlastic } from './Plastic.js'; function describe(name?: string, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.
@paramname The name of the suite, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the suite. This supports the same options as {@link test}.@paramfn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object.@returnImmediately fulfilled with `undefined`.@sincev20.13.0
describe
('Cat', () => {
function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
('should eat fish', () => {
const const cat: anycat = new import CatCat(); const const fish: anyfish = new import FishFish();
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
.doesNotThrow: (block: () => unknown, message?: string | Error) => void (+1 overload)
Asserts that the function `fn` does not throw an error. Using `assert.doesNotThrow()` is actually not useful because there is no benefit in catching an error and then rethrowing it. Instead, consider adding a comment next to the specific code path that should not throw and keep error messages as expressive as possible. When `assert.doesNotThrow()` is called, it will immediately call the `fn` function. If an error is thrown and it is the same type as that specified by the `error` parameter, then an `AssertionError` is thrown. If the error is of a different type, or if the `error` parameter is undefined, the error is propagated back to the caller. If specified, `error` can be a [`Class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes), [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions), or a validation function. See {@link throws } for more details. The following, for instance, will throw the `TypeError` because there is no matching error type in the assertion: ```js import assert from 'node:assert/strict'; assert.doesNotThrow( () => { throw new TypeError('Wrong value'); }, SyntaxError, ); ``` However, the following will result in an `AssertionError` with the message 'Got unwanted exception...': ```js import assert from 'node:assert/strict'; assert.doesNotThrow( () => { throw new TypeError('Wrong value'); }, TypeError, ); ``` If an `AssertionError` is thrown and a value is provided for the `message` parameter, the value of `message` will be appended to the `AssertionError` message: ```js import assert from 'node:assert/strict'; assert.doesNotThrow( () => { throw new TypeError('Wrong value'); }, /Wrong value/, 'Whoops', ); // Throws: AssertionError: Got unwanted exception: Whoops ```
@sincev0.1.21
doesNotThrow
(() => const cat: anycat.eat(const fish: anyfish));
}); function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
('should NOT eat plastic', () => {
const const cat: anycat = new import CatCat(); const const plastic: anyplastic = new import PlasticPlastic();
const assert: Omit<typeof assert, "equal" | "notEqual" | "deepEqual" | "notDeepEqual" | "ok" | "strictEqual" | "deepStrictEqual" | "ifError" | "strict" | "AssertionError"> & {
    ...;
}
In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, {@link deepEqual } will behave like {@link deepStrictEqual } . In strict assertion mode, error messages for objects display a diff. In legacy assertion mode, error messages for objects display the objects, often truncated. To use strict assertion mode: ```js import { strict as assert } from 'node:assert'; import assert from 'node:assert/strict'; ``` Example error diff: ```js import { strict as assert } from 'node:assert'; assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected ... Lines skipped // // [ // [ // ... // 2, // + 3 // - '3' // ], // ... // 5 // ] ``` To deactivate the colors, use the `NO_COLOR` or `NODE_DISABLE_COLORS` environment variables. This will also deactivate the colors in the REPL. For more on color support in terminal environments, read the tty `getColorDepth()` documentation.
@sincev15.0.0, v13.9.0, v12.16.2, v9.9.0
assert
.throws: (block: () => unknown, message?: string | Error) => void (+1 overload)
Expects the function `fn` to throw an error. If specified, `error` can be a [`Class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes), [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions), a validation function, a validation object where each property will be tested for strict deep equality, or an instance of error where each property will be tested for strict deep equality including the non-enumerable `message` and `name` properties. When using an object, it is also possible to use a regular expression, when validating against a string property. See below for examples. If specified, `message` will be appended to the message provided by the `AssertionError` if the `fn` call fails to throw or in case the error validation fails. Custom validation object/error instance: ```js import assert from 'node:assert/strict'; const err = new TypeError('Wrong value'); err.code = 404; err.foo = 'bar'; err.info = { nested: true, baz: 'text', }; err.reg = /abc/i; assert.throws( () => { throw err; }, { name: 'TypeError', message: 'Wrong value', info: { nested: true, baz: 'text', }, // Only properties on the validation object will be tested for. // Using nested objects requires all properties to be present. Otherwise // the validation is going to fail. }, ); // Using regular expressions to validate error properties: assert.throws( () => { throw err; }, { // The `name` and `message` properties are strings and using regular // expressions on those will match against the string. If they fail, an // error is thrown. name: /^TypeError$/, message: /Wrong/, foo: 'bar', info: { nested: true, // It is not possible to use regular expressions for nested properties! baz: 'text', }, // The `reg` property contains a regular expression and only if the // validation object contains an identical regular expression, it is going // to pass. reg: /abc/i, }, ); // Fails due to the different `message` and `name` properties: assert.throws( () => { const otherErr = new Error('Not found'); // Copy all enumerable properties from `err` to `otherErr`. for (const [key, value] of Object.entries(err)) { otherErr[key] = value; } throw otherErr; }, // The error's `message` and `name` properties will also be checked when using // an error as validation object. err, ); ``` Validate instanceof using constructor: ```js import assert from 'node:assert/strict'; assert.throws( () => { throw new Error('Wrong value'); }, Error, ); ``` Validate error message using [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions): Using a regular expression runs `.toString` on the error object, and will therefore also include the error name. ```js import assert from 'node:assert/strict'; assert.throws( () => { throw new Error('Wrong value'); }, /^Error: Wrong value$/, ); ``` Custom error validation: The function must return `true` to indicate all internal validations passed. It will otherwise fail with an `AssertionError`. ```js import assert from 'node:assert/strict'; assert.throws( () => { throw new Error('Wrong value'); }, (err) => { assert(err instanceof Error); assert(/value/.test(err)); // Avoid returning anything from validation functions besides `true`. // Otherwise, it's not clear what part of the validation failed. Instead, // throw an error about the specific validation that failed (as done in this // example) and add as much helpful debugging information to that error as // possible. return true; }, 'unexpected error', ); ``` `error` cannot be a string. If a string is provided as the second argument, then `error` is assumed to be omitted and the string will be used for `message` instead. This can lead to easy-to-miss mistakes. Using the same message as the thrown error message is going to result in an `ERR_AMBIGUOUS_ARGUMENT` error. Please read the example below carefully if using a string as the second argument gets considered: ```js import assert from 'node:assert/strict'; function throwingFirst() { throw new Error('First'); } function throwingSecond() { throw new Error('Second'); } function notThrowing() {} // The second argument is a string and the input function threw an Error. // The first case will not throw as it does not match for the error message // thrown by the input function! assert.throws(throwingFirst, 'Second'); // In the next example the message has no benefit over the message from the // error and since it is not clear if the user intended to actually match // against the error message, Node.js throws an `ERR_AMBIGUOUS_ARGUMENT` error. assert.throws(throwingSecond, 'Second'); // TypeError [ERR_AMBIGUOUS_ARGUMENT] // The string is only used (as message) in case the function does not throw: assert.throws(notThrowing, 'Second'); // AssertionError [ERR_ASSERTION]: Missing expected exception: Second // If it was intended to match for the error message do this instead: // It does not throw because the error messages match. assert.throws(throwingSecond, /Second$/); // If the error message does not match, an AssertionError is thrown. assert.throws(throwingFirst, /Second$/); // AssertionError [ERR_ASSERTION] ``` Due to the confusing error-prone notation, avoid a string as the second argument.
@sincev0.1.21
throws
(() => const cat: anycat.eat(const plastic: anyplastic));
}); });

User Interface tests

UI tests generally require a DOM, and possibly other browser-specific APIs (such as IndexedDb used below). These tend to be very complicated and expensive to setup.

If you use an API like IndexedDb but it's very isolated, a global mock like below is perhaps not the way to go. Instead, perhaps move this beforeEach into the specific test where IndexedDb will be accessed. Note that if the module accessing IndexedDb (or whatever) is itself widely accessed, either mock that module (probably the better option), or do keep this here.

import { function register<Data = any>(specifier: string | URL, parentURL?: string | URL, options?: Module.RegisterOptions<Data>): void (+1 overload)
Register a module that exports hooks that customize Node.js module resolution and loading behavior. See [Customization hooks](https://nodejs.org/docs/latest-v22.x/api/module.html#customization-hooks). This feature requires `--allow-worker` if used with the [Permission Model](https://nodejs.org/docs/latest-v22.x/api/permissions.html#permission-model).
@sincev20.6.0, v18.19.0@paramspecifier Customization hooks to be registered; this should be the same string that would be passed to `import()`, except that if it is relative, it is resolved relative to `parentURL`.@paramparentURL f you want to resolve `specifier` relative to a base URL, such as `import.meta.url`, you can pass that URL here.
register
} from 'node:module';
// ⚠️ Ensure only 1 instance of JSDom is instantiated; multiples will lead to many 🤬 import import jsdomjsdom from 'global-jsdom'; import './setup.units.mjs'; // 💡 import { import IndexedDbIndexedDb } from './globals/IndexedDb.js'; register<any>(specifier: string | URL, parentURL?: string | URL, options?: Module.RegisterOptions<any> | undefined): void (+1 overload)
Register a module that exports hooks that customize Node.js module resolution and loading behavior. See [Customization hooks](https://nodejs.org/docs/latest-v22.x/api/module.html#customization-hooks). This feature requires `--allow-worker` if used with the [Permission Model](https://nodejs.org/docs/latest-v22.x/api/permissions.html#permission-model).
@sincev20.6.0, v18.19.0@paramspecifier Customization hooks to be registered; this should be the same string that would be passed to `import()`, except that if it is relative, it is resolved relative to `parentURL`.@paramparentURL f you want to resolve `specifier` relative to a base URL, such as `import.meta.url`, you can pass that URL here.
register
('some-css-modules-loader');
import jsdomjsdom(var undefinedundefined, { url: stringurl: 'https://test.example.com', // ⚠️ Failing to specify this will likely lead to many 🤬 }); // Example of how to decorate a global. // JSDOM's `history` does not handle navigation; the following handles most cases. const const pushState: (data: any, unused: string, url?: string | URL | null) => voidpushState = module globalThisglobalThis.
module history
var history: History
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/history)
history
.History.pushState(data: any, unused: string, url?: string | URL | null): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/History/pushState)
pushState
.CallableFunction.bind<(data: any, unused: string, url?: string | URL | null) => void>(this: (data: any, unused: string, url?: string | URL | null) => void, thisArg: unknown): (data: any, unused: string, url?: string | URL | null) => void (+1 overload)
For a given function, creates a bound function that has the same body as the original function. The this object of the bound function is associated with the specified object, and has the specified initial parameters.
@paramthisArg The object to be used as the this object.
bind
(module globalThisglobalThis.
module history
var history: History
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/history)
history
);
module globalThisglobalThis.
module history
var history: History
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/history)
history
.History.pushState(data: any, unused: string, url?: string | URL | null): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/History/pushState)
pushState
= function function (local function) mock_pushState(data: any, unused: any, url: any): voidmock_pushState(data: anydata, unused: anyunused, url: anyurl) {
const pushState: (data: any, unused: string, url?: string | URL | null) => void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/History/pushState)
pushState
(data: anydata, unused: anyunused, url: anyurl);
module globalThisglobalThis.var location: Location
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/location)
location
.Location.assign(url: string | URL): void
Navigates to the given URL. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Location/assign)
assign
(url: anyurl);
}; beforeEach(function globalUIBeforeEach(): voidglobalUIBeforeEach); function function globalUIBeforeEach(): voidglobalUIBeforeEach() { module globalThisglobalThis.indexedDb = new import IndexedDbIndexedDb(); }

You can have 2 different levels of UI tests: a unit-like (wherein externals & dependencies are mocked) and a more end-to-end (where only externals like IndexedDb are mocked but the rest of the chain is real). The former is generally the purer option, and the latter is generally deferred to a fully end-to-end automated usability test via something like Playwright or Puppeteer. Below is an example of the former.

import { function before(fn?: it.HookFn, options?: it.HookOptions): void
This function creates a hook that runs before executing a suite. ```js describe('tests', async () => { before(() => console.log('about to run some test')); it('is a subtest', () => { assert.ok('some relevant assertion here'); }); }); ```
@sincev18.8.0, v16.18.0@paramfn The hook function. If the hook uses callbacks, the callback function is passed as the second argument.@paramoptions Configuration options for the hook.
before
, function describe(name?: string, options?: it.TestOptions, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.
@paramname The name of the suite, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the suite. This supports the same options as {@link test}.@paramfn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object.@returnImmediately fulfilled with `undefined`.@sincev20.13.0
describe
, const mock: it.MockTrackermock, function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
} from 'node:test';
import { import screenscreen } from '@testing-library/dom'; import { import renderrender } from '@testing-library/react'; // Any framework (ex svelte) // ⚠️ Note that SomeOtherComponent is NOT a static import; // this is necessary in order to facilitate mocking its own imports. function describe(name?: string, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.
@paramname The name of the suite, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the suite. This supports the same options as {@link test}.@paramfn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object.@returnImmediately fulfilled with `undefined`.@sincev20.13.0
describe
('<SomeOtherComponent>', () => {
let let SomeOtherComponent: anySomeOtherComponent; let let calcSomeValue: anycalcSomeValue; function before(fn?: it.HookFn, options?: it.HookOptions): void
This function creates a hook that runs before executing a suite. ```js describe('tests', async () => { before(() => console.log('about to run some test')); it('is a subtest', () => { assert.ok('some relevant assertion here'); }); }); ```
@sincev18.8.0, v16.18.0@paramfn The hook function. If the hook uses callbacks, the callback function is passed as the second argument.@paramoptions Configuration options for the hook.
before
(async () => {
// ⚠️ Sequence matters: the mock must be set up BEFORE its consumer is imported. // Requires the `--experimental-test-module-mocks` be set. let calcSomeValue: anycalcSomeValue = const mock: it.MockTrackermock.test.MockTracker.module(specifier: string, options?: it.MockModuleOptions): it.MockModuleContext
This function is used to mock the exports of ECMAScript modules, CommonJS modules, and Node.js builtin modules. Any references to the original module prior to mocking are not impacted. Only available through the [--experimental-test-module-mocks](https://nodejs.org/api/cli.html#--experimental-test-module-mocks) flag.
@sincev22.3.0@experimental@paramspecifier A string identifying the module to mock.@paramoptions Optional configuration options for the mock module.
module
('./calcSomeValue.js', {
calcSomeValue: it.Mock<(...args: any[]) => undefined>calcSomeValue: const mock: it.MockTrackermock.test.MockTracker.fn<(...args: any[]) => undefined>(original?: ((...args: any[]) => undefined) | undefined, options?: it.MockFunctionOptions): it.Mock<(...args: any[]) => undefined> (+1 overload)
This function is used to create a mock function. The following example creates a mock function that increments a counter by one on each invocation. The `times` option is used to modify the mock behavior such that the first two invocations add two to the counter instead of one. ```js test('mocks a counting function', (t) => { let cnt = 0; function addOne() { cnt++; return cnt; } function addTwo() { cnt += 2; return cnt; } const fn = t.mock.fn(addOne, addTwo, { times: 2 }); assert.strictEqual(fn(), 2); assert.strictEqual(fn(), 4); assert.strictEqual(fn(), 5); assert.strictEqual(fn(), 6); }); ```
@sincev19.1.0, v18.13.0@paramoriginal An optional function to create a mock on.@paramimplementation An optional function used as the mock implementation for `original`. This is useful for creating mocks that exhibit one behavior for a specified number of calls and then restore the behavior of `original`.@paramoptions Optional configuration options for the mock function.@returnThe mocked function. The mocked function contains a special `mock` property, which is an instance of {@link MockFunctionContext}, and can be used for inspecting and changing the behavior of the mocked function.
fn
(),
}); ({ type SomeOtherComponent: anySomeOtherComponent } = await import('./SomeOtherComponent.jsx')); }); function describe(name?: string, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.
@paramname The name of the suite, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the suite. This supports the same options as {@link test}.@paramfn The suite function declaring nested tests and suites. The first argument to this function is a {@link SuiteContext} object.@returnImmediately fulfilled with `undefined`.@sincev20.13.0
describe
('when calcSomeValue fails', () => {
// This you would not want to handle with a snapshot because that would be brittle: // When inconsequential updates are made to the error message, // the snapshot test would erroneously fail // (and the snapshot would need to be updated for no real value). function it(name?: string, fn?: it.TestFn): Promise<void> (+3 overloads)
The `test()` function is the value imported from the `test` module. Each invocation of this function results in reporting the test to the `TestsStream`. The `TestContext` object passed to the `fn` argument can be used to perform actions related to the current test. Examples include skipping the test, adding additional diagnostic information, or creating subtests. `test()` returns a `Promise` that fulfills once the test completes. if `test()` is called within a suite, it fulfills immediately. The return value can usually be discarded for top level tests. However, the return value from subtests should be used to prevent the parent test from finishing first and cancelling the subtest as shown in the following example. ```js test('top level test', async (t) => { // The setTimeout() in the following subtest would cause it to outlive its // parent test if 'await' is removed on the next line. Once the parent test // completes, it will cancel any outstanding subtests. await t.test('longer running subtest', async (t) => { return new Promise((resolve, reject) => { setTimeout(resolve, 1000); }); }); }); ``` The `timeout` option can be used to fail the test if it takes longer than `timeout` milliseconds to complete. However, it is not a reliable mechanism for canceling tests because a running test might block the application thread and thus prevent the scheduled cancellation.
@sincev18.0.0, v16.17.0@paramname The name of the test, which is displayed when reporting test results. Defaults to the `name` property of `fn`, or `'<anonymous>'` if `fn` does not have a name.@paramoptions Configuration options for the test.@paramfn The function under test. The first argument to this function is a {@link TestContext } object. If the test uses callbacks, the callback function is passed as the second argument.@returnFulfilled with `undefined` once the test completes, or immediately if the test runs within a suite.
it
('should fail gracefully by displaying a pretty error', () => {
let calcSomeValue: anycalcSomeValue.mockImplementation(function function (local function) mock__calcSomeValue(): nullmock__calcSomeValue() { return null; }); import renderrender(<let SomeOtherComponent: anySomeOtherComponent />); const const errorMessage: anyerrorMessage = import screenscreen.queryByText('unable'); assert.ok(const errorMessage: anyerrorMessage); }); }); });