diff --git a/doc/api/cli.md b/doc/api/cli.md
index 5baf534af1e5c8..cab061c1bf63a3 100644
--- a/doc/api/cli.md
+++ b/doc/api/cli.md
@@ -1086,12 +1086,29 @@ The value given must be a power of two.
### `--test`
Starts the Node.js command line test runner. This flag cannot be combined with
-`--check`, `--eval`, `--interactive`, or the inspector. See the documentation
-on [running tests from the command line][] for more details.
+`--watch-path`, `--check`, `--eval`, `--interactive`, or the inspector.
+See the documentation on [running tests from the command line][]
+for more details.
+
+### `--test-name-pattern`
+
+
+
+A regular expression that configures the test runner to only execute tests
+whose name matches the provided pattern. See the documentation on
+[filtering tests by name][] for more details.
### `--test-only`
@@ -1430,7 +1447,11 @@ will be chosen.
### `--watch`
> Stability: 1 - Experimental
@@ -1464,7 +1485,7 @@ This will turn off watching of required or imported modules, even when used in
combination with `--watch`.
This flag cannot be combined with
-`--check`, `--eval`, `--interactive`, or the REPL.
+`--check`, `--eval`, `--interactive`, `--test`, or the REPL.
```console
$ node --watch-path=./src --watch-path=./tests index.js
@@ -2153,6 +2174,7 @@ done
[debugger]: debugger.md
[debugging security implications]: https://nodejs.org/en/docs/guides/debugging-getting-started/#security-implications
[emit_warning]: process.md#processemitwarningwarning-options
+[filtering tests by name]: test.md#filtering-tests-by-name
[jitless]: https://v8.dev/blog/jitless
[libuv threadpool documentation]: https://docs.libuv.org/en/latest/threadpool.html
[remote code execution]: https://www.owasp.org/index.php/Code_Injection
diff --git a/doc/api/errors.md b/doc/api/errors.md
index a4f6902be32d63..75570302f58828 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -2648,6 +2648,25 @@ An unspecified or non-specific system error has occurred within the Node.js
process. The error object will have an `err.info` object property with
additional details.
+
+
+### `ERR_TAP_LEXER_ERROR`
+
+An error representing a failing lexer state.
+
+
+
+### `ERR_TAP_PARSER_ERROR`
+
+An error representing a failing parser state. Additional information about
+the token causing the error is available via the `cause` property.
+
+
+
+### `ERR_TAP_VALIDATION_ERROR`
+
+This error represents a failed TAP validation.
+
### `ERR_TEST_FAILURE`
diff --git a/doc/api/test.md b/doc/api/test.md
index 7da51afff4b7f9..c5f049cf43313e 100644
--- a/doc/api/test.md
+++ b/doc/api/test.md
@@ -184,7 +184,7 @@ import { describe, it } from 'node:test';
const { describe, it } = require('node:test');
```
-### `only` tests
+## `only` tests
If Node.js is started with the [`--test-only`][] command-line option, it is
possible to skip all top level tests except for a selected subset by passing
@@ -220,6 +220,42 @@ test('this test is not run', () => {
});
```
+## Filtering tests by name
+
+The [`--test-name-pattern`][] command-line option can be used to only run tests
+whose name matches the provided pattern. Test name patterns are interpreted as
+JavaScript regular expressions. The `--test-name-pattern` option can be
+specified multiple times in order to run nested tests. For each test that is
+executed, any corresponding test hooks, such as `beforeEach()`, are also
+run.
+
+Given the following test file, starting Node.js with the
+`--test-name-pattern="test [1-3]"` option would cause the test runner to execute
+`test 1`, `test 2`, and `test 3`. If `test 1` did not match the test name
+pattern, then its subtests would not execute, despite matching the pattern. The
+same set of tests could also be executed by passing `--test-name-pattern`
+multiple times (e.g. `--test-name-pattern="test 1"`,
+`--test-name-pattern="test 2"`, etc.).
+
+```js
+test('test 1', async (t) => {
+ await t.test('test 2');
+ await t.test('test 3');
+});
+
+test('Test 4', async (t) => {
+ await t.test('Test 5');
+ await t.test('test 6');
+});
+```
+
+Test name patterns can also be specified using regular expression literals. This
+allows regular expression flags to be used. In the previous example, starting
+Node.js with `--test-name-pattern="/test [4-5]/i"` would match `Test 4` and
+`Test 5` because the pattern is case-insensitive.
+
+Test name patterns do not change the set of files that the test runner executes.
+
## Extraneous asynchronous activity
Once a test function finishes executing, the TAP results are output as quickly
@@ -236,8 +272,8 @@ top level of the file's TAP output.
The second `setImmediate()` creates an `uncaughtException` event.
`uncaughtException` and `unhandledRejection` events originating from a completed
-test are handled by the `test` module and reported as diagnostic warnings in
-the top level of the file's TAP output.
+test are marked as failed by the `test` module and reported as diagnostic
+warnings in the top level of the file's TAP output.
```js
test('a test that creates asynchronous activity', (t) => {
@@ -255,6 +291,25 @@ test('a test that creates asynchronous activity', (t) => {
});
```
+## Watch mode
+
+
+
+> Stability: 1 - Experimental
+
+The Node.js test runner supports running in watch mode by passing the `--watch` flag:
+
+```bash
+node --test --watch
+```
+
+In watch mode, the test runner will watch for changes to test files and
+their dependencies. When a change is detected, the test runner will
+rerun the tests affected by the change.
+The test runner will continue to run until the process is terminated.
+
## Running tests from the command line
The Node.js test runner can be invoked from the command line by passing the
@@ -316,6 +371,89 @@ Otherwise, the test is considered to be a failure. Test files must be
executable by Node.js, but are not required to use the `node:test` module
internally.
+## Mocking
+
+The `node:test` module supports mocking during testing via a top-level `mock`
+object. The following example creates a spy on a function that adds two numbers
+together. The spy is then used to assert that the function was called as
+expected.
+
+```mjs
+import assert from 'node:assert';
+import { mock, test } from 'node:test';
+
+test('spies on a function', () => {
+ const sum = mock.fn((a, b) => {
+ return a + b;
+ });
+
+ assert.strictEqual(sum.mock.calls.length, 0);
+ assert.strictEqual(sum(3, 4), 7);
+ assert.strictEqual(sum.mock.calls.length, 1);
+
+ const call = sum.mock.calls[0];
+ assert.deepStrictEqual(call.arguments, [3, 4]);
+ assert.strictEqual(call.result, 7);
+ assert.strictEqual(call.error, undefined);
+
+ // Reset the globally tracked mocks.
+ mock.reset();
+});
+```
+
+```cjs
+'use strict';
+const assert = require('node:assert');
+const { mock, test } = require('node:test');
+
+test('spies on a function', () => {
+ const sum = mock.fn((a, b) => {
+ return a + b;
+ });
+
+ assert.strictEqual(sum.mock.calls.length, 0);
+ assert.strictEqual(sum(3, 4), 7);
+ assert.strictEqual(sum.mock.calls.length, 1);
+
+ const call = sum.mock.calls[0];
+ assert.deepStrictEqual(call.arguments, [3, 4]);
+ assert.strictEqual(call.result, 7);
+ assert.strictEqual(call.error, undefined);
+
+ // Reset the globally tracked mocks.
+ mock.reset();
+});
+```
+
+The same mocking functionality is also exposed on the [`TestContext`][] object
+of each test. The following example creates a spy on an object method using the
+API exposed on the `TestContext`. The benefit of mocking via the test context is
+that the test runner will automatically restore all mocked functionality once
+the test finishes.
+
+```js
+test('spies on an object method', (t) => {
+ const number = {
+ value: 5,
+ add(a) {
+ return this.value + a;
+ },
+ };
+
+ t.mock.method(number, 'add');
+ assert.strictEqual(number.add.mock.calls.length, 0);
+ assert.strictEqual(number.add(3), 8);
+ assert.strictEqual(number.add.mock.calls.length, 1);
+
+ const call = number.add.mock.calls[0];
+
+ assert.deepStrictEqual(call.arguments, [3]);
+ assert.strictEqual(call.result, 8);
+ assert.strictEqual(call.target, undefined);
+ assert.strictEqual(call.this, number);
+});
+```
+
## `run([options])`
+
+The `MockFunctionContext` class is used to inspect or manipulate the behavior of
+mocks created via the [`MockTracker`][] APIs.
+
+### `ctx.calls`
+
+
+
+* {Array}
+
+A getter that returns a copy of the internal array used to track calls to the
+mock. Each entry in the array is an object with the following properties.
+
+* `arguments` {Array} An array of the arguments passed to the mock function.
+* `error` {any} If the mocked function threw then this property contains the
+ thrown value. **Default:** `undefined`.
+* `result` {any} The value returned by the mocked function.
+* `stack` {Error} An `Error` object whose stack can be used to determine the
+ callsite of the mocked function invocation.
+* `target` {Function|undefined} If the mocked function is a constructor, this
+ field contains the class being constructed. Otherwise this will be
+ `undefined`.
+* `this` {any} The mocked function's `this` value.
+
+### `ctx.callCount()`
+
+
+
+* Returns: {integer} The number of times that this mock has been invoked.
+
+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.
+
+### `ctx.mockImplementation(implementation)`
+
+
+
+* `implementation` {Function|AsyncFunction} The function to be used as the
+ mock's new implementation.
+
+This function is used to change the behavior of an existing mock.
+
+The following example creates a mock function using `t.mock.fn()`, calls the
+mock function, and then changes the mock implementation to a different function.
+
+```js
+test('changes a mock behavior', (t) => {
+ let cnt = 0;
+
+ function addOne() {
+ cnt++;
+ return cnt;
+ }
+
+ function addTwo() {
+ cnt += 2;
+ return cnt;
+ }
+
+ const fn = t.mock.fn(addOne);
+
+ assert.strictEqual(fn(), 1);
+ fn.mock.mockImplementation(addTwo);
+ assert.strictEqual(fn(), 3);
+ assert.strictEqual(fn(), 5);
+});
+```
+
+### `ctx.mockImplementationOnce(implementation[, onCall])`
+
+
+
+* `implementation` {Function|AsyncFunction} The function to be used as the
+ mock's implementation for the invocation number specified by `onCall`.
+* `onCall` {integer} The invocation number that will use `implementation`. If
+ the specified invocation has already occurred then an exception is thrown.
+ **Default:** The number of the next invocation.
+
+This function is used to change the behavior of an existing mock for a single
+invocation. Once invocation `onCall` has occurred, the mock will revert to
+whatever behavior it would have used had `mockImplementationOnce()` not been
+called.
+
+The following example creates a mock function using `t.mock.fn()`, calls the
+mock function, changes the mock implementation to a different function for the
+next invocation, and then resumes its previous behavior.
+
+```js
+test('changes a mock behavior once', (t) => {
+ let cnt = 0;
+
+ function addOne() {
+ cnt++;
+ return cnt;
+ }
+
+ function addTwo() {
+ cnt += 2;
+ return cnt;
+ }
+
+ const fn = t.mock.fn(addOne);
+
+ assert.strictEqual(fn(), 1);
+ fn.mock.mockImplementationOnce(addTwo);
+ assert.strictEqual(fn(), 3);
+ assert.strictEqual(fn(), 4);
+});
+```
+
+### `ctx.restore()`
+
+
+
+Resets the implementation of the mock function to its original behavior. The
+mock can still be used after calling this function.
+
+## Class: `MockTracker`
+
+
+
+The `MockTracker` class is used to manage mocking functionality. The test runner
+module provides a top level `mock` export which is a `MockTracker` instance.
+Each test also provides its own `MockTracker` instance via the test context's
+`mock` property.
+
+### `mock.fn([original[, implementation]][, options])`
+
+
+
+* `original` {Function|AsyncFunction} An optional function to create a mock on.
+ **Default:** A no-op function.
+* `implementation` {Function|AsyncFunction} 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`. **Default:** The function specified by `original`.
+* `options` {Object} Optional configuration options for the mock function. The
+ following properties are supported:
+ * `times` {integer} The number of times that the mock will use the behavior of
+ `implementation`. Once the mock function has been called `times` times, it
+ will automatically restore the behavior of `original`. This value must be an
+ integer greater than zero. **Default:** `Infinity`.
+* Returns: {Proxy} The mocked function. The mocked function contains a special
+ `mock` property, which is an instance of [`MockFunctionContext`][], and can
+ be used for inspecting and changing the behavior of the mocked function.
+
+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);
+});
+```
+
+### `mock.method(object, methodName[, implementation][, options])`
+
+
+
+* `object` {Object} The object whose method is being mocked.
+* `methodName` {string|symbol} The identifier of the method on `object` to mock.
+ If `object[methodName]` is not a function, an error is thrown.
+* `implementation` {Function|AsyncFunction} An optional function used as the
+ mock implementation for `object[methodName]`. **Default:** The original method
+ specified by `object[methodName]`.
+* `options` {Object} Optional configuration options for the mock method. The
+ following properties are supported:
+ * `getter` {boolean} If `true`, `object[methodName]` is treated as a getter.
+ This option cannot be used with the `setter` option. **Default:** false.
+ * `setter` {boolean} If `true`, `object[methodName]` is treated as a setter.
+ This option cannot be used with the `getter` option. **Default:** false.
+ * `times` {integer} The number of times that the mock will use the behavior of
+ `implementation`. Once the mocked method has been called `times` times, it
+ will automatically restore the original behavior. This value must be an
+ integer greater than zero. **Default:** `Infinity`.
+* Returns: {Proxy} The mocked method. The mocked method contains a special
+ `mock` property, which is an instance of [`MockFunctionContext`][], and can
+ be used for inspecting and changing the behavior of the mocked method.
+
+This function is used to create a mock on an existing object method. The
+following example demonstrates how a mock is created on an existing object
+method.
+
+```js
+test('spies on an object method', (t) => {
+ const number = {
+ value: 5,
+ subtract(a) {
+ return this.value - a;
+ },
+ };
+
+ t.mock.method(number, 'subtract');
+ assert.strictEqual(number.subtract.mock.calls.length, 0);
+ assert.strictEqual(number.subtract(3), 2);
+ assert.strictEqual(number.subtract.mock.calls.length, 1);
+
+ const call = number.subtract.mock.calls[0];
+
+ assert.deepStrictEqual(call.arguments, [3]);
+ assert.strictEqual(call.result, 2);
+ assert.strictEqual(call.error, undefined);
+ assert.strictEqual(call.target, undefined);
+ assert.strictEqual(call.this, number);
+});
+```
+
+### `mock.reset()`
+
+
+
+This function restores the default behavior of all mocks that were previously
+created by this `MockTracker` and disassociates the mocks from the
+`MockTracker` instance. Once disassociated, the mocks can still be used, but the
+`MockTracker` instance can no longer be used to reset their behavior or
+otherwise interact with them.
+
+After each test completes, this function is called on the test context's
+`MockTracker`. If the global `MockTracker` is used extensively, calling this
+function manually is recommended.
+
+### `mock.restoreAll()`
+
+
+
+This function restores the default behavior of all mocks that were previously
+created by this `MockTracker`. Unlike `mock.reset()`, `mock.restoreAll()` does
+not disassociate the mocks from the `MockTracker` instance.
+
## Class: `TapStream`