import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import "@testing-library/jest-dom"; import { ChessPuzzle } from "../.."; import { Reset } from "../Reset"; import { Puzzle } from "../../../../utils"; describe("ChessPuzzle.Reset", () => { const mockPuzzle: Puzzle = { fen: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", moves: ["e4", "e5"], }; describe("displayName", () => { it("should have correct displayName", () => { expect(Reset.displayName).toBe("ChessPuzzle.Reset"); }); }); describe("ref forwarding", () => { it("should forward ref to button element", () => { const ref = React.createRef(); render( , ); expect(ref.current).toBeInstanceOf(HTMLButtonElement); }); it("should forward ref when using asChild", () => { const ref = React.createRef(); render( , ); expect(ref.current).toBeInstanceOf(HTMLButtonElement); }); it("should support callback refs", () => { let capturedRef: HTMLElement | null = null; const callbackRef = (ref: HTMLElement | null) => { capturedRef = ref; }; render( , ); expect(capturedRef).toBeInstanceOf(HTMLButtonElement); }); }); describe("visibility based on showOn prop", () => { it("should be visible when status matches showOn", () => { render( Reset , ); expect(screen.getByRole("button")).toBeInTheDocument(); }); it("should be hidden when status does not match showOn", () => { render( Reset , ); expect(screen.queryByRole("button")).not.toBeInTheDocument(); }); it("should default to showing on failed and solved statuses", () => { // Default showOn is ["failed", "solved"], so it should be hidden at start render( Reset , ); expect(screen.queryByRole("button")).not.toBeInTheDocument(); }); it("should accept multiple statuses in showOn", () => { render( Reset , ); expect(screen.getByRole("button")).toBeInTheDocument(); }); }); describe("prop spreading", () => { it("should apply custom className", () => { render( Reset , ); expect(screen.getByRole("button")).toHaveClass("custom-reset-class"); }); it("should apply custom id", () => { render( Reset , ); expect(screen.getByRole("button")).toHaveAttribute("id", "reset-button"); }); it("should apply data-* attributes", () => { render( Reset , ); const button = screen.getByTestId("reset"); expect(button).toHaveAttribute("data-custom", "value"); }); it("should apply aria-* attributes", () => { render( Reset , ); expect(screen.getByRole("button")).toHaveAttribute( "aria-label", "Reset puzzle", ); }); it("should apply disabled attribute", () => { render( Reset , ); expect(screen.getByRole("button")).toBeDisabled(); }); }); describe("asChild pattern", () => { it("should render custom element when asChild is true", () => { render( , ); const button = screen.getByRole("button"); expect(button).toHaveTextContent("Custom Reset"); expect(button).toHaveClass("custom-button"); }); it("should merge className with asChild element", () => { render( , ); const button = screen.getByRole("button"); expect(button).toHaveClass("reset-class"); expect(button).toHaveClass("child-class"); }); it("should compose onClick handlers with asChild", () => { const childOnClick = jest.fn(); render( , ); fireEvent.click(screen.getByRole("button")); expect(childOnClick).toHaveBeenCalledTimes(1); }); }); describe("functionality", () => { it("should call onReset callback when clicked", () => { const handleReset = jest.fn(); render( Reset , ); fireEvent.click(screen.getByRole("button")); expect(handleReset).toHaveBeenCalledTimes(1); }); it("should pass puzzle context to onReset callback", () => { const handleReset = jest.fn(); render( Reset , ); fireEvent.click(screen.getByRole("button")); expect(handleReset).toHaveBeenCalledWith( expect.objectContaining({ puzzle: mockPuzzle, status: expect.any(String), changePuzzle: expect.any(Function), }), ); }); it("should have type button by default", () => { render( Reset , ); expect(screen.getByRole("button")).toHaveAttribute("type", "button"); }); }); describe("context validation", () => { it("should throw error when used outside ChessPuzzle.Root", () => { const consoleError = jest .spyOn(console, "error") .mockImplementation(() => {}); expect(() => { render(Reset); }).toThrow(); consoleError.mockRestore(); }); }); describe("children", () => { it("should render text children", () => { render( Reset Puzzle , ); expect(screen.getByRole("button")).toHaveTextContent("Reset Puzzle"); }); it("should render element children", () => { render( Reset Icon , ); expect(screen.getByTestId("child")).toBeInTheDocument(); }); it("should render without children", () => { render( , ); expect(screen.getByRole("button")).toBeInTheDocument(); }); }); describe("backward compatibility", () => { it("should work with minimal props when status matches default showOn", () => { // Since default showOn is ["failed", "solved"], we need to set showOn to see the button render( Reset , ); expect(screen.getByRole("button")).toBeInTheDocument(); }); }); });