Files
portifolio-evandrodevbr/lib/analytics.server.paths.test.ts
T
Evandro Fonseca Junior 8d07b8c6bb feat(home): prova no topo, contato sem atrito e conversão medida
Home mais curta (hero, vitrine de clientes, sobre, serviços, IA resumida, depoimentos e contato), faixa de clientes e telas reais no hero, sem números do GitHub. Barra de cookies fina, WhatsApp fixo no celular, formulário com e-mail opcional e alternativa por e-mail, página /ia, eventos de e-mail, redes e currículo e conversão do Ads opcional por variável. Rodapé em 3 colunas. Remove componentes órfãos (LighthouseMetrics, Skills, Experience, contagem do GitHub).
2026-10-14 03:32:23 -03:00

104 lines
3.4 KiB
TypeScript

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