diff --git a/test/e2e/support/scenarios/combobox.mjs b/test/e2e/support/scenarios/combobox.mjs index 0c91ff0..ee40a23 100644 --- a/test/e2e/support/scenarios/combobox.mjs +++ b/test/e2e/support/scenarios/combobox.mjs @@ -16,7 +16,8 @@ // carries role="status" but is a direct child of role="listbox". ARIA does // not permit role="status" as a listbox child; axe flags this as // aria-required-children (critical). This is tracked in FOLLOWUPS.md. -// The fixme flag on that case is set in scenarios.spec.mjs. +// That case carries `fixme: true` below; scenarios.spec.mjs reads the flag +// and runs it via test.fixme so the defect is tracked, not silenced. const preview = (page) => page.locator("[data-shadix-preview]").first(); const trigger = (page) => preview(page).locator("[data-slot='combobox-trigger']").first(); @@ -24,6 +25,8 @@ const content = (page) => preview(page).locator("[data-slot='combobox-content']" const search = (page) => content(page).locator("[data-slot='combobox-input']"); // Visible options: the hook adds class="hidden" to non-matching items. const visibleOption = (page) => content(page).locator("[role='option']:visible").first(); +// Active option: the hook marks the keyboard-active item with [data-active]. +const activeOption = (page) => content(page).locator("[role='option'][data-active]").first(); const empty = (page) => content(page).locator("[data-slot='combobox-empty']"); export default [ @@ -50,11 +53,14 @@ export default [ run: async (page) => { await trigger(page).click(); await content(page).waitFor({ state: "visible" }); - // ArrowDown from the search input activates the first visible option. - // The hook focuses the search input on open, so ArrowDown works immediately. + // ArrowDown from the search input activates the first visible option + // (the hook marks it [data-active] + points aria-activedescendant at it). + // keyboard nav is synchronous here; for a component with async focus, wait + // for the active option's [aria-selected]/[data-active] before returning. await search(page).press("ArrowDown"); - await visibleOption(page).waitFor({ state: "visible" }); - return content(page); + await activeOption(page).waitFor({ state: "visible" }); + // Return the active option itself — it is the element that signals the state. + return activeOption(page); }, }, {