mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-14 08:53:11 +00:00
- setup.e2e.spec.ts: prewarm GET 13→26 rotas (rota /editar, alvos de redirect, wizards, PWA artifacts, rotas do chat Sollinha) + POST ganhou next-steps, home-search, ai-chat, ai-transcribe; prewarmGet com retry-único (abort do compile aborta a conexão do próprio prewarm); budget explícito 420s no lugar do test.slow(). - campaignE2EFixtures.ts: campaign.login com retry-único do submit (re-fill+re-click com grace-wait do destino exato) — submit abortado pelo full-page reload do compile frio nunca navega. - campaignMunicipalities.e2e.spec.ts: refactor mínimo por evidência — B24 (estágio largo B158 + toggle do trigger pós-reload), :713 (retry do server action de criação), :1063 (seed parity via db:seed:minimal — achado do OPS28 — + retry do suggest). - P4-L fechado com evidência: campaignLeaderships ×3 dev + ×1 E2E_PROD=1 (TECH-DEBT row 59 + TESTING.md caveat). - Aceite: campaignMunicipalities 17/17 ×3 consecutivos em dev a 2 workers (load 5-18). Sem migration/access/Consent/UI.
88 lines
3.8 KiB
TypeScript
88 lines
3.8 KiB
TypeScript
import { expect, test } from '@playwright/test'
|
|
|
|
const baseURL = process.env.PLAYWRIGHT_BASE_URL ?? 'http://localhost:3000'
|
|
|
|
test('prewarms shared Next route bundles sequentially', async ({ request }) => {
|
|
// 26 route modules compiled cold, each up to ~60 s under parallel-worktree
|
|
// load (measured 2026-08-10, load ~50: /campanha/contatos took 57 s), plus a
|
|
// one-shot retry per GET for the dev-server abort class below. On CI the
|
|
// production build answers warm in seconds, so the budget never bites there.
|
|
test.setTimeout(420_000)
|
|
// A cold compile can make Next dev abort an in-flight request (socket hang
|
|
// up, measured on the original list under load) — the route compiles anyway,
|
|
// so a single retry lands warm. The assertion runs on the retry only;
|
|
// a second failure is a real regression (broken/404 route).
|
|
const prewarmGet = async (path: string) => {
|
|
const first = await request.get(`${baseURL}${path}`).catch(() => undefined)
|
|
if (first?.ok()) return first
|
|
const retry = await request.get(`${baseURL}${path}`).catch(() => undefined)
|
|
expect(retry?.ok(), `Failed to prewarm ${path}`).toBe(true)
|
|
return retry
|
|
}
|
|
for (const path of [
|
|
'/campanha/login',
|
|
'/campanha',
|
|
'/campanha/quadro',
|
|
'/campanha/municipios',
|
|
'/campanha/territorios',
|
|
'/campanha/municipios/e2e-prewarm',
|
|
// The only edit route specs navigate (grep-verified 2026-08-10): compiling
|
|
// it cold mid-test aborted the :78 goto with ERR_ABORTED (dev full-reload).
|
|
'/campanha/municipios/e2e-prewarm/editar',
|
|
'/campanha/perfil',
|
|
'/campanha/demandas',
|
|
'/campanha/demandas/nova',
|
|
// The demand-create form redirects to /campanha/demandas/<slug>; the detail
|
|
// module is a goto-less redirect target, so it needs its own prewarm entry
|
|
// (same class as /editar: cold compile mid-test aborts the redirect).
|
|
'/campanha/demandas/e2e-prewarm',
|
|
'/campanha/liderancas',
|
|
'/campanha/contatos',
|
|
'/campanha/conceitos',
|
|
'/campanha/acoes/atualizar-votos',
|
|
'/campanha/acoes/atualizar-lideranca',
|
|
'/campanha/acoes/mudar-tendencia',
|
|
'/campanha/acoes/registrar-atualizacao',
|
|
'/campanha/agenda',
|
|
'/campanha/atividades/nova',
|
|
'/campanha/atualizacoes',
|
|
'/campanha/offline',
|
|
// PWA artifacts every authenticated page fetches on load — a cold compile
|
|
// here mid-suite full-page-reloads connected clients (ERR_ABORTED class).
|
|
'/campanha/manifest.webmanifest',
|
|
'/campanha/sw.js',
|
|
'/campanha/convite/e2e-prewarm',
|
|
'/',
|
|
]) {
|
|
await prewarmGet(path)
|
|
}
|
|
|
|
// POST-only API route handlers (auto-save popovers): Next dev compiles a
|
|
// route on its first hit, and that compile can trigger a full-page reload
|
|
// for any client currently connected — which aborts an in-flight fetch mid
|
|
// test. An unauthenticated POST never succeeds, but it still forces the
|
|
// compile before any spec's client makes the real request.
|
|
for (const path of [
|
|
'/campanha/municipios/advisors',
|
|
'/campanha/municipios/engagement-level',
|
|
'/campanha/municipios/expected-votes',
|
|
'/campanha/municipios/leaderships',
|
|
'/campanha/municipios/pledge-declared-votes',
|
|
'/campanha/municipios/pledge-estimated-votes',
|
|
'/campanha/municipios/political-trend',
|
|
'/campanha/municipios/next-steps',
|
|
'/campanha/liderancas/support-status',
|
|
'/campanha/home-search',
|
|
// The Sollinha chat mounts on every authenticated page: its transport and
|
|
// the PWA registration hit these on first load/session-restore — cold
|
|
// compiles mid-suite are the ERR_ABORTED class (measured on :78 /editar).
|
|
'/campanha/api/ai-chat',
|
|
'/campanha/api/ai-transcribe',
|
|
'/campanha/webauthn/login-options',
|
|
'/campanha/webauthn/login',
|
|
'/campanha/webauthn/register-options',
|
|
'/campanha/webauthn/register',
|
|
]) {
|
|
await request.post(`${baseURL}${path}`, { data: {} }).catch(() => undefined)
|
|
}
|
|
})
|