From 19c953b801bd562e0835945484d18f1a748fdb0e Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 6 Dec 2022 13:21:02 -0500 Subject: [PATCH 1/2] test_runner: don't use a symbol for runHook() This is not exposed to userland, so there is no need to put it behind a symbol. --- lib/internal/test_runner/test.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index c56c03c0725586..96c86ab3ed6d08 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -75,7 +75,6 @@ const testNamePatterns = testNamePatternFlag?.length > 0 ? (re) => convertStringToRegExp(re, '--test-name-pattern') ) : null; const kShouldAbort = Symbol('kShouldAbort'); -const kRunHook = Symbol('kRunHook'); const kHookNames = ObjectSeal(['before', 'after', 'beforeEach', 'afterEach']); const kUnwrapErrors = new SafeSet() .add(kTestCodeFailure).add(kHookFailure) @@ -476,7 +475,7 @@ class Test extends AsyncResource { return { ctx, args: [ctx] }; } - async [kRunHook](hook, args) { + async runHook(hook, args) { validateOneOf(hook, 'hook name', kHookNames); try { await ArrayPrototypeReduce(this.hooks[hook], async (prev, hook) => { @@ -507,13 +506,13 @@ class Test extends AsyncResource { const { args, ctx } = this.getRunArgs(); const afterEach = runOnce(async () => { if (this.parent?.hooks.afterEach.length > 0) { - await this.parent[kRunHook]('afterEach', { args, ctx }); + await this.parent.runHook('afterEach', { args, ctx }); } }); try { if (this.parent?.hooks.beforeEach.length > 0) { - await this.parent[kRunHook]('beforeEach', { args, ctx }); + await this.parent.runHook('beforeEach', { args, ctx }); } const stopPromise = stopTest(this.timeout, this.signal); const runArgs = ArrayPrototypeSlice(args); @@ -761,9 +760,10 @@ class Suite extends Test { const hookArgs = this.getRunArgs(); const afterEach = runOnce(async () => { if (this.parent?.hooks.afterEach.length > 0) { - await this.parent[kRunHook]('afterEach', hookArgs); + await this.parent.runHook('afterEach', hookArgs); } }); + try { this.parent.activeSubtests++; await this.buildSuite; @@ -775,19 +775,18 @@ class Suite extends Test { return; } - if (this.parent?.hooks.beforeEach.length > 0) { - await this.parent[kRunHook]('beforeEach', hookArgs); + await this.parent.runHook('beforeEach', hookArgs); } - await this[kRunHook]('before', hookArgs); + await this.runHook('before', hookArgs); const stopPromise = stopTest(this.timeout, this.signal); const subtests = this.skipped || this.error ? [] : this.subtests; const promise = SafePromiseAll(subtests, (subtests) => subtests.start()); await SafePromiseRace([promise, stopPromise]); - await this[kRunHook]('after', hookArgs); + await this.runHook('after', hookArgs); await afterEach(); this.pass(); From f220bd6fdd49d338e0b4c2a08f72ca06ca8b1d30 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 8 Dec 2022 17:21:22 -0500 Subject: [PATCH 2/2] test_runner: add t.after() hook This commit adds an after() hook to the TestContext class. This hook can be used to clean up after a test finishes. --- doc/api/test.md | 27 +++++++++++++++++++++++++++ lib/internal/test_runner/test.js | 5 +++++ test/message/test_runner_hooks.js | 8 +++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/doc/api/test.md b/doc/api/test.md index 3588c6d6acd45b..e4493867ef75b2 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -1125,6 +1125,33 @@ test('top level test', async (t) => { }); ``` +### `context.after([fn][, options])` + + + +* `fn` {Function|AsyncFunction} The hook function. The first argument + to this function is a [`TestContext`][] object. If the hook uses callbacks, + the callback function is passed as the second argument. **Default:** A no-op + function. +* `options` {Object} Configuration options for the hook. The following + properties are supported: + * `signal` {AbortSignal} Allows aborting an in-progress hook. + * `timeout` {number} A number of milliseconds the hook will fail after. + If unspecified, subtests inherit this value from their parent. + **Default:** `Infinity`. + +This function is used to create a hook that runs after the current test +finishes. + +```js +test('top level test', async (t) => { + t.after((t) => t.diagnostic(`finished running ${t.name}`)); + assert.ok('some relevant assertion here'); +}); +``` + ### `context.afterEach([fn][, options])`