Skip to content

Commit 5c6c6e2

Browse files
fix: fix capturing non-static positioned elements via bidi interface (#944)
* fix: fix capturing non-static positioned elements via bidi interface * chore: update release notes
1 parent 523d6a2 commit 5c6c6e2

File tree

2 files changed

+35
-11
lines changed

2 files changed

+35
-11
lines changed

.changeset/hot-carrots-appear.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"webdriver-image-comparison": patch
3+
"@wdio/visual-service": patch
4+
---
5+
6+
Fix capturing element screenshots with BiDi
7+
8+
This release fixes #919 where an element screenshot, that was for example from an overlay, dropdown, popover, tooltip, modal, was returning an incorrect screenshot
9+
10+
## Committers: 1
11+
12+
- Wim Selles ([@wswebcreation](https://github.com/wswebcreation))
13+

packages/webdriver-image-comparison/src/commands/saveWebElement.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import scrollElementIntoView from '../clientSideScripts/scrollElementIntoView.js
1010
import { canUseBidiScreenshot, getBase64ScreenshotSize, getMethodOrWicOption, waitFor } from '../helpers/utils.js'
1111
import scrollToPosition from '../clientSideScripts/scrollToPosition.js'
1212
import type { InternalSaveElementMethodOptions } from './save.interfaces.js'
13+
import type { BidiScreenshot, GetWindowHandle } from '../methods/methods.interfaces.js'
1314

1415
/**
1516
* Saves an image of an element
@@ -78,17 +79,27 @@ export default async function saveWebElement(
7879
// We also need to clip the image to the element size, taking into account the DPR
7980
// and also clipt if from the document, not the viewport
8081
const rect = await methods.getElementRect!((await element as WebdriverIO.Element).elementId)
81-
base64Image = await takeBase64BiDiScreenshot({
82-
bidiScreenshot: methods.bidiScreenshot!,
83-
getWindowHandle: methods.getWindowHandle!,
84-
origin: 'document',
85-
clip: {
86-
x: Math.floor(rect.x),
87-
y: Math.floor(rect.y),
88-
width: Math.floor(rect.width),
89-
height: Math.floor(rect.height),
90-
},
91-
})
82+
const clip = { x: Math.floor(rect.x), y: Math.floor(rect.y), width: Math.floor(rect.width), height: Math.floor(rect.height) }
83+
const { bidiScreenshot, getWindowHandle } = methods as { bidiScreenshot: BidiScreenshot; getWindowHandle: GetWindowHandle }
84+
const takeBiDiElementScreenshot = (origin: 'document' | 'viewport') =>
85+
takeBase64BiDiScreenshot({ bidiScreenshot, getWindowHandle, origin, clip })
86+
87+
try {
88+
// By default we take the screenshot from the document
89+
base64Image = await takeBiDiElementScreenshot('viewport')
90+
} catch (err: any) {
91+
// But when we get a zero dimension error (meaning the element might be bigger than the
92+
// viewport or it might not be in the viewport), we need to take the screenshot from the document.
93+
const isZeroDimensionError = typeof err?.message === 'string' && err.message.includes(
94+
'WebDriver Bidi command "browsingContext.captureScreenshot" failed with error: unable to capture screen - Unable to capture screenshot with zero dimensions'
95+
)
96+
97+
if (!isZeroDimensionError) {
98+
throw err
99+
}
100+
101+
base64Image = await takeBiDiElementScreenshot('document')
102+
}
92103
} else {
93104
// Scroll the element into top of the viewport and return the current scroll position
94105
let currentPosition: number | undefined

0 commit comments

Comments
 (0)