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"); }); });