From 7c02486f1f91f3b15f70b394f5655092acf88951 Mon Sep 17 00:00:00 2001 From: Colin Ihrig Date: Fri, 29 Mar 2024 22:58:10 -0400 Subject: [PATCH] test_runner: run afterEach hooks in correct order This commit updates the test runner afterEach hook so that the current test's afterEach hooks run before any ancestor afterEach hooks. Fixes: https://github.com/nodejs/node/issues/51671 PR-URL: https://github.com/nodejs/node/pull/52239 Reviewed-By: Moshe Atlow Reviewed-By: Chemi Atlow --- lib/internal/test_runner/test.js | 13 ++++++++++++- .../test-runner/output/hooks-with-no-global-test.js | 4 ++-- test/fixtures/test-runner/output/hooks.js | 8 ++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index a5b7714ad59d82..5c003ca6106f87 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -6,6 +6,7 @@ const { ArrayPrototypeShift, ArrayPrototypeSlice, ArrayPrototypeSome, + ArrayPrototypeSplice, ArrayPrototypeUnshift, FunctionPrototype, MathMax, @@ -275,6 +276,7 @@ class Test extends AsyncResource { after: [], beforeEach: [], afterEach: [], + ownAfterEachCount: 0, }; } else { const nesting = parent.parent === null ? parent.nesting : @@ -294,6 +296,7 @@ class Test extends AsyncResource { after: [], beforeEach: ArrayPrototypeSlice(parent.hooks.beforeEach), afterEach: ArrayPrototypeSlice(parent.hooks.afterEach), + ownAfterEachCount: 0, }; if ((testNamePatterns !== null && !this.matchesTestNamePatterns()) || @@ -559,7 +562,15 @@ class Test extends AsyncResource { } }); } - ArrayPrototypePush(this.hooks[name], hook); + if (name === 'afterEach') { + // afterEach hooks for the current test should run in the order that they + // are created. However, the current test's afterEach hooks should run + // prior to any ancestor afterEach hooks. + ArrayPrototypeSplice(this.hooks[name], this.hooks.ownAfterEachCount, 0, hook); + this.hooks.ownAfterEachCount++; + } else { + ArrayPrototypePush(this.hooks[name], hook); + } return hook; } diff --git a/test/fixtures/test-runner/output/hooks-with-no-global-test.js b/test/fixtures/test-runner/output/hooks-with-no-global-test.js index ea01463fd6cc1f..f8aadc0dc960f6 100644 --- a/test/fixtures/test-runner/output/hooks-with-no-global-test.js +++ b/test/fixtures/test-runner/output/hooks-with-no-global-test.js @@ -26,14 +26,14 @@ after(() => { 'describe beforeEach', 'describe nested beforeEach', 'describe nested it 1', - 'describe afterEach', 'describe nested afterEach', + 'describe afterEach', 'describe beforeEach', 'describe nested beforeEach', 'describe nested test 2', - 'describe afterEach', 'describe nested afterEach', + 'describe afterEach', 'describe nested after', 'describe after', diff --git a/test/fixtures/test-runner/output/hooks.js b/test/fixtures/test-runner/output/hooks.js index 7bc5ab14bf5557..8a397726feeff4 100644 --- a/test/fixtures/test-runner/output/hooks.js +++ b/test/fixtures/test-runner/output/hooks.js @@ -18,8 +18,8 @@ describe('describe hooks', () => { 'beforeEach 1', '1', 'afterEach 1', 'beforeEach 2', '2', 'afterEach 2', 'before nested', - 'beforeEach nested 1', '+beforeEach nested 1', 'nested 1', 'afterEach nested 1', '+afterEach nested 1', - 'beforeEach nested 2', '+beforeEach nested 2', 'nested 2', 'afterEach nested 2', '+afterEach nested 2', + 'beforeEach nested 1', '+beforeEach nested 1', 'nested 1', '+afterEach nested 1', 'afterEach nested 1', + 'beforeEach nested 2', '+beforeEach nested 2', 'nested 2', '+afterEach nested 2', 'afterEach nested 2', 'after nested', 'after describe hooks', ]); @@ -139,8 +139,8 @@ test('test hooks', async (t) => { 'beforeEach 2', '2', 'afterEach 2', 'beforeEach nested', 'nested before nested', - 'beforeEach nested 1', 'nested beforeEach nested 1', 'nested1', 'afterEach nested 1', 'nested afterEach nested 1', - 'beforeEach nested 2', 'nested beforeEach nested 2', 'nested 2', 'afterEach nested 2', 'nested afterEach nested 2', + 'beforeEach nested 1', 'nested beforeEach nested 1', 'nested1', 'nested afterEach nested 1', 'afterEach nested 1', + 'beforeEach nested 2', 'nested beforeEach nested 2', 'nested 2', 'nested afterEach nested 2', 'afterEach nested 2', 'afterEach nested', 'nested after nested', 'after test hooks',