// @vitest-environment jsdom
//
// Gates the shared PopoverItem ARIA contract: aria-checked for menuitemradio/menuitemcheckbox and
// aria-selected for option are rendered as explicit attributes AFTER the floating-ui item props (so they
// win over getItemProps' single-select guess). Six live menus (LanguageSwitcher, ViewSwitcher,
// AddToPlaylist, ChannelTags, tableHeader, plexDetailUi) depend on this; without a test, a regression in
// the shared path would silently drop the checked indicator for screen-reader users. Floating-ui recipe:
// stub the two observers autoUpdate wires, wrap in a FloatingTree, query the hidden surface.
import { describe, it, expect, beforeAll, afterEach } from "vitest";
import { useState } from "react";
import { render, screen, cleanup } from "@testing-library/react";
import { FloatingTree } from "@floating-ui/react";
import { PopoverSurface, PopoverItem } from "./AnchoredPopover";
import { useAnchoredPopover } from "./anchoredPopoverHooks";
beforeAll(() => {
class Stub {
observe() {}
unobserve() {}
disconnect() {}
takeRecords() {
return [];
}
}
globalThis.ResizeObserver ??= Stub as unknown as typeof ResizeObserver;
globalThis.IntersectionObserver ??= Stub as unknown as typeof IntersectionObserver;
});
afterEach(cleanup);
function Menu() {
const [open, setOpen] = useState(true);
const pop = useAnchoredPopover({ open, onOpenChange: setOpen, mode: "menu" });
return (
{}}>
Newest
{}}>
Oldest
{}}>
Show shorts
);
}
describe("PopoverItem ARIA contract", () => {
it("exposes aria-checked on menuitemradio and menuitemcheckbox items", () => {
render(
,
);
const radios = screen.getAllByRole("menuitemradio", { hidden: true });
expect(radios.map((r) => r.getAttribute("aria-checked"))).toEqual(["true", "false"]);
const checkbox = screen.getByRole("menuitemcheckbox", { hidden: true });
expect(checkbox.getAttribute("aria-checked")).toBe("true");
});
});