import { GA_DISABLE_KEY, OPEN_COOKIE_PREFERENCES_EVENT, openCookiePreferences, trackCvDownload, trackEmailClick, trackSocialClick, trackWhatsAppOpen, } from "./analytics"; const CONSENT_KEY = "evandro.analytics-consent.v1"; const ADS_LABEL = "NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL"; const common = { send_to: "G-QTT9QT0T3S", page_path: "/", page_location: "https://evandro.dev.br/", page_referrer: "", }; beforeEach(() => { jest.replaceProperty(process.env, "NODE_ENV", "production"); localStorage.setItem(CONSENT_KEY, "granted"); delete window[GA_DISABLE_KEY]; window.gtag = jest.fn(); window.history.replaceState({}, "", "/"); }); afterEach(() => { jest.restoreAllMocks(); localStorage.clear(); delete window.gtag; delete process.env[ADS_LABEL]; }); describe("events", () => { it("sends email_click, social_click and cv_download with static labels only", () => { trackEmailClick({ placement: "footer" }); trackSocialClick({ network: "linkedin" }); trackCvDownload({ placement: "curriculo" }); expect(window.gtag).toHaveBeenNthCalledWith(1, "event", "email_click", { ...common, placement: "footer", }); expect(window.gtag).toHaveBeenNthCalledWith(2, "event", "social_click", { ...common, network: "linkedin", }); expect(window.gtag).toHaveBeenNthCalledWith(3, "event", "cv_download", { ...common, placement: "curriculo", }); expect(window.gtag).toHaveBeenCalledTimes(3); }); it("reports the floating button as a whatsapp_open placement", () => { trackWhatsAppOpen({ service: "Contato", placement: "floating" }); expect(window.gtag).toHaveBeenCalledWith("event", "whatsapp_open", { ...common, service: "Contato", placement: "floating", }); }); it("knows the /ia page instead of lumping it into /other", () => { window.history.replaceState({}, "", "/ia?x=1#y"); trackEmailClick({ placement: "ia" }); expect(window.gtag).toHaveBeenCalledWith( "event", "email_click", expect.objectContaining({ page_path: "/ia", page_location: "https://evandro.dev.br/ia", }), ); }); it.each([ ["without consent", () => localStorage.removeItem(CONSENT_KEY)], ["after refusal", () => localStorage.setItem(CONSENT_KEY, "denied")], [ "when GA is disabled", () => Object.assign(window, { [GA_DISABLE_KEY]: true }), ], ["when gtag is missing", () => delete window.gtag], ])("sends nothing %s", (_label, arrange) => { process.env[ADS_LABEL] = "abc123"; const gtag = window.gtag as jest.Mock; arrange(); trackWhatsAppOpen({ service: "Contato", placement: "floating" }); trackEmailClick({ placement: "footer" }); trackSocialClick({ network: "linkedin" }); trackCvDownload({ placement: "curriculo" }); expect(gtag).not.toHaveBeenCalled(); }); it("sends nothing outside production", () => { jest.replaceProperty(process.env, "NODE_ENV", "development"); trackEmailClick({ placement: "footer" }); expect(window.gtag).not.toHaveBeenCalled(); }); it("never throws when gtag fails", () => { window.gtag = jest.fn(() => { throw new Error("blocked"); }); expect(() => trackEmailClick({ placement: "footer" })).not.toThrow(); }); }); describe("Google Ads conversion", () => { it("is not sent without the conversion label", () => { trackWhatsAppOpen({ service: "Contato", placement: "floating" }); trackEmailClick({ placement: "footer" }); expect(window.gtag).toHaveBeenCalledTimes(2); for (const [, name] of (window.gtag as jest.Mock).mock.calls) { expect(name).not.toBe("conversion"); } }); it("goes out next to whatsapp_open and email_click when the label exists", () => { process.env[ADS_LABEL] = "abc123"; trackWhatsAppOpen({ service: "Contato", placement: "floating" }); trackEmailClick({ placement: "footer" }); const calls = (window.gtag as jest.Mock).mock.calls; expect(calls.map(([, name]) => name)).toEqual([ "whatsapp_open", "conversion", "email_click", "conversion", ]); expect(calls[1]).toEqual([ "event", "conversion", { send_to: "AW-18432694647/abc123" }, ]); }); it("does not turn social clicks or CV downloads into Ads conversions", () => { process.env[ADS_LABEL] = "abc123"; trackSocialClick({ network: "linkedin" }); trackCvDownload({ placement: "curriculo" }); expect(window.gtag).toHaveBeenCalledTimes(2); }); }); describe("cookie preferences", () => { it("asks the consent bar to reopen through a window event", () => { const listener = jest.fn(); window.addEventListener(OPEN_COOKIE_PREFERENCES_EVENT, listener); openCookiePreferences(); window.removeEventListener(OPEN_COOKIE_PREFERENCES_EVENT, listener); expect(listener).toHaveBeenCalledTimes(1); }); });