feat: support element screenshots of elements in a frame in WebDriver BiDi sessions (v9 `switchFrame()`, v10 `context.frame()`)
Los mantenedores suelen responder en 1 día
@plum117 ya está trabajando en esto.
Desde el 9/10/2026.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 50/100
- Tipo de issue
- Nueva funcionalidad
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- typescript
- Área
- testing-qa
Línea de trabajo
Start with packages/image-comparison-core/src/methods/takeElementScreenshots.ts and screenshots.ts, then inspect images.ts for the ignore-region path. Add unit coverage for nested frames, borders, padding, and scroll, and remove the skip from tests/specs/v10.browsingContexts.spec.ts. Done means the v9 and v10 frame cases produce the same screenshot with 0% mismatch.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Is your feature request related to a problem? Please describe.
In a WebDriver BiDi session (the default for Chrome, Edge and Firefox since WebdriverIO v9), checkElement() / toMatchElementSnapshot() of an element inside an iframe does not work:
- WebdriverIO v9, frame reached with
browser.switchFrame(): the image is wrong. It is moved by the position of the iframe in the page. A baseline made in the same way is also wrong, so the test can pass with a wrong image. - WebdriverIO v10:
switchFrame()is removed for BiDi sessions, and its replacementcontext.frame()fails:WebDriver Bidi command "browsingContext.captureScreenshot" failed with error: invalid argument - Invalid input in "clip".
With WebDriver Classic ('wdio:enforceWebDriverClassic': true, Appium, Safari), it works in v9 and v10.
Test: the same box outside a frame (baseline) and inside an iframe at margin: 60px 0 0 30px. Expected: 0% mismatch. Local headless Chrome 154, @wdio/visual-service 10.1.0 (with the WebdriverIO v10 changes of #1227).
| How the frame is reached | v9.32.0 BiDi | v10.0.0-alpha.163 BiDi | v9 Classic | v10 Classic |
|---|---|---|---|---|
browser.switchFrame($('iframe')) |
69.587% (image moved by 30/60 px) | error: switchFrame removed for BiDi |
0% | 0% |
(await browser.url(url)).frame('iframe') |
not in v9 | error: Invalid input in "clip" |
not in v9 | error: needs BiDi |
Reproduction (fixtures tests/fixtures/v10/frame.html and box.html from #1222, on the wdio0-v10-compliance branch):
it('compares the same box outside and inside a frame', async () => {
await browser.url(boxPage)
await browser.checkElement(await $('#target'), 'frame-box') // baseline
// v9
await browser.url(framePage)
await browser.switchFrame($('iframe'))
console.log(await browser.checkElement(await $('#target'), 'frame-box')) // 69.587, expected 0
await browser.switchFrame(null)
// v10
const frame = await (await browser.url(framePage)).frame('iframe')
console.log(await browser.checkElement(await frame.$('#target'), 'frame-box')) // throws "Invalid input in clip"
})
tests/specs/v10.browsingContexts.spec.ts (#1222) has the v10 case as it.skip.
Root cause
In the BiDi element screenshot (takeElementScreenshots.ts#L46 and #L77):
getElementRect()gives the position of the element in the frame document (x 40, y 40 in the test).takeBase64BiDiScreenshot()captures the top-level context (screenshots.ts#L546), with that position as theclip.
The clip misses the element by the position of the iframe (30/60 px).
Describe the solution you'd like
Support element screenshots of elements in frames in BiDi sessions, for v9 switchFrame() and v10 context.frame().
Proposed method (tested outside the service): compute the element rect in the top-level document with a client-side script that runs in the element's own document and adds the content-box position of each parent iframe:
function getElementRectInTopDocument (el, origin) {
const r = el.getBoundingClientRect()
let x = r.left, y = r.top, win = el.ownerDocument.defaultView
while (win !== win.top) {
const frameEl = win.frameElement // null for a cross-origin frame
if (!frameEl) return null
const fr = frameEl.getBoundingClientRect()
const style = win.parent.getComputedStyle(frameEl)
x += fr.left + frameEl.clientLeft + parseFloat(style.paddingLeft)
y += fr.top + frameEl.clientTop + parseFloat(style.paddingTop)
win = win.parent
}
// 'document' origin: add the scroll of the top-level page. 'viewport' origin: no scroll.
return origin === 'document'
? { x: x + win.scrollX, y: y + win.scrollY, width: r.width, height: r.height }
: { x, y, width: r.width, height: r.height }
}
Run it with element.execute(getElementRectInTopDocument, origin). In v9 (after switchFrame()) and in v10 (context.frame()), element.execute() runs in the frame document (browser.execute() runs in the top-level page in v10).
Result with the clip from this script:
| Rect | Mismatch | |
|---|---|---|
v9 switchFrame() |
x 70, y 100 (was 40, 40) | 0.000% (was 69.587%) |
v10 context.frame() |
x 70, y 100 | 0.000% (was an error) |
Service changes:
- Add the client-side script.
- In both BiDi element functions, use it in place of
getElementRect(). KeepgetElementRect()as the fallback when the script returnsnull. autoElementScroll:scrollElementIntoViewonly scrolls inside the frame. With the'viewport'origin, the top-level page must also show the iframe.- Ignore regions:
images.ts#L621also usesgetElementRect(), so elements in a frame used inignoreprobably have the same offset (not tested). - Tests: unit tests for the script (nested frames, iframe border and padding, scroll), and remove
.skipfromtests/specs/v10.browsingContexts.spec.ts.
Describe alternatives you've considered
- Use WebDriver Classic for these tests (
'wdio:enforceWebDriverClassic': true). This works now, but it disables BiDi for the whole session. - Capture the frame context directly: not possible,
browsingContext.captureScreenshotonly accepts a top-level context. - Cross-origin frames:
frameElementisnull, so the script cannot read the iframe position. Possible solution (not tested): BiDibrowsingContext.locateNodeswith thecontextlocator in the parent context gives the iframe element, andscript.callFunctionin the parent gives its position. Else keep the current behavior and log a warning.
Additional context
- Related, closed: #1156 / #1155 (wrong emulation detection inside a frame, which caused blank images with the fallback path on Firefox). From the analysis in #1156, the fallback path (
takeScreenshot+ crop) has the same frame offset when it is used for other reasons, for exampleresizeDimensions(not tested). - Limit of the method: a part of the element that the iframe does not show (iframe too small or scrolled) is not in the image, because the capture is of the top-level page.
- Lenguaje dominante
- TypeScript
- Estrellas
- 156
- Forks
- 62
- Merge medio
- 2 h 2 min
- PR fusionados (30 d)
- 111
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de webdriverio/visual-testing
-
Proposal: a noise-tolerant compare mode with pixelmatch 8's windowSizePosiblemente ocupada @plum117 la tomó hace 3 días. Abiertoenhancement
webdriverio/visual-testing#1311 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
bug: the visual service fails on Android Chrome through Appium 3 in the default WebDriver BiDi session (workaround: `wdio:enforceWebDriverClassic`)Posiblemente ocupada @plum117 la tomó hace 3 días. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
webdriverio/visual-testing#1232 · 2 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Wait for Screenshot to MatchPosiblemente ocupada @plum117 la tomó hace 1 día. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
webdriverio/visual-testing#690 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Using checkFullPageScreen method, capturing images with duplicate viewport and is not scrolling to the bottom of the pagePosiblemente ocupada @plum117 la tomó hace 1 día. Abiertohelp wanted
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
webdriverio/visual-testing#125 · 2 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de webdriverio/visual-testing
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
db-ux-design-system/core-web#8461 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
-
Cannot run an integration on windows when power shell is selected as the default profile terminalAbiertoPriority/Blocker Type/Bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
wso2/product-integrator#2767 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
-
severity:low
Dificultad 1/5 1-3 horas Aptitud para principiantes 84/100
Los mantenedores suelen responder en 1 día