fix(web): name checkboxes, radios, switches, cells, and shadow-hosted buttons from content, and a reset input by its value
Merged
OK
1mo ago+157+157+012345678901234567890123456789-22-22-01234567890123456789
- Repro through the runner, on
/roleswith a<div role="switch">Dark mode</div>:getByRole('switch', { name: 'Dark mode' })resolves one node through Playwright's role selector, andtoHaveAccessibleName('Dark mode')on the same locator fails withobserved: name "" (match count 1). The agent tree lists an unnamed switch. Same forrole="checkbox",role="radio",<td>,role="gridcell", a custom element withrole="button"whose text is behind its shadow root, and<input type="reset" value="Clear">. - Cause:
accessibleNameinpackages/web/src/in-page/read-semantics.tsnamed from content for a hand-picked role list,childrenNameOfread lightchildNodesonly, andresetwas mapped tobuttonbut onlybuttonandsubmittook thevalue. - The role list is now accname's, the same list Playwright's
roleUtils.allowsNameFromContentuses, pluslistitem,status, andalert, which the tree already named.NAME_FROM_CONTENT_ROLESinpackages/web/src/in-page/read-semantics.ts. - Content collection follows Playwright's walk (
contentChildrenOf): a<slot>reads its assigned nodes, a host reads its unslotted light children and then its shadow tree, a closed root from the record the init script keeps. A<slot>isdisplay: contents, so both readers space it like a block (* Custom, not*Custom). submitandresetread theirvalue, elseSubmitorReset, as Chrome and Playwright do.- Tests:
packages/web/tests/integration/read-node-names.test.tsasserts the tree name and Playwright'sgetByRole(role, { name, exact: true })land on the same element for 15 cases;packages/e2e/tests/integration/web-platform.test.tsrunstoHaveCount(1)andtoHaveAccessibleName(name)on one locator through the real runner for six of them. - Docs:
docs/reference/screen.mdxnames the roles and the shadow tree rule.
Out of scope, found on the way: the reader reads a scope-less <th> as columnheader where Playwright reads it as rowheader when a filled <td> sits next to it. The fixture uses scope="col" to stay clear of that.