diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index 2203bbd3497659..f3b9ba26bb610c 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -14,6 +14,7 @@ const { MathMax, Number, NumberPrototypeToFixed, + ObjectAssign, ObjectKeys, ObjectSeal, Promise, @@ -358,11 +359,11 @@ class TestContext { this.#test.todo(message); } - test(name, options, fn) { - const overrides = { + #runTest(name, options, fn, extraOverrides) { + const overrides = ObjectAssign({ __proto__: null, loc: getCallerLocation(), - }; + }, extraOverrides); const { plan } = this.#test; if (plan !== null) { @@ -377,6 +378,14 @@ class TestContext { return subtest.start(); } + test = ObjectAssign((...args) => this.#runTest(...args), { + __proto__: null, + expectFailure: (name, opts, fn) => this.#runTest(name, opts, fn, { __proto__: null, expectFailure: true }), + only: (name, opts, fn) => this.#runTest(name, opts, fn, { __proto__: null, only: true }), + skip: (name, opts, fn) => this.#runTest(name, opts, fn, { __proto__: null, skip: true }), + todo: (name, opts, fn) => this.#runTest(name, opts, fn, { __proto__: null, todo: true }), + }); + before(fn, options) { this.#test.createHook('before', fn, { __proto__: null, diff --git a/test/parallel/test-runner-subtest-methods.js b/test/parallel/test-runner-subtest-methods.js new file mode 100644 index 00000000000000..e43e6d9595268a --- /dev/null +++ b/test/parallel/test-runner-subtest-methods.js @@ -0,0 +1,55 @@ +'use strict'; + +require('../common'); +const assert = require('node:assert'); +const { test } = require('node:test'); +const { isPromise } = require('node:util/types'); + +test('subtest context should have test variants', async (t) => { + assert.strictEqual(typeof t.test, 'function'); + assert.strictEqual(typeof t.test.expectFailure, 'function'); + assert.strictEqual(typeof t.test.only, 'function'); + assert.strictEqual(typeof t.test.skip, 'function'); + assert.strictEqual(typeof t.test.todo, 'function'); +}); + +test('subtest should return a promise', async (t) => { + const normal = t.test('normal subtest'); + assert.ok(isPromise(normal)); + await normal; +}); + +test('t.test[variant]() should return a promise', async (t) => { + const xfail = t.test.expectFailure('expectFailure subtest', () => { throw new Error('This should pass'); }); + const only = t.test.only('only subtest'); + const skip = t.test.skip('skip subtest'); + const todo = t.test.todo('todo subtest'); + + assert.ok(isPromise(xfail)); + assert.ok(isPromise(only)); + assert.ok(isPromise(skip)); + assert.ok(isPromise(todo)); + + await xfail; + await only; + await skip; + await todo; +}); + +test('nested subtests should have test variants', async (t) => { + await t.test('level 1', async (t) => { + assert.strictEqual(typeof t.test, 'function'); + assert.strictEqual(typeof t.test.expectFailure, 'function'); + assert.strictEqual(typeof t.test.only, 'function'); + assert.strictEqual(typeof t.test.skip, 'function'); + assert.strictEqual(typeof t.test.todo, 'function'); + + await t.test('level 2', async (t) => { + assert.strictEqual(typeof t.test, 'function'); + assert.strictEqual(typeof t.test.expectFailure, 'function'); + assert.strictEqual(typeof t.test.skip, 'function'); + assert.strictEqual(typeof t.test.todo, 'function'); + assert.strictEqual(typeof t.test.only, 'function'); + }); + }); +});