Skip to content

Commit 252ab25

Browse files
DavertMikDavertMikclaude
authored
fix(CDPBrowser): report connection errors on failed steps, skip screenshots without rendering (#5747)
* fix(CDPBrowser): report connection errors on failed steps, skip screenshots without rendering Helper _before errors are only logged by core, so when the browser could not be started or reached the first step failed with "Cannot read properties of null (reading 'send')". The connection error is now kept and rethrown before each step, so the failure summary shows the real cause. saveScreenshot and saveElementScreenshot no longer throw on browsers without a rendering engine (Lightpanda); they print a debug message and return. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(CDPBrowser): expect screenshots to be skipped without a rendering engine Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: DavertMik <davert@testomat.io> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent dbd4806 commit 252ab25

5 files changed

Lines changed: 26 additions & 20 deletions

File tree

‎docs/helpers/Lightpanda.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ These are set automatically and only need overriding for unusual setups:
6262

6363
## Limitations
6464

65-
* No screenshots and no screencast: `saveScreenshot` throws.
65+
* No screenshots and no screencast: `saveScreenshot` and `saveElementScreenshot` do nothing (a debug message is printed).
6666
* No frames or popups.
6767
* No scrolling: scroll positions always stay at 0.
6868
* Computed styles cover what visibility checks need (`display`, `visibility`, `opacity`,

‎lib/helper/CDPBrowser.js‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,20 @@ class CDPBrowser extends Helper {
357357
await this.cdp.connect()
358358
}
359359

360+
_beforeStep() {
361+
if (this._connectError) throw new Error(this._connectError.message)
362+
}
363+
360364
async _before() {
361-
if (!this.cdp || !this.cdp.isConnected) await this._connect()
365+
this._connectError = null
366+
if (!this.cdp || !this.cdp.isConnected) {
367+
try {
368+
await this._connect()
369+
} catch (err) {
370+
this._connectError = err
371+
throw err
372+
}
373+
}
362374
this._navStartWaiters = []
363375
this._lastMainFrameNav = { loaderId: null, events: {} }
364376
const { targetId } = await this.cdp.send('Target.createTarget', { url: 'about:blank' })
@@ -1343,7 +1355,8 @@ class CDPBrowser extends Helper {
13431355
*/
13441356
async saveScreenshot(fileName) {
13451357
if (this.capabilities.screenshot === false) {
1346-
throw new Error('saveScreenshot is not supported: this browser has no rendering engine')
1358+
this.debug('saveScreenshot skipped: this browser has no rendering engine')
1359+
return
13471360
}
13481361
const outputDir = global.output_dir || '.'
13491362
const res = await this.cdp.send('Page.captureScreenshot', { format: 'png' }, this.sessionId)
@@ -1355,7 +1368,8 @@ class CDPBrowser extends Helper {
13551368
*/
13561369
async saveElementScreenshot(locator, fileName) {
13571370
if (this.capabilities.screenshot === false) {
1358-
throw new Error('saveElementScreenshot is not supported: this browser has no rendering engine')
1371+
this.debug('saveElementScreenshot skipped: this browser has no rendering engine')
1372+
return
13591373
}
13601374
const res = await this._run(this._candidates(locator), 'rect')
13611375
if (!res.found) throw new ElementNotFound(locator)

‎lib/helper/Lightpanda.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const config = {}
7272
*
7373
* ## Limitations
7474
*
75-
* - No screenshots and no screencast: `saveScreenshot` throws.
75+
* - No screenshots and no screencast: `saveScreenshot` and `saveElementScreenshot` do nothing (a debug message is printed).
7676
* - No frames or popups.
7777
* - No scrolling: scroll positions always stay at 0.
7878
* - Computed styles cover what visibility checks need (`display`, `visibility`, `opacity`,

‎test/helper/CDPBrowser_lightpanda_test.js‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,10 @@ describe('Lightpanda helper (self-managed lightpanda serve)', function () {
6666
await I.dontSeeElement('#does-not-exist')
6767
})
6868

69-
it('rejects screenshots with a clear message', async () => {
69+
it('skips screenshots without failing', async () => {
7070
await I.amOnPage('/')
71-
try {
72-
await I.saveScreenshot('nope.png')
73-
throw new Error('should have thrown')
74-
} catch (err) {
75-
expect(err.message).to.include('no rendering engine')
76-
}
71+
await I.saveScreenshot('nope.png')
72+
expect(fs.existsSync(path.join(global.output_dir || '.', 'nope.png'))).to.be.false
7773
})
7874

7975
webApiTests.tests()

‎test/helper/CDPBrowser_obscura_test.js‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,11 @@ describe('Obscura helper (self-managed obscura serve)', function () {
8080
}
8181
})
8282

83-
it('rejects screenshots with a clear message when there is no rendering engine', async function () {
83+
it('skips screenshots without failing when there is no rendering engine', async function () {
8484
await I.amOnPage('/')
85-
if (I.capabilities.screenshot !== false) this.skip() // this binary can render; saveScreenshot works instead of throwing
86-
try {
87-
await I.saveScreenshot('nope.png')
88-
throw new Error('should have thrown')
89-
} catch (err) {
90-
expect(err.message).to.include('no rendering engine')
91-
}
85+
if (I.capabilities.screenshot !== false) this.skip() // this binary can render; saveScreenshot writes a file instead
86+
await I.saveScreenshot('nope.png')
87+
expect(fs.existsSync(path.join(global.output_dir || '.', 'nope.png'))).to.be.false
9288
})
9389

9490
webApiTests.tests()

0 commit comments

Comments
 (0)