// @vitest-environment jsdom import { act } from "react"; import { createRoot } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { GlobalMicButton } from "./GlobalMicButton"; // eslint-disable-next-line @typescript-eslint/no-explicit-any (globalThis as any).IS_REACT_ACT_ENVIRONMENT = true; describe("GlobalMicButton", () => { let container: HTMLDivElement; let root: ReturnType | null = null; beforeEach(() => { container = document.createElement("div"); document.body.appendChild(container); root = null; }); afterEach(() => { if (root) { act(() => { root!.unmount(); }); root = null; } if (container.parentNode) container.remove(); }); function render(state: "idle" | "listening" | "speaking" = "idle") { root = createRoot(container); act(() => { root!.render(); }); return { getButton: () => container.querySelector("button[aria-label='Voice']") as HTMLButtonElement, getDataState: () => container.querySelector("button[aria-label='Voice']")?.getAttribute("data-state"), }; } it("renders a button with aria-label 'Voice' by default", () => { const { getButton } = render(); expect(getButton()).not.toBeNull(); }); it("reflects the state prop via data-state", () => { expect(render("idle").getDataState()).toBe("idle"); expect(render("listening").getDataState()).toBe("listening"); expect(render("speaking").getDataState()).toBe("speaking"); }); it("is a no-op on click in Phase 8 (does not throw)", () => { const { getButton } = render(); act(() => { getButton().click(); }); expect(getButton()).not.toBeNull(); }); });