import { render, screen } from "@testing-library/react" import React from "react" import "@testing-library/jest-dom" import { PageLoader } from "./PageLoader" describe("PageLoader", () => { describe("Rendering", () => { it("renders correctly with various props", () => { render( , ) const loader = screen.getByRole("status") expect(loader).toBeInTheDocument() expect(loader).toHaveAttribute("data-testid", "test-loader") expect(loader).toHaveAttribute("aria-label", "Loading content") expect(loader).toHaveClass("custom-loader") }) it("renders with minimum props", () => { render() const loader = screen.getByRole("status") expect(loader).toBeInTheDocument() expect(loader).toHaveAttribute("aria-label", "Loading") }) }) describe("Sizes", () => { it.each([ { size: "xs" as const, expectedClass: "size--xs" }, { size: "sm" as const, expectedClass: "size--sm" }, { size: "md" as const, expectedClass: "size--md" }, { size: "lg" as const, expectedClass: "size--lg" }, { size: "xl" as const, expectedClass: "size--xl" }, ])("applies $size size", ({ size, expectedClass }) => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass(expectedClass) }) it("applies default size", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass("size--md") }) it("changes size dynamically", () => { const { rerender } = render() const loader = screen.getByRole("status") expect(loader).toHaveClass("size--sm") rerender() expect(loader).toHaveClass("size--lg") }) }) describe("Emphasis", () => { it.each([ { emphasis: "subtle" as const, expectedClass: "emphasis--subtle" }, { emphasis: "normal" as const, expectedClass: "emphasis--normal" }, { emphasis: "strong" as const, expectedClass: "emphasis--strong" }, ])("applies $emphasis emphasis", ({ emphasis, expectedClass }) => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass(expectedClass) }) it("applies default emphasis", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass("emphasis--normal") }) }) describe("Tone", () => { it.each([ { tone: "neutral" as const, expectedClass: "tone--neutral" }, { tone: "accent" as const, expectedClass: "tone--accent" }, { tone: "positive" as const, expectedClass: "tone--positive" }, { tone: "critical" as const, expectedClass: "tone--critical" }, ])("applies $tone tone", ({ tone, expectedClass }) => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass(expectedClass) }) it("applies default tone", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass("tone--accent") }) }) describe("Animation Speed", () => { it.each([ { speed: "slow" as const, expectedClass: "speed--slow" }, { speed: "normal" as const, expectedClass: "speed--normal" }, { speed: "fast" as const, expectedClass: "speed--fast" }, ])("applies $speed speed", ({ speed, expectedClass }) => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass(expectedClass) }) it("applies default speed", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass("speed--normal") }) }) describe("Display Modes", () => { it.each([ { display: "inline" as const, expectedClass: "display--inline" }, { display: "block" as const, expectedClass: "display--block" }, { display: "overlay" as const, expectedClass: "display--overlay" }, ])("applies $display display", ({ display, expectedClass }) => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass(expectedClass) }) it("applies default display", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass("display--inline") }) it("applies backdrop with overlay mode", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass("display--overlay", "withBackdrop") }) }) describe("Label", () => { it("renders with custom label", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveAttribute("aria-label", "Custom loading text") }) it("renders label text in non-overlay mode", () => { render() expect(screen.getByText("Processing...")).toBeInTheDocument() }) it("does not render label text in overlay mode", () => { render() expect(screen.queryByText("Processing...")).not.toBeInTheDocument() }) it("renders with default label", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveAttribute("aria-label", "Loading") }) }) describe("CSS Classes", () => { it("applies base loader classes", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass("loader") }) it("applies custom className", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass("my-custom-class") }) it("combines all classes correctly", () => { render( , ) const loader = screen.getByRole("status") expect(loader).toHaveClass( "loader", "emphasis--strong", "tone--positive", "size--lg", "speed--fast", "display--block", "custom", ) }) }) describe("HTML Attributes", () => { it("passes through id", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveAttribute("id", "my-loader") }) it("passes through data attributes", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveAttribute("data-testid", "test") expect(loader).toHaveAttribute("data-custom", "value") }) it("has correct ARIA attributes", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveAttribute("role", "status") expect(loader).toHaveAttribute("aria-live", "polite") }) }) describe("Spinner Structure", () => { it("contains spinner element", () => { const { container } = render() const spinner = container.querySelector(".spinner") expect(spinner).toBeInTheDocument() expect(spinner).toHaveAttribute("aria-hidden", "true") }) it("maintains structure with different props", () => { const { container } = render( , ) const spinner = container.querySelector(".spinner") expect(spinner).toBeInTheDocument() }) }) describe("ResponsiveValue Support", () => { it("handles responsive size values", () => { render( , ) const loader = screen.getByRole("status") expect(loader).toBeInTheDocument() // Note: Actual responsive behavior would need to be tested with viewport changes }) it("handles responsive emphasis values", () => { render( , ) const loader = screen.getByRole("status") expect(loader).toBeInTheDocument() }) it("handles mixed responsive and static values", () => { render( , ) const loader = screen.getByRole("status") expect(loader).toBeInTheDocument() }) }) describe("Edge Cases", () => { it("handles undefined props gracefully", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveClass("size--md", "tone--accent") }) it("handles rapid prop changes", () => { const { rerender } = render() const loader = screen.getByRole("status") expect(loader).toHaveClass("emphasis--subtle") rerender() expect(loader).toHaveClass("emphasis--normal") rerender() expect(loader).toHaveClass("emphasis--strong") }) it("handles multiple instances", () => { render( <> , ) expect(screen.getByTestId("first")).toBeInTheDocument() expect(screen.getByTestId("second")).toBeInTheDocument() expect(screen.getByTestId("third")).toBeInTheDocument() }) it("cleans up properly on unmount", () => { const { unmount } = render() expect(screen.getByRole("status")).toBeInTheDocument() unmount() expect(screen.queryByRole("status")).not.toBeInTheDocument() }) }) describe("Accessibility", () => { it("has proper loader semantics", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveAttribute("role", "status") expect(loader).toHaveAttribute("aria-live", "polite") }) it("supports custom ARIA attributes", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveAttribute("aria-describedby", "description") expect(loader).toHaveAttribute("aria-busy", "true") }) it("provides accessible label", () => { render() const loader = screen.getByRole("status") expect(loader).toHaveAttribute( "aria-label", "Please wait while we load your data", ) }) }) })