Skip to content

fix: propagate chained Suite#timeout() to already-registered hooks#6104

Open
chatman-media wants to merge 1 commit into
mochajs:mainfrom
chatman-media:fix/suite-timeout-propagate-to-hooks
Open

fix: propagate chained Suite#timeout() to already-registered hooks#6104
chatman-media wants to merge 1 commit into
mochajs:mainfrom
chatman-media:fix/suite-timeout-propagate-to-hooks

Conversation

@chatman-media

Copy link
Copy Markdown

PR Checklist

Overview

Suite#timeout(ms) retroactively applies the new timeout to child tests and suites (added in #5612 for #5422), but it only iterates this.tests and this.suites — it skips the four hook arrays (_beforeAll, _beforeEach, _afterAll, _afterEach).

So the chained form does not raise the timeout for hooks:

describe('foo', () => {
  before(async () => { /* slow setup > 2000ms */ });
  it('bar', () => {});
}).timeout(10000);

The hooks are created during the describe callback with the suite's timeout at that moment (the default), and the subsequent .timeout(10000) call never reaches them. The inner it() and the function () { this.timeout(N); ... } form both work, which makes the behaviour inconsistent (see the table in #6033).

Fix

Iterate the hook arrays alongside tests/suites in the setter. Hooks are Runnable instances and already expose a .timeout() setter, so this mirrors the existing loops exactly:

for (const hooks of [
  this._beforeAll,
  this._beforeEach,
  this._afterAll,
  this._afterEach,
]) {
  for (const h of hooks) {
    h.timeout(this._timeout);
  }
}

Tests

Added a unit test in test/unit/suite.spec.cjs under timeout() > when argument is passed that registers one hook of each kind, calls suite.timeout(5000), and asserts all four hooks report 5000.

  • Fails without the fix: expected 2000 to be 5000.
  • Passes with the fix.
  • Full node unit suite (1102 passing) and the chained-timeout self-test (test/unit/timeout.spec.cjs, 13 passing) remain green; eslint clean.

Suite#timeout(ms) retroactively applies the new timeout to child tests
and suites (added in mochajs#5612 for mochajs#5422), but it skipped the four hook
arrays (_beforeAll, _beforeEach, _afterAll, _afterEach).

As a result, the chained form

  describe('foo', () => {
    before(async () => { /* slow setup */ });
    it('bar', () => {});
  }).timeout(10000);

did not raise the timeout for the hooks: they were created during the
describe callback with the suite's timeout at that moment (the default),
and the subsequent .timeout() call never reached them. The equivalent
function() form (this.timeout(N) inside the callback) and the inner
it() were unaffected, making the behaviour inconsistent.

Iterate the hook arrays alongside tests/suites in the setter so hooks
are Runnable instances and already expose a .timeout() setter.

Closes mochajs#6033
@linux-foundation-easycla

linux-foundation-easycla Bot commented Jun 20, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: chatman-media / name: Alexander Kireev (756d75d)

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi @chatman-media, thanks for the pull request! A scan flagged a concern with it. Could you please take a look?

[pr-task-completion] This PR's body is missing [x] checks on the following tasks from the PR template.

Repositories often provide a set of tasks that pull request authors are expected to complete. Those tasks should be marked as completed with a [x] in the pull request description. Please complete those tasks and mark the checks as [x] completed.

🗺️ This message was posted automatically by OctoGuide: a bot for GitHub repository best practices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 Bug: Suite.timeout() propagation misses hooks, chained describe(...).timeout(N) does not apply to hooks

1 participant