Humanized actions in the Playwright wrappers (Python, JS, .NET) now run through a
single shared engine built on Playwright's own selector engine: full locator support
(roles, chains, filters, frame locators, strict mode), Playwright options honoured,
value inputs operated with real input, persona-aware keys, and errors instead of
silent fallbacks. Puppeteer: frame-scoped actions, button/count, Shift on typos.
Follow-ups: macOS dropdowns via type-ahead, nested same-box element handles,
stale handles fail fast, CI fails on a missing test binary.
Removing the Playwright fallback closed a main-world read leak but left every
get_by_* locator raising UnsupportedHumanizeSelectorError. Reimplement the four
cheap engines in the isolated-world resolver so those locators work again.
Selector engines (shared resolver, byte-identical in all three wrappers):
- internal:testid and internal:attr (placeholder/alt/title). The i flag is a
case-insensitive substring on the raw attribute value; test ids stay strict.
- internal:text. Exact compares the full normalized subtree text, unlike the
public text= engine which compares immediate fragments.
- internal:label, resolving aria-labelledby, then aria-label, then .labels.
- internal:role and >> chaining stay unsupported; the error now names what is
supported and the workaround.
Text parity fixes in __elementText, checked against playwright-core:
- drop a <br> to newline branch Playwright does not have
- concatenate shadow-root text into the host, which Playwright does
- give the public text= engine Playwright's self/selfAndChildren rule, since
contains() cannot see into a shadow root and kept the host as a match
Target identity: payloads carry a per-world generation (protocol v2). The world
is rebuilt on navigation and its id counter restarts, so an id alone could name
a different element. Generation is bounded to Int32, which the .NET wrapper
requires.
force=True now skips the pointer check entirely, matching Playwright, instead of
suppressing only the coverage rejection.
Also: drop dead _BOX_OP, _ACTIONABLE_OP and readSnapshot, and add a test
asserting the three hand-copied resolver literals stay identical and free of
characters that would terminate their host string literals.
Verified against Playwright's own locator resolution in a real browser:
20/20 engine parity, 7/7 text parity.