Skip to content

Commit b551b9d

Browse files
DavertMikclaude
andcommitted
fix(CDPBrowser): deterministic Obscura suite — await within-block promise chains in shared webapi tests; null-safe assertion message templating
Flake 1 ("should respect form fields inside within block") and Flake 2 (the "kills a SIGTERM-ignoring child within bounds" phantom) were one bug, not two. test/helper/webapi.js's `within tests` fired `I._withinBegin(locator).then()...` without awaiting/returning it, racing the test's own later `await`ed assertions against the still-in-flight async scope setup. Under load this produced a real AssertionFailedError with a `null` param. lib/utils.js's template() only guarded `undefined`, so formatting that error inside Mocha's own epilogue threw `null.toString()`, crashing the reporter mid-print; Mocha's uncaughtException recovery then misattributed the crash to whatever test was `currentRunnable` (the last-run spawn-lifecycle test), producing a blank, EXIT:0 "phantom" failure on an otherwise fully deterministic test (verified 15/15 clean in isolation). Fixes: - test/helper/webapi.js: await the three unawaited within-block promise chains that precede further awaited assertions in the same test body. - lib/utils.js: template() now treats `null` the same as `undefined` (renders as empty string instead of throwing) — a deliberate divergence from 3.x, which has the identical latent bug. Verified via 3 consecutive full Obscura suite runs (179 passing/122 pending/0 failing, exit 0 each time, instrumented to confirm zero unhandled rejections escalate to a Mocha failure), isolated within-describe passes on Obscura/Chrome/Puppeteer/Playwright, and a clean Chrome regression run (201/112/0, unchanged). Full root-cause writeup in .superpowers/flake-report.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent db172f4 commit b551b9d

2 files changed

Lines changed: 4 additions & 4 deletions

File tree

lib/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export const methodsOfObject = function (obj, className) {
108108
export const template = function (template, data) {
109109
return template.replace(/{{([^{}]*)}}/g, (a, b) => {
110110
const r = data[b]
111-
if (r === undefined) return ''
111+
if (r === undefined || r === null) return ''
112112
return r.toString()
113113
})
114114
}

test/helper/webapi.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,7 +1620,7 @@ export function tests() {
16201620
if (I.capabilities?.layout === 'none') this.skip() // visibility requires a real layout engine
16211621
await I.amOnPage('/form/example4')
16221622
await I.seeElement('#navbar-collapse-menu')
1623-
I._withinBegin('#register')
1623+
await I._withinBegin('#register')
16241624
.then(() => I.see('E-Mail'))
16251625
.then(() => I.dontSee('Toggle navigation'))
16261626
.then(() => I.dontSeeElement('#navbar-collapse-menu'))
@@ -1638,7 +1638,7 @@ export function tests() {
16381638
await I.seeInField('Hasło', '12345')
16391639
await I.checkOption('terms')
16401640
await I.seeCheckboxIsChecked('terms')
1641-
I._withinBegin({ css: '.form-group' })
1641+
await I._withinBegin({ css: '.form-group' })
16421642
.then(() => I.see('E-Mail'))
16431643
.then(() => I.dontSee('Hasło'))
16441644
.then(() => I.dontSeeElement('#navbar-collapse-menu'))
@@ -1661,7 +1661,7 @@ export function tests() {
16611661
it('should execute within block 2', async () => {
16621662
await I.amOnPage('/form/example4')
16631663
await I.fillField('Hasło', '12345')
1664-
I._withinBegin({ xpath: '//div[@class="form-group"][2]' })
1664+
await I._withinBegin({ xpath: '//div[@class="form-group"][2]' })
16651665
.then(() => I.dontSee('E-Mail'))
16661666
.then(() => I.see('Hasło'))
16671667
.then(() => I.grabTextFrom('label'))

0 commit comments

Comments
 (0)