teqo-backup/tests/e2e/campaignHomePixel.e2e.spec.ts
Francisco Solla 5635e6522c feat(site): vira o site público para o mandato pós-eleição (S47)
Home abre no agradecimento pelos 152.049 votos com board 1+3, trajetória, bandeiras do mandato, galeria de fotos e rodapé institucional; chrome novo (header home/interno, lockup de nome, menu mobile acessível) e /artigos//fotos com título compacto.

As superfícies de campanha saem do ar (308 de /conteudos, /jingles e /cards), junto com newsletter, estúdio público de cards e UI da Central/jingles; download de foto e .ics perdem o 1313. Sem migration, sem Consent novo e sem apagar dados do CMS.
2026-10-22 02:16:08 -03:00

95 lines
4.1 KiB
TypeScript

import type { APIRequestContext } from '@playwright/test'
import { adminHeaders } from '../helpers/adminApi'
import { seedTestUser } from '../helpers/seedUser'
import { expect, test } from './fixtures/e2eTest'
/**
* S10 — the Meta pixel on the public campaign page: configured through
* `SiteSettings.tracking.facebookPixelId` (admin REST), the home renders the
* base code (inline `next/script` + `fbq` init) and nothing at all without a
* configured ID (fail-closed). The external `fbevents.js` fetch is fulfilled
* locally by the shared e2e guard (fixtures/e2eTest.ts), so no spec ever
* depends on the Meta CDN; the base code itself is inline. S47 removed the
* campaign newsletter capture, so the old capture→Lead assertion is gone; the
* pixel stays a page-level PageView. Serial mode (precedent
* `campaignNearestMunicipality`): the tests share one worker — a parallel
* split would race two `seedTestUser` beforeAlls.
*/
test.describe.configure({ mode: 'serial' })
test.describe('Campaign home Meta pixel', () => {
const baseURL = process.env.PLAYWRIGHT_BASE_URL ?? 'http://localhost:3000'
const runSuffix = Date.now()
// Valid 15-digit numeric ID (same class the admin validation accepts).
const PIXEL_ID = '123456789012345'
// `_status: 'published'` publishes through the global's draft pipeline, same
// pattern the frontend spec uses for versioned documents.
const setSitePixel = async (
request: APIRequestContext,
headers: Record<string, string>,
pixelId: string | null,
) => {
// Insurance against the same-user concurrent-login session race with
// specs that do NOT route their login through the advisory-locked
// `adminHeaders` helper (e.g. the frontend spec's inline logins): a 403
// means the session row was lost to another worker — re-login mints a
// fresh one. The locked helper already serializes the specs that use it.
for (let attempt = 0; attempt < 2; attempt += 1) {
const response = await request.post(`${baseURL}/api/globals/site-settings`, {
headers,
data: { tracking: { facebookPixelId: pixelId }, _status: 'published' },
})
if (response.ok()) return
if (response.status() === 403 && attempt === 0) {
headers = await adminHeaders(request, baseURL)
continue
}
throw new Error(`setSitePixel(${pixelId}) failed with ${response.status()}`)
}
}
test.beforeAll(async ({ request }) => {
await seedTestUser()
// Self-healing lifecycle (S9 precedent): an aborted run could leave the
// pixel behind and poison the fail-closed assertion — purge first.
const headers = await adminHeaders(request, baseURL)
await setSitePixel(request, headers, null)
})
test.afterAll(async ({ request }) => {
const headers = await adminHeaders(request, baseURL).catch(() => undefined)
if (headers) {
await setSitePixel(request, headers, null)
}
})
test('renders nothing without a configured pixel ID', async ({ page }) => {
// Fresh load (unique query param misses every HTTP/router cache entry —
// the content-section trick); the app ignores unknown params. The
// fail-closed read comes from the global, which beforeAll just reset.
await page.goto(`/?e2e=${runSuffix}-none`)
await expect(page.locator('script[id^="meta-pixel-"]')).toHaveCount(0)
})
test('renders the base code when the site settings carry a valid ID', async ({
page,
request,
}) => {
const headers = await adminHeaders(request, baseURL)
// The REST update busts `global_site-settings` via afterChange BEFORE the
// goto, so the fresh render carries the pixel (deterministic, no cache race).
await setSitePixel(request, headers, PIXEL_ID)
await page.goto(`/?e2e=${runSuffix}-set`)
const pixelScript = page.locator(`script#meta-pixel-${PIXEL_ID}`)
await expect(pixelScript).toBeAttached()
// The base code defines `window.fbq` synchronously (queue-based no-op
// until fbevents.js processes it) — the seam `trackMetaLead` uses.
await expect
.poll(() => page.evaluate(() => typeof (window as { fbq?: unknown }).fbq === 'function'))
.toBe(true)
})
})