import React from "react"; import { render, screen } from "@testing-library/react"; import { Stack } from "./stack"; describe("Stack", () => { // ============================================================================ // Rendering Tests // ============================================================================ it("renders with default props", () => { render(Content); expect(screen.getByText("Content")).toBeInTheDocument(); }); it("renders children correctly", () => { render( Child 1 Child 2 ); expect(screen.getByText("Child 1")).toBeInTheDocument(); expect(screen.getByText("Child 2")).toBeInTheDocument(); }); it("renders as div by default", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack.tagName).toBe("DIV"); }); it("always has base stack class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack"); }); // ============================================================================ // Polymorphic Rendering Tests // ============================================================================ it("renders as different elements via as prop", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack.tagName).toBe("SECTION"); }); it("renders as article", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack.tagName).toBe("ARTICLE"); }); it("renders as nav", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack.tagName).toBe("NAV"); }); it("renders as ul", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack.tagName).toBe("UL"); }); it("renders as ol", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack.tagName).toBe("OL"); }); // ============================================================================ // Direction Class Tests // ============================================================================ it("applies vertical direction class by default", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-vertical"); }); it("applies vertical direction class explicitly", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-vertical"); }); it("applies horizontal direction class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-horizontal"); }); // ============================================================================ // Gap Class Tests // ============================================================================ it("applies gap-0 class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-gap-0"); }); it("applies gap-xs class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-gap-xs"); }); it("applies gap-sm class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-gap-sm"); }); it("applies gap-md class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-gap-md"); }); it("applies gap-lg class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-gap-lg"); }); it("applies gap-xl class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-gap-xl"); }); // ============================================================================ // Align Class Tests (Cross-Axis) // ============================================================================ it("applies align-start class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-align-start"); }); it("applies align-center class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-align-center"); }); it("applies align-end class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-align-end"); }); it("applies align-stretch class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-align-stretch"); }); // ============================================================================ // Justify Class Tests (Main-Axis) // ============================================================================ it("applies justify-start class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-justify-start"); }); it("applies justify-center class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-justify-center"); }); it("applies justify-end class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-justify-end"); }); it("applies justify-between class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-justify-between"); }); // ============================================================================ // Wrap Class Tests // ============================================================================ it("applies wrap class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-wrap"); }); it("applies nowrap class", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-nowrap"); }); // ============================================================================ // Multiple Props Tests // ============================================================================ it("applies multiple utility classes", () => { render( Content ); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack"); expect(stack).toHaveClass("stack-horizontal"); expect(stack).toHaveClass("stack-gap-lg"); expect(stack).toHaveClass("stack-align-center"); expect(stack).toHaveClass("stack-justify-between"); expect(stack).toHaveClass("stack-wrap"); }); it("combines vertical direction with other props", () => { render( Content ); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-vertical"); expect(stack).toHaveClass("stack-gap-md"); expect(stack).toHaveClass("stack-align-start"); expect(stack).toHaveClass("stack-justify-center"); }); // ============================================================================ // Custom Class Tests // ============================================================================ it("merges custom className with utility classes", () => { render( Content ); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack"); expect(stack).toHaveClass("stack-vertical"); expect(stack).toHaveClass("stack-gap-md"); expect(stack).toHaveClass("custom-class"); }); it("merges custom classes prop with utility classes", () => { render( Content ); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack"); expect(stack).toHaveClass("stack-gap-md"); expect(stack).toHaveClass("legacy-class"); }); it("merges both className and classes with utility classes", () => { render( Content ); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack"); expect(stack).toHaveClass("stack-gap-md"); expect(stack).toHaveClass("custom-class"); expect(stack).toHaveClass("legacy-class"); }); // ============================================================================ // Inline Styles Tests // ============================================================================ it("applies custom styles", () => { render( Content ); const stack = screen.getByTestId("stack"); expect(stack).toHaveStyle({ backgroundColor: "rgb(255, 0, 0)" }); expect(stack).toHaveStyle({ color: "rgb(255, 255, 255)" }); }); it("accepts CSS custom properties in styles", () => { render( Content ); const stack = screen.getByTestId("stack"); expect(stack).toHaveAttribute("style"); }); // ============================================================================ // Ref Forwarding Tests // ============================================================================ it("forwards ref correctly", () => { const ref = React.createRef(); render( Content ); expect(ref.current).toBeInstanceOf(HTMLDivElement); }); it("forwards ref with polymorphic as prop", () => { const ref = React.createRef(); render( Content ); expect(ref.current).toBeInstanceOf(HTMLElement); expect(ref.current?.tagName).toBe("SECTION"); }); // ============================================================================ // Accessibility Tests // ============================================================================ it("forwards ARIA attributes", () => { render( Content ); const stack = screen.getByTestId("stack"); expect(stack).toHaveAttribute("aria-label", "Test Stack"); expect(stack).toHaveAttribute("role", "region"); }); it("forwards data attributes", () => { render( Content ); const stack = screen.getByTestId("stack"); expect(stack).toHaveAttribute("data-custom", "value"); }); // ============================================================================ // Edge Cases // ============================================================================ it("handles empty children", () => { render(); const stack = screen.getByTestId("stack"); expect(stack).toBeInTheDocument(); expect(stack).toBeEmptyDOMElement(); }); it("handles no optional props gracefully", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toBeInTheDocument(); expect(stack).toHaveClass("stack"); expect(stack).toHaveClass("stack-vertical"); expect(stack.tagName).toBe("DIV"); }); it("handles only direction prop", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack"); expect(stack).toHaveClass("stack-horizontal"); // Should not have gap, align, justify, or wrap classes when not provided expect(stack.className.split(" ").length).toBe(2); // only "stack" and "stack-horizontal" }); // ============================================================================ // Layout Behavior Tests // ============================================================================ it("creates vertical flex container by default", () => { render(Content); const stack = screen.getByTestId("stack"); // Base stack class ensures display: flex is applied expect(stack).toHaveClass("stack"); }); it("creates horizontal flex container when direction is horizontal", () => { render(Content); const stack = screen.getByTestId("stack"); expect(stack).toHaveClass("stack-horizontal"); }); });