import { describe, it, expect, beforeEach, afterEach } from "vitest"; import { render, screen } from "@testing-library/react"; import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "@/components/ui"; describe("Select Dropdown - Viewport Awareness", () => { let originalInnerHeight: number; beforeEach(() => { originalInnerHeight = window.innerHeight; }); afterEach(() => { // Restore original window height Object.defineProperty(window, "innerHeight", { writable: true, configurable: true, value: originalInnerHeight, }); }); it("should render Select component with trigger and content", () => { render( ); // Trigger should be visible expect(screen.getByRole("button")).toBeInTheDocument(); }); it("should apply bottom-full class when flipped upward", () => { // Test verifies the flip logic when dropdown is near bottom of viewport // Simulating a dropdown positioned 10px from viewport bottom const dropdownBottom = window.innerHeight - 10; const spaceBelow = window.innerHeight - dropdownBottom; const shouldFlipUpward = spaceBelow < 20; expect(shouldFlipUpward).toBe(true); }); it("should apply top-full class when sufficient space below", () => { const mockBottom = 300; // Plenty of space below const viewportHeight = 1080; const spaceBelow = viewportHeight - mockBottom; const shouldFlipUpward = spaceBelow < 20; expect(shouldFlipUpward).toBe(false); }); it("should use 20px threshold for flip decision", () => { const threshold = 20; // Just above threshold - should not flip const spaceBelowAbove = 21; expect(spaceBelowAbove < threshold).toBe(false); // Just below threshold - should flip const spaceBelowBelow = 19; expect(spaceBelowBelow < threshold).toBe(true); // Exactly at threshold - should flip const spaceBelowExact = 20; expect(spaceBelowExact < threshold).toBe(false); }); it("should calculate space below correctly", () => { const viewportHeight = 1080; const dropdownBottom = 950; const expectedSpaceBelow = viewportHeight - dropdownBottom; expect(expectedSpaceBelow).toBe(130); expect(expectedSpaceBelow < 20).toBe(false); // Should not flip }); it("should handle edge case at exact viewport bottom", () => { const viewportHeight = 1080; const dropdownBottom = 1080; // Exactly at bottom const spaceBelow = viewportHeight - dropdownBottom; expect(spaceBelow).toBe(0); expect(spaceBelow < 20).toBe(true); // Should flip }); it("should handle edge case beyond viewport", () => { const viewportHeight = 1080; const dropdownBottom = 1100; // Beyond viewport const spaceBelow = viewportHeight - dropdownBottom; expect(spaceBelow).toBe(-20); expect(spaceBelow < 20).toBe(true); // Should flip }); }); describe("Select Dropdown - CSS Classes", () => { it("should use correct classes for downward expansion", () => { const flipUpward = false; const classes = flipUpward ? "bottom-full mb-1" : "top-full mt-1"; expect(classes).toBe("top-full mt-1"); }); it("should use correct classes for upward expansion", () => { const flipUpward = true; const classes = flipUpward ? "bottom-full mb-1" : "top-full mt-1"; expect(classes).toBe("bottom-full mb-1"); }); it("should include common classes regardless of flip direction", () => { const commonClasses = "absolute z-50 max-h-60 w-full overflow-auto rounded-md border bg-card p-1 shadow-md"; // These classes should always be present expect(commonClasses).toContain("absolute"); expect(commonClasses).toContain("z-50"); expect(commonClasses).toContain("max-h-60"); }); });