import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it } from "vitest";
import { useFocusTrap } from "./index";
afterEach(() => {
    cleanup();
});
function TestComponent({ active = true }) {
    const ref = useFocusTrap(active);
    return (<div>
            <button type="button" data-testid="outside">Outside</button>
            <div ref={ref} data-testid="trap">
                <button type="button">First</button>
                <button type="button">Second</button>
                <button type="button">Third</button>
            </div>
        </div>);
}
describe("useFocusTrap", () => {
    it("should not focus element on mount even when active (current implementation behavior)", () => {
        render(<TestComponent active={true}/>);
        expect(document.activeElement).toBe(document.body);
    });
    it("should trap focus when active and something outside is focused", async () => {
        render(<TestComponent active={true}/>);
        const firstButton = screen.getByText("First");
        const outsideButton = screen.getByTestId("outside");
        // Focus outside should be dragged back to the trap
        outsideButton.focus();
        // The focusin$ observable should catch this and focusFirstDescendant
        expect(document.activeElement).toBe(firstButton);
    });
    it("should NOT trap focus when inactive", () => {
        render(<TestComponent active={false}/>);
        const outsideButton = screen.getByTestId("outside");
        outsideButton.focus();
        expect(document.activeElement).toBe(outsideButton);
    });
    it("should wrap focus to the first element when Tabbing from the last element", () => {
        render(<TestComponent active={true}/>);
        const firstButton = screen.getByText("First");
        const thirdButton = screen.getByText("Third");
        thirdButton.focus();
        expect(document.activeElement).toBe(thirdButton);
        // Simulate Tab key on the last element
        fireEvent.keyDown(thirdButton, { key: "Tab" });
        expect(document.activeElement).toBe(firstButton);
    });
    it("should wrap focus to the last element when Shift-Tabbing from the first element", () => {
        render(<TestComponent active={true}/>);
        const firstButton = screen.getByText("First");
        const thirdButton = screen.getByText("Third");
        firstButton.focus();
        expect(document.activeElement).toBe(firstButton);
        // Simulate Shift-Tab key on the first element
        fireEvent.keyDown(firstButton, { key: "Tab", shiftKey: true });
        expect(document.activeElement).toBe(thirdButton);
    });
    it("should focus the last element when 'returning' to the first element if we were already there (clever Shift-Tab-out handling)", () => {
        render(<TestComponent active={true}/>);
        const firstButton = screen.getByText("First");
        const thirdButton = screen.getByText("Third");
        const outsideButton = screen.getByTestId("outside");
        // 1. Focus the first element inside the trap
        firstButton.focus();
        expect(document.activeElement).toBe(firstButton);
        // 2. Focus something outside (like a browser would if you Shift-Tabbed out)
        outsideButton.focus();
        // The trap should recognize we were on First, and focusFirstDescendant would put us back on First.
        // So it should trigger the focus-last-descendant logic.
        expect(document.activeElement).toBe(thirdButton);
    });
});
