import { describe, it, expect } from "vitest";
import { render, screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";

import {
  Tooltip,
  TooltipProvider,
  TooltipRoot,
  TooltipTrigger,
  TooltipPositioner,
  TooltipPopup,
} from "./tooltip";

describe("Tooltip", () => {
  it("shows its content in a portal on hover", async () => {
    const user = userEvent.setup();

    render(
      <Tooltip content="Objects">
        <button type="button">Objects nav</button>
      </Tooltip>,
    );

    const trigger = screen.getByRole("button", { name: "Objects nav" });
    const body = within(document.body);

    expect(body.queryByText("Objects")).toBeNull();

    await user.hover(trigger);

    expect(await body.findByText("Objects")).toBeVisible();
  });

  it("shows its content on keyboard focus", async () => {
    const user = userEvent.setup();

    render(
      <Tooltip content="Help text">
        <button type="button">Focusable</button>
      </Tooltip>,
    );

    const body = within(document.body);

    await user.tab();

    expect(await body.findByText("Help text")).toBeVisible();
  });

  it("delegates the trigger element via render (keeps the host tag)", () => {
    render(
      <Tooltip content="Tip">
        <a href="/objects">Go</a>
      </Tooltip>,
    );

    const link = screen.getByRole("link", { name: "Go" });
    expect(link).toHaveAttribute("href", "/objects");
  });

  it("composes from the raw parts", async () => {
    const user = userEvent.setup();

    render(
      <TooltipProvider delay={0}>
        <TooltipRoot>
          <TooltipTrigger render={<button type="button">Raw</button>} />
          <TooltipPrimitive.Portal>
            <TooltipPositioner side="bottom">
              <TooltipPopup>Raw tip</TooltipPopup>
            </TooltipPositioner>
          </TooltipPrimitive.Portal>
        </TooltipRoot>
      </TooltipProvider>,
    );

    await user.hover(screen.getByRole("button", { name: "Raw" }));

    const body = within(document.body);
    expect(await body.findByText("Raw tip")).toBeVisible();
  });
});
