feat: support element screenshots of elements in a frame in WebDriver BiDi sessions (v9 `switchFrame()`, v10 `context.frame()`)
I maintainer di solito rispondono entro 1 giorno
@plum117 ci sta già lavorando.
Dal 9/10/2026.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 50/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- typescript
- Ambito
- testing-qa
Direzione di ricerca
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.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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.
- Lingua principale
- TypeScript
- Stelle
- 156
- Fork
- 62
- Merge medio
- 2h 2m
- PR unite (30g)
- 111
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di webdriverio/visual-testing
-
Proposal: a noise-tolerant compare mode with pixelmatch 8's windowSizeForse già presa @plum117 l’ha presa 3 giorni fa. Apertaenhancement
webdriverio/visual-testing#1311 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
bug: the visual service fails on Android Chrome through Appium 3 in the default WebDriver BiDi session (workaround: `wdio:enforceWebDriverClassic`)Forse già presa @plum117 l’ha presa 3 giorni fa. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
webdriverio/visual-testing#1232 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Wait for Screenshot to MatchForse già presa @plum117 l’ha presa 2 giorni fa. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 45/100
webdriverio/visual-testing#690 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Using checkFullPageScreen method, capturing images with duplicate viewport and is not scrolling to the bottom of the pageForse già presa @plum117 l’ha presa 2 giorni fa. Apertahelp wanted
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
webdriverio/visual-testing#125 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di webdriverio/visual-testing
Issue simili
-
Documentation Link TypoAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 83/100
Zettlr/Zettlr#6610 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Feil lovtekst i bekreftelsen når leder melder unntak fra oppfølgingsplanForse già presa @AudunSorheim l’ha presa oggi. Aperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 92/100
navikt/syfo-oppfolgingsplan-frontend#1110 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
db-ux-design-system/core-web#8461 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Cannot run an integration on windows when power shell is selected as the default profile terminalApertaPriority/Blocker Type/Bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
wso2/product-integrator#2767 ·
I maintainer di solito rispondono entro 1 giorno