import { readFileSync } from "node:fs"; import { join } from "node:path"; import ts from "typescript"; /** * Caminhos de lib/analytics.ts quando não existe `window` (renderização no servidor): nenhum rastreio, * nenhuma conversão e nenhum erro. O setup do projeto exige o jsdom e o `window` dele não pode ser * escondido, então o próprio fonte é transpilado e executado com `window` e `localStorage` indefinidos. */ type AnalyticsModule = typeof import("./analytics"); const ADS_LABEL = "NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL"; function loadWithoutWindow(storage?: Storage): AnalyticsModule { const source = readFileSync(join(process.cwd(), "lib/analytics.ts"), "utf8"); const { outputText } = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020, }, }); const loaded = { exports: {} as AnalyticsModule }; new Function("module", "exports", "window", "localStorage", outputText)( loaded, loaded.exports, undefined, storage, ); return loaded.exports; } let gtag: jest.Mock; beforeEach(() => { jest.replaceProperty(process.env, "NODE_ENV", "production"); process.env[ADS_LABEL] = "abc123"; localStorage.setItem("evandro.analytics-consent.v1", "granted"); gtag = jest.fn(); window.gtag = gtag; }); afterEach(() => { jest.restoreAllMocks(); localStorage.clear(); delete window.gtag; delete process.env[ADS_LABEL]; }); describe("analytics without a window", () => { it("path: every tracker is silent and never throws, even with granted consent and a conversion label", () => { // o consentimento está "granted" no storage real: só a ausência de `window` impede o envio const analytics = loadWithoutWindow(localStorage); expect(() => { analytics.trackWhatsAppOpen({ service: "Contato", placement: "floating", }); analytics.trackEmailClick({ placement: "footer" }); analytics.trackSocialClick({ network: "linkedin" }); analytics.trackCvDownload({ placement: "curriculo" }); }).not.toThrow(); expect(gtag).not.toHaveBeenCalled(); }); it("path: readConsent finds no storage -> null", () => { expect(loadWithoutWindow().readConsent()).toBeNull(); }); it("path: openCookiePreferences has no window to notify -> returns without error", () => { const listener = jest.fn(); window.addEventListener("evandro:open-cookie-preferences", listener); expect(() => loadWithoutWindow().openCookiePreferences()).not.toThrow(); window.removeEventListener("evandro:open-cookie-preferences", listener); expect(listener).not.toHaveBeenCalled(); }); it("control: the same source with a window does dispatch the reopen event", () => { const listener = jest.fn(); window.addEventListener("evandro:open-cookie-preferences", listener); const source = readFileSync( join(process.cwd(), "lib/analytics.ts"), "utf8", ); const { outputText } = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS }, }); const loaded = { exports: {} as AnalyticsModule }; new Function("module", "exports", "window", outputText)( loaded, loaded.exports, window, ); loaded.exports.openCookiePreferences(); window.removeEventListener("evandro:open-cookie-preferences", listener); expect(listener).toHaveBeenCalledTimes(1); }); });