import type { Page } from "@playwright/test"; /** What assistive tech sees for one node: its role, name, and ARIA properties such as `expanded`. */ export interface AxNode { readonly role: string; readonly name: string; readonly [property: string]: unknown; } /** * Reads Chromium's accessibility tree. Playwright's role queries compute ARIA from DOM attributes * and miss `ElementInternals` roles and states, so tests of custom elements ask the browser instead. */ export async function axTree(page: Page): Promise { const cdp = await page.context().newCDPSession(page); try { const { nodes } = await cdp.send("Accessibility.getFullAXTree"); return nodes .filter((node) => !node.ignored) .map((node) => ({ ...Object.fromEntries((node.properties ?? []).map((p) => [p.name, p.value.value])), role: String(node.role?.value ?? ""), name: String(node.name?.value ?? ""), })); } finally { await cdp.detach(); } } export async function axNode(page: Page, role: string, name: string): Promise { return (await axTree(page)).find((node) => node.role === role && node.name === name); }