fix(hooks): emit hook.failed when a helper suite hook throws - #5684
fix(hooks): emit hook.failed when a helper suite hook throws#5684luantaraschi wants to merge 2 commits into
Conversation
A custom helper's `_beforeSuite()` / `_afterSuite()` is queued on the recorder from the `event.suite.before` / `event.suite.after` listeners in lib/listener/helpers.js. That path runs inside suiteSetup/suiteTeardown, not inside the `injected()` wrapper, and only `injected()` calls `fireHook()`. So a failing helper lifecycle method rejected the mocha hook without ever emitting `event.hook.failed`, and reporters that listen for it, junitReporter among them, recorded nothing. Both error handlers now emit the matching hook object before calling done, so `hookName` reads BeforeSuite or AfterSuite exactly as it does for the test-file-defined hooks. Closes codeceptjs#5660
|
The red The last CI here ran on 2026-08-07 and the Android job failed at the Sauce Labs handshake: That is a missing credential, not a broken test. Fork pull requests do not receive You already fixed this on 2026-08-12 in So I pressed Update branch to pick up the guard rather than leave a red X sitting on an approved PR. The Android job is skipped on the new head, as intended. The fresh runs are sitting at |
Motivation/Description of the PR
Resolves #5660.
@mirao's trace is correct and I followed it through the code.
event.hook.failedis only emitted byfireHook(), which is only reached from theinjected()wrapper used for test-file-definedBeforeSuite()/AfterSuite(). A custom helper's_beforeSuite()/_afterSuite()takes a different route:lib/mocha/ui.js:106registerssuite.beforeAll('codeceptjs.beforeSuite', suiteSetup(suite))→suiteSetupemitsevent.suite.before→lib/listener/helpers.js:30queuesrunAsyncHelpersHook('_beforeSuite', ...)on the recorder. When that throws, it surfaces insuiteSetup'srecorder.errHandler, which calleddoneFn(err)and nothing else. Nohook.failed, sojunitReporter's listener never fired and the report stayed empty.Both error handlers now emit the matching hook object before calling done. I passed the mocha suite straight through, which is what
fireHook()already does, sohook.ctx.testandhook.hookNamecome out the same shape junitReporter already consumes (['BeforeSuite', 'AfterSuite'].includes(hook.hookName)).I did not reuse
fireHook()here: it derives the hook kind fromsuite.ctx?.test?.title?.match(/"([^"]*)"/)[1], and these hooks are titledcodeceptjs.beforeSuite, which has no quoted segment, so that match returns null and the indexing throws.Type of change
Checklist:
npm run docs) — N/A, no public API changenpm run lint)npm test)Two tests appended to
test/unit/mocha/asyncWrapper_test.js, one per hook. They queue a throwing helper method the same wayrunAsyncHelpersHookdoes and assert both thatdonestill receives the error and thathook.failedcarries the righthookName. Both fail on the commit before this change withhook.failed was emitted.Full unit suite on Windows: 758 passing / 13 failing before, 760 passing / 11 failing after. The 11 remaining are pre-existing path assertions that expect POSIX paths and see a
C:drive letter (utils_test.js,utils/trace_test.js), identical with and without this change.Related: #5683 fixes the other half of the junit reporting gap @mirao reported, the suite timestamp.