You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* fix(mocha): fail fast when test hook import chain rejects
In 4.x the per-test setup()/teardown() hooks load ./test.js via a dynamic
import() with no .catch(). If that import rejects, or the .then body throws
(e.g. enhanceMochaTest on an undefined test, a listener throwing), done() is
never called and the mocha hook hangs forever — the silent-hang failure mode
the 4.0 release is most concerned with.
This mirrors the existing suiteSetup()/suiteTeardown() shape exactly: append a
.catch(err => doneFn(err)) to both import chains. No recorder.errHandler is
added (the per-test handler owns the single errFn slot). makeDoneCallableOnce
already guards against a double done() call.
Adds 3 regression tests: setup() and teardown() with a throwing then-body call
done with the error within 1s instead of hanging, plus a happy-path check.
Reverting the fix makes the two error-path tests hang (verified).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit ac59a40)
* fix(core): restore sessions and propagate errors on session/within/retryTo error paths
Fixes four of the latent error-path divergences characterized in #5622, by
making the error paths symmetric with the success paths. The characterization
assertions are updated to the corrected behavior in the same commit.
- within() async error (lib/effects.js): the catch now calls finishHelpers()
(so helpers' _withinEnd runs on error, not just success) and returns
recorder.promise() (so the error propagates through within() instead of being
detached onto a trailing task that a caller awaiting within() never sees).
- session() async error (lib/session.js): schedules a recorder task that runs
recorder.session.restore so the recorder session is restored on error (it
was only restored on success, leaking the session id). The existing
restoreVars/listener cleanup is kept as-is — switching to finalize()'s real
restoreVars() closes the browser context under BROWSER_RESTART=session.
- session() sync error (lib/session.js): the finally recorder.catch now calls
recorder.session.restore before re-throwing (the only place that runs on a
rejected chain).
- retryTo() (lib/effects.js): a thrown callback no longer reject()s the outer
promise prematurely — it routes through recorder.throw so the retry logic
owns the outcome (retry, or reject once maxTries is exhausted). A callback
that throws then succeeds on a later attempt now resolves instead of
rejecting. tries now starts at 1 on the first attempt (was 2); the retry
count is preserved (tries < maxTries).
Verified: unit 748/0, runner 273/0 (incl. all retryFailedStep/rerun tests),
acceptance within/session/els green under both BROWSER_RESTART=browser and
=session.
Not changed here (would be unsafe or out of scope, see PR):
recorder.retries clearing (retryFailedStep depends on it), the stopped-recorder
no-op contract, and nested cross-level restore ordering.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit dca7626)
---------
Co-authored-by: DavertMik <davert@testomat.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
0 commit comments