-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
Version
1.58.2
Steps to reproduce
- clone my repo: https://github.com/nstepien/playwright-bugs
npm cinpm test tabbing
(the rightclick.spec.ts test file is for a separate issue, unrelated to this one)
Expected behavior
Tests should pass, tabbing and focus states should behave similarly across browsers.
Focus/tabbing behavior should not change if elements are in an iframe.
There should be no DOM elements focused when the page/iframe isn't focused.
There should be no browser UI elements focused when the page/iframe is focused.
Actual behavior
tabbingtest:- Chromium:
When focus is on the last element and pressing Tab,
focus moves to a browser UI element,
pressing Tab one more time moves focus to the first focusable element...
but the browser UI element that was focused... is still focused! Double focus! 🐛
I tried manually typing withheadless: falsebut nothing happens,
tabbing moved focus to another browser UI element instead of moving focus within the page. 🐛 - Firefox:
When focus is on the last element and pressing Tab,
it seems like focus is set on a browser UI element,
butdocument.hasFocus()istrue, andInput Cis theactiveElement. 🐛
Pressing Tab further does not cycle focus toInput A. 🐛
Visually speaking it does look like focus is then removed from the browser UI element.
I tried manually typing withheadless: falsebut nothing happens,
it's unclear where the focus actually is, despite what the DOM APIs report. 🐛 - WebKit:
No issues with WebKit.
Although it's unclear if a browser UI element receives focus,
focus does get correctly removed fromInput C,
and pressing Tab once more cycles focus toInput Aas expected.
- Chromium:
shift tabbingtest:- Chromium and WebKit: essentially same as above
- Firefox: once focus leaves the page, focus shifts between two browser UI elements, despite what the DOM APIs report.
tabbing in iframetest:- Chromium:
Similar to above, but an additional Tab press is required forInput Ato receive focus.
A browser UI element remains focused though. 🐛 - Firefox:
Unlike the tests above, Tab does remove focus fromInput C,
but the parent document and the iframe have focus. 🐛
After pressing Tab once more,
Input Cbecomes focused again instead ofInput A,
but the iframe's document is not focused. Ghost focus? 🐛👻
After pressing Tab one more time,
the iframe's document is now focused. - WebKit:
Once focus leavesInput C, pressing Tab does not move focus back into the page. 🐛
- Chromium:
shift tabbing in iframetest:- Chromium and WebKit: essentially same as the
tabbing in iframetest. - Firefox:
Unlike thetabbing in iframetest,
shift-tabbing seems to cycle focus betweenInput Aand a browser UI element,
without ever restoring focus to the iframe's document. 🐛
- Chromium and WebKit: essentially same as the
clicking to restore focus in iframe after tabbingtest:- Chromium:
While clicking does restore focus to the iframe's document/input,
the browser UI element that was focused by tabbing, remains focused. 🐛 - Firefox:
Whenheadlessis disabled, clicking on the input immediately blurs, requiring another click to restore focus. 🐛
Whenheadlessis enabled, it seems to behave like Chromium and WebKit, at least in terms of what the DOM APIs report, at least at the end. - WebKit:
No issues.
- Chromium:
Additional context
Focus states are highly unpredictable in Playwright, with results diverging between browsers, with/out iframe, and with/out headless, leading to flaky tests and hours spent debugging tests, especially as it affects both keyboard and mouse interactions.
Focus management is already hard as it is with DOM APIs, so this is another beast to tame.
I've tested with an iframe as well, as I'm using Playwright through Vitest's browser mode, and Vitest runs tests in an iframe.
My understanding of what's causing these bugs: the page.keyboard.* APIs simulate a virtual keyboard within the page's (or document's) context, but if focus moves outside the page then it should be impossible to interact with the page via keyboard interactions until focus moves back to the page again.
Instead, Playwright does try to simulate these keyboard events within the page even if the page isn't focused, and browsers get confused, which results in undefined behaviors, and "dual focus" where both page elements and UI elements are visually focused.
Maybe we need alternative APIs like browser.keyboard.* or window.keyboard.*?
Should the page.keyboard.* APIs should throw when the page isn't focused?
Should Playwright trap focus within the page/document?
It's unclear how much of this is an issue with browsers vs Playwright.
Manually tabbing instead of programmatically tabbing works fine in real browsers.
Although manually tabbing in:
- Playwright's Firefox browser +
tabbing.html-> tabbing works, but stops moving focus once it cycles toInput A. I can shift+tab, but then it'll get stuck onInput C. - Playwright's WebKit browser +
tabbing-iframe.html-> can't manually tab back into the page.
Environment
System:
OS: Windows 11 10.0.26200
CPU: (32) x64 AMD Ryzen 9 9950X3D 16-Core Processor
Memory: 42.69 GB / 63.58 GB
Binaries:
Node: 25.6.1 - C:\Program Files\nodejs\node.EXE
npm: 11.7.0 - C:\Program Files\nodejs\npm.CMD
IDEs:
VSCode: 1.109.3 - C:\Users\Stepi\AppData\Local\Programs\Microsoft VS Code\bin\code.CMD
npmPackages:
@playwright/test: ^1.58.2 => 1.58.2