From 480711f37b775a8d7ce3812e8ba905cb1e7aaf64 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Sat, 1 Aug 2026 18:18:33 -0700 Subject: [PATCH 1/2] doc: formalize fn/name as part of TestOptions API `TestOptions` as provided to `node:test`'s `test`/`it` supports both `name` and `fn` as options per its implementation. I'd like to formalize this as part of the public, documented API. ### Motivation I have a use-case for consuming both fields. I'd like to be able to return the result of a function to `test`/`it` without needing to spread the parameters; e.g.: ```js const testOptionsFactory = (opts = {}) => { return { fn: () => { /* .. */ }, name: opts.name }; }; test(testOptionsFactory({name: 'foo'})); ``` If I cannot rely on this behavior, then I would need to instead return an array of parameters and spread them: ```js const testParamsFactory = (opts = {}) => { return opts.name !== undefined ? [opts.name, () => { /* .. */ }] : [() => { /* .. */ }]; }; test(...testParamsFactory({name: 'foo'})); ``` I don't think it's too terribly controversial that the former is more ergonomic than the latter. ### Next Steps Once this lands, I plan to propose the addition of these fields to `@types/node`. Since the fields are not currently publicly documented, I can't justify such a change. Signed-off-by: Christopher Hiller --- doc/api/test.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/api/test.md b/doc/api/test.md index ef5fd0bcad61..c18116d981d0 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -1956,6 +1956,10 @@ changes: If the number of assertions run in the test does not match the number specified in the plan, the test will fail. **Default:** `undefined`. + * `fn` {Function|AsyncFunction} The function under test. If provided, it will take + precedence over the `fn` parameter. + * `name` {string} The name of the test. If provided, it will take precedence over the + `name` parameter. * `fn` {Function|AsyncFunction} The function under test. The first argument to this function is a [`TestContext`][] object. If the test uses callbacks, the callback function is passed as the second argument. **Default:** A no-op From 89a7728f4e8733e4aaebc4903b23af8e811c7817 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Sun, 2 Aug 2026 00:03:07 -0700 Subject: [PATCH 2/2] test: add test/it options precedence suite This adds a test suite which proves the behavior of `test`/`it`'s options; specifically how the `name` and `fn` options take precedence over their associated parameters, and how a test can be named and run using only a single "options" parameter. Signed-off-by: Christopher Hiller --- .../parallel/test-runner-option-precedence.js | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/parallel/test-runner-option-precedence.js diff --git a/test/parallel/test-runner-option-precedence.js b/test/parallel/test-runner-option-precedence.js new file mode 100644 index 000000000000..a2b1097b28e8 --- /dev/null +++ b/test/parallel/test-runner-option-precedence.js @@ -0,0 +1,41 @@ +'use strict'; +require('../common'); +const { test, suite } = require('node:test'); + +suite('test runner option precedence', () => { + test( + 'overridden test name', + { name: 'options.name overrides test name', plan: 1 }, + (t) => { + t.assert.strictEqual(t.name, 'options.name overrides test name'); + }, + ); + + test( + 'options.fn overrides test function', + { + fn: (t) => { + t.assert.ok(true); + }, + plan: 1, + }, + (t) => { + t.assert.fail('should not be called'); + }, + ); + + test('options.fn only', { + plan: 1, + fn: (t) => { + t.assert.ok(true); + }, + }); + + test({ + name: 'single parameter options', + plan: 1, + fn: (t) => { + t.assert.ok(true); + }, + }); +});