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).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).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.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.test } from 'node:test';
import { import detectOsInUserAgent
detectOsInUserAgent } from '…';
const const userAgents: {
ua: string;
os: string;
}[]
userAgents = [
{
ua: string
ua: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3',
os: string
os: '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.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.concurrency: true }, t: test.TestContext
t => {
for (const { const os: string
os, const ua: string
ua } of const userAgents: {
ua: string;
os: string;
}[]
userAgents) {
t: test.TestContext
t.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.test(const ua: string
ua, () => 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.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`.equal(import detectOsInUserAgent
detectOsInUserAgent(const ua: string
ua), const os: string
os));
}
});
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.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.test } from 'node:test';
import { import getWorkspacePJSONs
getWorkspacePJSONs } 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.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.concurrency: true }, async t: test.TestContext
t => {
const const pjsons: any
pjsons = await import getWorkspacePJSONs
getWorkspacePJSONs();
for (const const pjson: any
pjson of const pjsons: any
pjsons) {
// ⚠️ `t.test`, NOT `test`
t: test.TestContext
t.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.test(`Ensure fields are properly set: ${const pjson: any
pjson.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.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.partialDeepStrictEqual(const pjson: any
pjson.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');
});
});
```beforeEach } from 'node:test';
import { import ServiceWorkerGlobalScope
ServiceWorkerGlobalScope } 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');
});
});
```beforeEach(function globalSWBeforeEach(): void
globalSWBeforeEach);
function function globalSWBeforeEach(): void
globalSWBeforeEach() {
module globalThis
globalThis.var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)self = new import ServiceWorkerGlobalScope
ServiceWorkerGlobalScope();
}
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.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.describe, const mock: it.MockTracker
mock, 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.it } from 'node:test';
import { import onActivate
onActivate } from './onActivate.js';
function describe(name?: string, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.describe('ServiceWorker::onActivate()', () => {
const const globalSelf: Window & typeof globalThis
globalSelf = module globalThis
globalThis.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.MockTracker
mock.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);
});
```fn(async function function (local function) mock__claim(): Promise<void>
mock__claim() {});
const const matchAll: it.Mock<() => Promise<void>>
matchAll = const mock: it.MockTracker
mock.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);
});
```fn(async function function (local function) mock__matchAll(): Promise<void>
mock__matchAll() {});
class class ActivateEvent
ActivateEvent 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 globalThis
globalThis.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 globalThis
global.var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)self = const globalSelf: Window & typeof globalThis
globalSelf;
});
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.it('should claim all clients', async () => {
await import onActivate
onActivate(new constructor ActivateEvent(...args: any[]): ActivateEvent
ActivateEvent());
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.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`.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.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.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`.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.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.basename, function (method) dirname(path: string): string
Return the directory name of a path. Similar to the Unix dirname command.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.extname, function (method) join(...paths: string[]): string
Join all arguments together and normalize the resulting path.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.setResolveSnapshotPath(function generateSnapshotPath(testFilePath: string): string
generateSnapshotPath);
/**
* @param {string} testFilePath '/tmp/foo.test.js'
* @returns {string} '/tmp/foo.test.snap.cjs'
*/
function function generateSnapshotPath(testFilePath: string): string
generateSnapshotPath(testFilePath: string
'/tmp/foo.test.js'testFilePath) {
const const ext: string
ext = 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.extname(testFilePath: string
'/tmp/foo.test.js'testFilePath);
const const filename: string
filename = 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.basename(testFilePath: string
'/tmp/foo.test.js'testFilePath, const ext: string
ext);
const const base: string
base = function dirname(path: string): string
Return the directory name of a path. Similar to the Unix dirname command.dirname(testFilePath: string
'/tmp/foo.test.js'testFilePath);
return function join(...paths: string[]): string
Join all arguments together and normalize the resulting path.join(const base: string
base, `${const filename: string
filename}.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.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.it } from 'node:test';
import { import prettyDOM
prettyDOM } from '@testing-library/dom';
import { import render
render } from '@testing-library/react'; // Any framework (ex svelte)
import { import SomeComponent
SomeComponent } from './SomeComponent.jsx';
function describe(name?: string, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.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.it('should render defaults when no props are provided', t: it.TestContext
t => {
const const component: any
component = import render
render(<import SomeComponent
SomeComponent />).container.firstChild;
t: it.TestContext
t.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.
});
```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)]
});
});
```snapshot(import prettyDOM
prettyDOM(const component: any
component));
});
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.it('should consume `foo` when provided', function () {
const const component: any
component = import render
render(<import SomeComponent
SomeComponent foo: string
foo="bar" />).container.firstChild;
this.assert.snapshot(import prettyDOM
prettyDOM(const component: any
component));
// `this` works only when `function` is used (not "fat arrow").
});
});
⚠️
assert.snapshot
comes from the test's context (t
orthis
), notnode:assert
. This is necessary because the test context has access to scope that is impossible fornode:assert
(you would have to manually provide it every timeassert.snapshot
is used, likesnapshot(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).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).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.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.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.it } from 'node:test';
import { import Cat
Cat } from './Cat.js';
import { import Fish
Fish } from './Fish.js';
import { import Plastic
Plastic } from './Plastic.js';
function describe(name?: string, fn?: it.SuiteFn): Promise<void> (+3 overloads)
The `suite()` function is imported from the `node:test` module.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.it('should eat fish', () => {
const const cat: any
cat = new import Cat
Cat();
const const fish: any
fish = new import Fish
Fish();
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.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
```doesNotThrow(() => const cat: any
cat.eat(const fish: any
fish));
});
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.it('should NOT eat plastic', () => {
const const cat: any
cat = new import Cat
Cat();
const const plastic: any
plastic = new import Plastic
Plastic();
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.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.throws(() => const cat: any
cat.eat(const plastic: any
plastic));
});
});
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).register } from 'node:module';
// ⚠️ Ensure only 1 instance of JSDom is instantiated; multiples will lead to many 🤬
import import jsdom
jsdom from 'global-jsdom';
import './setup.units.mjs'; // 💡
import { import IndexedDb
IndexedDb } 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).register('some-css-modules-loader');
import jsdom
jsdom(var undefined
undefined, {
url: string
url: '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) => void
pushState = module globalThis
globalThis.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.bind(module globalThis
globalThis.module history
var history: History
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/history)history);
module globalThis
globalThis.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): void
mock_pushState(data: any
data, unused: any
unused, url: any
url) {
const pushState: (data: any, unused: string, url?: string | URL | null) => void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/History/pushState)pushState(data: any
data, unused: any
unused, url: any
url);
module globalThis
globalThis.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: any
url);
};
beforeEach(function globalUIBeforeEach(): void
globalUIBeforeEach);
function function globalUIBeforeEach(): void
globalUIBeforeEach() {
module globalThis
globalThis.indexedDb = new import IndexedDb
IndexedDb();
}
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');
});
});
```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.describe, const mock: it.MockTracker
mock, 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.it } from 'node:test';
import { import screen
screen } from '@testing-library/dom';
import { import render
render } 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.describe('<SomeOtherComponent>', () => {
let let SomeOtherComponent: any
SomeOtherComponent;
let let calcSomeValue: any
calcSomeValue;
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');
});
});
```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: any
calcSomeValue = const mock: it.MockTracker
mock.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.module('./calcSomeValue.js', {
calcSomeValue: it.Mock<(...args: any[]) => undefined>
calcSomeValue: const mock: it.MockTracker
mock.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);
});
```fn(),
});
({ type SomeOtherComponent: any
SomeOtherComponent } = 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.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.it('should fail gracefully by displaying a pretty error', () => {
let calcSomeValue: any
calcSomeValue.mockImplementation(function function (local function) mock__calcSomeValue(): null
mock__calcSomeValue() {
return null;
});
import render
render(<let SomeOtherComponent: any
SomeOtherComponent />);
const const errorMessage: any
errorMessage = import screen
screen.queryByText('unable');
assert.ok(const errorMessage: any
errorMessage);
});
});
});