// @vitest-environment jsdom import { act, cleanup, fireEvent, render, screen, } from "@testing-library/react"; import "@testing-library/jest-dom/vitest"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { ConfirmButton } from "../components/ui/confirm-button"; function XIcon() { return X; } function renderButton( props: Partial[0]> = {}, ) { const onConfirm = props.onConfirm ?? vi.fn(); render( } label="Remove combatant" onConfirm={onConfirm} {...props} />, ); return { onConfirm }; } describe("ConfirmButton", () => { beforeEach(() => { vi.useFakeTimers(); }); afterEach(() => { vi.useRealTimers(); cleanup(); }); it("renders the default icon in idle state", () => { renderButton(); expect(screen.getByTestId("x-icon")).toBeTruthy(); expect(screen.getByRole("button")).toHaveAttribute( "aria-label", "Remove combatant", ); }); it("transitions to confirm state with Check icon on first click", () => { renderButton(); fireEvent.click(screen.getByRole("button")); expect(screen.queryByTestId("x-icon")).toBeNull(); expect(screen.getByRole("button")).toHaveAttribute( "aria-label", "Confirm remove combatant", ); expect(screen.getByRole("button").className).toContain("bg-destructive"); }); it("calls onConfirm on second click in confirm state", () => { const { onConfirm } = renderButton(); const button = screen.getByRole("button"); fireEvent.click(button); fireEvent.click(button); expect(onConfirm).toHaveBeenCalledOnce(); }); it("auto-reverts after 5 seconds", () => { renderButton(); fireEvent.click(screen.getByRole("button")); expect(screen.queryByTestId("x-icon")).toBeNull(); act(() => { vi.advanceTimersByTime(5000); }); expect(screen.getByTestId("x-icon")).toBeTruthy(); }); it("reverts on Escape key", () => { renderButton(); fireEvent.click(screen.getByRole("button")); expect(screen.queryByTestId("x-icon")).toBeNull(); fireEvent.keyDown(document, { key: "Escape" }); expect(screen.getByTestId("x-icon")).toBeTruthy(); }); it("reverts on click outside", () => { renderButton(); fireEvent.click(screen.getByRole("button")); expect(screen.queryByTestId("x-icon")).toBeNull(); fireEvent.mouseDown(document.body); expect(screen.getByTestId("x-icon")).toBeTruthy(); }); it("does not enter confirm state when disabled", () => { renderButton({ disabled: true }); fireEvent.click(screen.getByRole("button")); expect(screen.getByTestId("x-icon")).toBeTruthy(); }); it("cleans up timer on unmount", () => { const clearTimeoutSpy = vi.spyOn(globalThis, "clearTimeout"); renderButton(); fireEvent.click(screen.getByRole("button")); cleanup(); expect(clearTimeoutSpy).toHaveBeenCalled(); clearTimeoutSpy.mockRestore(); }); it("manages independent instances separately", () => { const onConfirm1 = vi.fn(); const onConfirm2 = vi.fn(); render( <> 1} label="Remove first" onConfirm={onConfirm1} /> 2} label="Remove second" onConfirm={onConfirm2} /> , ); const buttons = screen.getAllByRole("button"); fireEvent.click(buttons[0]); // First is confirming, second is still idle expect(screen.queryByTestId("icon-1")).toBeNull(); expect(screen.getByTestId("icon-2")).toBeTruthy(); }); // T008: Keyboard-specific tests it("Enter key triggers confirm state", () => { renderButton(); const button = screen.getByRole("button"); // Native button handles Enter via click event fireEvent.click(button); expect(screen.queryByTestId("x-icon")).toBeNull(); expect(button).toHaveAttribute("aria-label", "Confirm remove combatant"); }); it("Enter in confirm state calls onConfirm", () => { const { onConfirm } = renderButton(); const button = screen.getByRole("button"); fireEvent.click(button); // enter confirm state fireEvent.click(button); // confirm expect(onConfirm).toHaveBeenCalledOnce(); }); it("Escape in confirm state reverts", () => { renderButton(); fireEvent.click(screen.getByRole("button")); fireEvent.keyDown(document, { key: "Escape" }); expect(screen.getByTestId("x-icon")).toBeTruthy(); expect(screen.getByRole("button")).toHaveAttribute( "aria-label", "Remove combatant", ); }); it("blur event reverts confirm state", () => { renderButton(); const button = screen.getByRole("button"); fireEvent.click(button); expect(screen.queryByTestId("x-icon")).toBeNull(); fireEvent.blur(button); expect(screen.getByTestId("x-icon")).toBeTruthy(); }); it("Enter/Space keydown stops propagation to prevent parent handlers", () => { const parentHandler = vi.fn(); render( // biome-ignore lint/a11y/noStaticElementInteractions: test wrapper
} label="Remove combatant" onConfirm={vi.fn()} />
, ); const button = screen.getByRole("button"); fireEvent.keyDown(button, { key: "Enter" }); fireEvent.keyDown(button, { key: " " }); expect(parentHandler).not.toHaveBeenCalled(); }); });