import { fireEvent, render, screen } from "@testing-library/react";
import { usePathname } from "next/navigation";
import HoverPrefetchLink from "./HoverPrefetchLink";
jest.mock("next/navigation", () => ({ usePathname: jest.fn() }));
jest.mock("next/link", () => ({
__esModule: true,
default: ({
children,
prefetch,
...props
}: { children?: React.ReactNode; prefetch?: boolean | null } & Record<
string,
unknown
>) => (
{children}
),
}));
const link = () => screen.getByRole("link", { name: "Cases" });
beforeEach(() => {
jest.mocked(usePathname).mockReturnValue("/");
});
it("does not prefetch when the page opens", () => {
render(Cases);
expect(link()).toHaveAttribute("data-prefetch", "false");
expect(link()).toHaveAttribute("href", "/cases");
});
it.each([
["mouse", (element: Element) => fireEvent.mouseEnter(element)],
["keyboard focus", (element: Element) => fireEvent.focus(element)],
["touch", (element: Element) => fireEvent.touchStart(element)],
])("starts prefetching when the visitor reaches it by %s", (_label, reach) => {
render(Cases);
reach(link());
// null = o comportamento padrão do Link (pré-carrega a rota)
expect(link()).toHaveAttribute("data-prefetch", "null");
});
it("keeps the callers' own handlers", () => {
const onMouseEnter = jest.fn();
const onFocus = jest.fn();
const onClick = jest.fn();
render(
Cases
,
);
fireEvent.mouseEnter(link());
fireEvent.focus(link());
fireEvent.click(link());
expect(onMouseEnter).toHaveBeenCalledTimes(1);
expect(onFocus).toHaveBeenCalledTimes(1);
expect(onClick).toHaveBeenCalledTimes(1);
});
it("only prefetches the link that was reached, not its siblings", () => {
render(
<>
Cases
Serviços
>,
);
fireEvent.mouseEnter(link());
expect(link()).toHaveAttribute("data-prefetch", "null");
expect(screen.getByRole("link", { name: "Serviços" })).toHaveAttribute(
"data-prefetch",
"false",
);
});
describe("links para um ponto da home", () => {
it.each([["/#contact"], ["/#process"], ["/?tipo=site#contact"]])(
"never prefetches %s from another page, even on hover, focus or touch (it would pull the whole home)",
(href) => {
jest.mocked(usePathname).mockReturnValue("/privacidade");
render(Cases);
expect(link()).toHaveAttribute("data-prefetch", "false");
fireEvent.mouseEnter(link());
fireEvent.focus(link());
fireEvent.touchStart(link());
expect(link()).toHaveAttribute("data-prefetch", "false");
},
);
it("never prefetches an object href with the home path and a hash from another page", () => {
jest.mocked(usePathname).mockReturnValue("/cases");
render(
Cases
,
);
fireEvent.mouseEnter(link());
expect(link()).toHaveAttribute("data-prefetch", "false");
});
it("stops prefetching a home anchor that was reached on the home once the visitor moves to another page (the header does not remount)", () => {
jest.mocked(usePathname).mockReturnValue("/");
const { rerender } = render(
Cases,
);
fireEvent.mouseEnter(link());
expect(link()).toHaveAttribute("data-prefetch", "null");
jest.mocked(usePathname).mockReturnValue("/cases");
rerender(Cases);
expect(link()).toHaveAttribute("data-prefetch", "false");
});
it("keeps the hover prefetch for a home anchor while on the home itself (it is the same page)", () => {
jest.mocked(usePathname).mockReturnValue("/");
render(Cases);
fireEvent.mouseEnter(link());
expect(link()).toHaveAttribute("data-prefetch", "null");
});
it("keeps the hover prefetch for a link to another page, and for the home without a hash, from anywhere", () => {
jest.mocked(usePathname).mockReturnValue("/privacidade");
render(
<>
Cases
Início
Vídeo
Serviços
>,
);
for (const name of ["Cases", "Início", "Vídeo", "Serviços"]) {
const item = screen.getByRole("link", { name });
fireEvent.mouseEnter(item);
expect(item).toHaveAttribute("data-prefetch", "null");
}
});
it("still runs the caller's handlers on a home anchor seen from another page", () => {
jest.mocked(usePathname).mockReturnValue("/privacidade");
const onMouseEnter = jest.fn();
render(
Cases
,
);
fireEvent.mouseEnter(link());
expect(onMouseEnter).toHaveBeenCalledTimes(1);
});
it("prefetches as usual when the router is unknown (no pathname)", () => {
jest.mocked(usePathname).mockReturnValue(null as unknown as string);
render(Cases);
fireEvent.mouseEnter(link());
expect(link()).toHaveAttribute("data-prefetch", "null");
});
});