Files
portifolio-evandrodevbr/lib/analytics.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

190 lines
5.7 KiB
TypeScript

import {
GA_DISABLE_KEY,
readConsent,
trackEmailClick,
trackSocialClick,
trackWhatsAppOpen,
} from "./analytics";
/**
* Testes de caminhos-base de lib/analytics.ts (complemento de analytics.test.ts):
* modelo de rota de cada página (analyticsPagePath), cada condição que silencia o envio (sendEvent)
* e a conversão do Google Ads (sendAdsConversion) com e sem etiqueta, com e sem consentimento.
*/
const CONSENT_KEY = "evandro.analytics-consent.v1";
const ADS_LABEL = "NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL";
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];
window.history.replaceState({}, "", "/");
});
function gtagCalls() {
return (window.gtag as jest.Mock).mock.calls;
}
describe("analyticsPagePath (via the page_path sent with each event)", () => {
it.each([
["/", "/"],
["/servicos", "/servicos"],
["/cases", "/cases"],
["/curriculo", "/curriculo"],
["/privacidade", "/privacidade"],
["/ia", "/ia"],
["/cases/", "/cases"],
["/ia/?utm=x#y", "/ia"],
["/servicos/criacao-de-sites", "/servicos/[slug]"],
["/servicos/qualquer/coisa/mais", "/servicos/[slug]"],
["/cases/sev-modaintima", "/cases/[slug]"],
["/cases/ana%40example.com?x=1", "/cases/[slug]"],
["/servicos-extra", "/other"],
["/cases-extra/abc", "/other"],
["/nao-existe", "/other"],
])("path: location %s -> page_path %s", (location, expected) => {
window.history.replaceState({}, "", location);
trackSocialClick({ network: "linkedin" });
expect(gtagCalls()).toHaveLength(1);
expect(gtagCalls()[0][2]).toMatchObject({
page_path: expected,
page_location: `https://evandro.dev.br${expected}`,
page_referrer: "",
});
});
});
describe("sendEvent: cada condição que silencia o envio", () => {
it("path: gtag exists but is not a function -> nothing sent, no conversion, no error", () => {
process.env[ADS_LABEL] = "abc123";
window.gtag = "not-a-function" as never;
expect(() =>
trackWhatsAppOpen({ service: "S", placement: "p" }),
).not.toThrow();
expect(() => trackEmailClick({ placement: "p" })).not.toThrow();
});
it("path: stored consent is an unknown value -> treated as no consent", () => {
localStorage.setItem(CONSENT_KEY, "yes");
trackSocialClick({ network: "linkedin" });
expect(readConsent()).toBeNull();
expect(gtagCalls()).toHaveLength(0);
});
it("path: storage throws -> readConsent returns null and nothing is sent", () => {
jest.spyOn(Storage.prototype, "getItem").mockImplementation(() => {
throw new Error("storage blocked");
});
expect(readConsent()).toBeNull();
trackSocialClick({ network: "linkedin" });
expect(gtagCalls()).toHaveLength(0);
});
it("path: event counted -> one gtag call carrying the static params and the route template", () => {
window.history.replaceState({}, "", "/cases/sev-modaintima?q=1#x");
trackEmailClick({ placement: "footer" });
expect(gtagCalls()).toEqual([
[
"event",
"email_click",
{
send_to: "G-QTT9QT0T3S",
placement: "footer",
page_path: "/cases/[slug]",
page_location: "https://evandro.dev.br/cases/[slug]",
page_referrer: "",
},
],
]);
});
});
describe("sendAdsConversion: etiqueta x consentimento", () => {
it.each([
["is unset", undefined],
["is an empty string", ""],
])(
"path: label %s, consent granted -> only the GA4 event goes out",
(_l, label) => {
if (label !== undefined) process.env[ADS_LABEL] = label;
trackWhatsAppOpen({ service: "Contato", placement: "floating" });
trackEmailClick({ placement: "footer" });
expect(gtagCalls().map(([, name]) => name)).toEqual([
"whatsapp_open",
"email_click",
]);
},
);
it("path: label set, consent denied -> nothing at all, not even the conversion", () => {
process.env[ADS_LABEL] = "abc123";
localStorage.setItem(CONSENT_KEY, "denied");
trackWhatsAppOpen({ service: "Contato", placement: "floating" });
trackEmailClick({ placement: "footer" });
expect(gtagCalls()).toHaveLength(0);
});
it("path: label set, consent granted -> the conversion uses the Ads id and the label", () => {
process.env[ADS_LABEL] = "xyz-789";
trackWhatsAppOpen({ service: "Contato", placement: "floating" });
expect(gtagCalls().map(([, name]) => name)).toEqual([
"whatsapp_open",
"conversion",
]);
expect(gtagCalls()[1][2]).toEqual({
send_to: "AW-18432694647/xyz-789",
});
});
it("path: the conversion call throws -> the click handler still returns normally", () => {
process.env[ADS_LABEL] = "abc123";
window.gtag = jest.fn((_command: unknown, name: unknown) => {
if (name === "conversion") throw new Error("ads blocked");
});
expect(() =>
trackWhatsAppOpen({ service: "Contato", placement: "floating" }),
).not.toThrow();
expect(gtagCalls().map(([, name]) => name)).toEqual([
"whatsapp_open",
"conversion",
]);
});
it("path: gtag disappears right after the event was counted -> the conversion is skipped silently", () => {
process.env[ADS_LABEL] = "abc123";
const gtag = jest.fn(() => {
delete window.gtag;
});
window.gtag = gtag;
expect(() => trackEmailClick({ placement: "footer" })).not.toThrow();
expect(gtag).toHaveBeenCalledTimes(1);
});
});