import { act, fireEvent, render, screen } from "@testing-library/react"; import FloatingWhatsApp from "./FloatingWhatsApp"; const CONSENT_KEY = "evandro.analytics-consent.v1"; type Entry = Pick; let notify: (entries: Entry[]) => void = () => {}; const originalObserver = global.IntersectionObserver; class FakeObserver { constructor(callback: IntersectionObserverCallback) { notify = (entries) => callback(entries as IntersectionObserverEntry[], this as never); } observe = jest.fn(); unobserve = jest.fn(); disconnect = jest.fn(); takeRecords = () => []; } function Page({ withInvites = true }: { withInvites?: boolean }) { return ( <> {withInvites && ( <> Conversar sobre meu projeto
)} ); } function setVisibility(hero: boolean, contact: boolean) { act(() => notify([ { target: document.getElementById("hero-contact-cta") as Element, isIntersecting: hero, }, { target: document.getElementById("contact") as Element, isIntersecting: contact, }, ]), ); } const floatingLink = () => screen.queryByRole("link", { name: "Conversar no WhatsApp" }); beforeEach(() => { global.IntersectionObserver = FakeObserver as unknown as typeof IntersectionObserver; jest.replaceProperty(process.env, "NODE_ENV", "production"); localStorage.setItem(CONSENT_KEY, "granted"); window.gtag = jest.fn(); }); afterEach(() => { global.IntersectionObserver = originalObserver; jest.restoreAllMocks(); localStorage.clear(); delete window.gtag; }); it("stays hidden until the observer reports, then shows a 56px WhatsApp shortcut for small screens", () => { render(); expect(floatingLink()).toBeNull(); setVisibility(false, false); const link = floatingLink(); expect(link).toBeInTheDocument(); expect(link).toHaveAttribute("target", "_blank"); expect(link).toHaveAttribute("rel", "noopener noreferrer"); const url = new URL(link?.getAttribute("href") ?? ""); expect(url.origin).toBe("https://wa.me"); expect(url.searchParams.get("text")).toContain( "Quero conversar sobre um projeto.", ); // alvo de 56 px, canto inferior direito, só abaixo de 768 px expect(link).toHaveClass("h-14", "w-14"); expect(link?.parentElement).toHaveClass("fixed", "right-sp-4", "md:hidden"); }); it("hides while the hero button is on screen", () => { render(); setVisibility(true, false); expect(floatingLink()).toBeNull(); setVisibility(false, false); expect(floatingLink()).toBeInTheDocument(); }); it("hides while the contact section is on screen", () => { render(); setVisibility(false, true); expect(floatingLink()).toBeNull(); setVisibility(false, false); expect(floatingLink()).toBeInTheDocument(); }); it("shows right away on a page that has neither the hero button nor the contact section", () => { render(); expect(floatingLink()).toBeInTheDocument(); }); it("lifts itself by the height of the open cookie bar", () => { render(); setVisibility(false, false); expect(floatingLink()?.parentElement?.className).toContain( "var(--cookie-bar-height,0px)", ); }); it("reports the click as a floating WhatsApp handoff", () => { render(); setVisibility(false, false); fireEvent.click(floatingLink() as HTMLElement, { button: 0 }); expect(window.gtag).toHaveBeenCalledTimes(1); expect(window.gtag).toHaveBeenCalledWith( "event", "whatsapp_open", expect.objectContaining({ placement: "floating" }), ); });