Playbook de Erros E2E — OLP
SSOT para resolução de erros em testes. Toda falha encontrada DEVE ser catalogada aqui com causa raiz, classificação e padrão derivado.
Última atualização: 2026-04-04
1. Protocolo de Diagnóstico
Workflow obrigatório antes de classificar qualquer falha de teste:
text
┌─────────────────────────────────────────────────────┐
│ 1. Rodar o teste contra PRODUÇÃO no sandbox │
│ BASE_URL=https://olp.digital npx playwright ... │
│ │
│ 2. Passou em prod? │
│ ├─ SIM → Teste está correto. │
│ │ Problema é no staging (dados/infra). │
│ │ → Corrigir staging, NÃO o teste. │
│ │ │
│ └─ NÃO → Bug no teste (seletor, import, lógica)│
│ → Corrigir o teste, catalogar aqui. │
│ │
│ 3. NUNCA relaxar assertions para aceitar │
│ resultados vazios ou incorretos. │
└─────────────────────────────────────────────────────┘Checklist antes de dar veredito
- [ ] Teste rodou contra produção?
- [ ] DOM real foi inspecionado (browser tools ou screenshot)?
- [ ] Se falha é timing: qual é o tempo real da operação em staging?
- [ ] Se falha é dados: staging tem os mesmos dados que produção?
- [ ] Se falha é seletor: seletor bate com o DOM real em produção?
2. Catálogo de Erros e Resoluções
ERR-001 — ReferenceError: BASE_URL is not defined
| Campo | Valor |
|---|---|
| Arquivo | e2e/loading-gate.spec.ts |
| Erro | ReferenceError: BASE_URL is not defined (3 testes falharam) |
| Causa raiz | Import faltando — o spec importava apenas TIMEOUTS mas usava BASE_URL |
| Classificação | Bug de teste (import) |
| Resolução | Adicionar BASE_URL ao import: import { BASE_URL, TIMEOUTS } from './fixtures/constants' |
| Padrão derivado | Todo spec que usa navegação DEVE importar BASE_URL de fixtures/constants |
ERR-002 — waitForURL timeout após login em SPA
| Campo | Valor |
|---|---|
| Arquivo | e2e/login-senha.spec.ts |
| Erro | page.waitForURL(regex) expira mesmo com login bem-sucedido |
| Causa raiz | SPA não muda a URL após login — o React Router renderiza o Dashboard na mesma rota |
| Classificação | Bug de teste (premissa errada sobre navegação SPA) |
| Resolução | Substituir waitForURL por page.waitForSelector('nav button') para verificar que o Dashboard hidratou |
| Padrão derivado | Em SPAs, nunca usar waitForURL para confirmar login. Verificar a presença de elemento do Dashboard (sidebar/nav) |
ERR-003 — Seletor input[name="senha"] não encontrado
| Campo | Valor |
|---|---|
| Arquivo | e2e/login-senha.spec.ts |
| Erro | locator.fill: Error: strict mode violation ou element not found |
| Causa raiz | O input de senha no DOM real usa id="senha" sem atributo name |
| Classificação | Bug de teste (seletor errado) |
| Resolução | Corrigir seletor para input#senha |
| Padrão derivado | Preferir seletores #id sobre [name]. Sempre inspecionar o DOM real em produção (browser tools ou screenshot) antes de criar seletores |
ERR-004 — Toggle de senha não funciona com click()
| Campo | Valor |
|---|---|
| Arquivo | e2e/login-senha.spec.ts |
| Erro | Após click() no botão de toggle, o input continua type="password" |
| Causa raiz | O componente usa padrão hold-to-reveal (mousedown mostra, mouseup esconde) em vez de toggle simples |
| Classificação | Bug de teste (premissa errada sobre interação) |
| Resolução | Usar dispatchEvent('mousedown') para revelar e dispatchEvent('mouseup') para ocultar |
| Padrão derivado | Verificar o padrão de interação real do componente (click vs hold vs hover) antes de escrever o teste. Testar manualmente no browser primeiro |
ERR-005 — Login timeout 15s insuficiente
| Campo | Valor |
|---|---|
| Arquivo | e2e/fixtures/constants.ts |
| Erro | Login expira antes de completar no staging |
| Causa raiz | Argon2id (hash de senha) é computacionalmente caro por design. No staging com menos recursos, pode levar >15s |
| Classificação | Staging infra (timing) |
| Resolução | Aumentar TIMEOUTS.login de 15s para 30s |
| Padrão derivado | TIMEOUTS.login DEVE ser ≥30s. Para cold start de Edge Functions, usar ≥20s. Timeouts devem considerar o pior caso do staging, não o caso médio de produção |
ERR-006 — Templates não carregam ao clicar olimpíada (hook)
| Campo | Valor |
|---|---|
| Arquivo | Componente de templates do especialista/coordenador |
| Erro | Lista de templates sempre vazia ao selecionar olimpíada |
| Causa raiz | Hook deprecated retornava [] as Template[] hardcoded. O listarTemplates() imperativo populava o cache do React Query, mas o componente lia a propriedade estática vazia |
| Classificação | Bug de código (hook deprecated, não reativo) |
| Resolução | Usar hook reativo (useComunicacaoTemplates(hubId)) que lê diretamente do cache React Query |
| Padrão derivado | Se dados não aparecem na UI, verificar se o hook lê do cache React Query de forma reativa (subscription). Hooks imperativos que populam cache sem retornar dados são anti-padrão |
ERR-007 — Templates vazio no staging (dados)
| Campo | Valor |
|---|---|
| Arquivo | Seed/dados do staging |
| Erro | Teste de comunicação falha porque não há templates associados à escola de teste |
| Causa raiz | O seed do staging não incluía dados de template_hubs e templates_mensagem para a escola "Monteiro Lobato" |
| Classificação | Staging dados (seed incompleto) |
| Resolução | Adicionar templates ao seed do staging |
| Padrão derivado | Se o teste espera dados (templates, olimpíadas, alunos), o seed do staging DEVE ter esses dados. Nunca aceitar empty state como correto se produção tem dados |
ERR-008 — Notificação ntfy nunca enviada no CI
| Campo | Valor |
|---|---|
| Arquivo | .github/workflows/ci.yml |
| Erro | Step "Notificar falha E2E via ntfy" termina em 0s sem enviar nada, sem erro visível |
| Causa raiz | Workflow usava secrets.NTFY_TOPIC mas o secret no GitHub se chama NTFY_TOPIC_URL. Variável vazia → if [ -n ] falha silenciosamente |
| Classificação | Bug de infra (nome de secret divergente entre Supabase e GitHub Actions) |
| Resolução | Trocar para secrets.NTFY_TOPIC_URL, adicionar warning explícito se ausente, e aceitar tanto hash quanto URL completa |
| Padrão derivado | Nomes de secrets entre ambientes (Supabase Vault vs GitHub Actions) podem divergir. Sempre validar com log/warning se o secret está vazio antes de usá-lo. Nunca assumir que ausência de erro = execução bem-sucedida |
ERR-009 — Seletor .cursor-pointer genérico causa clique em elemento errado
| Campo | Valor |
|---|---|
| Arquivo | e2e/comunicacao-coordenador.spec.ts |
| Erro | Teste "clicar em olimpíada carrega templates" falha — clica em elemento errado ou não encontra card |
| Causa raiz | Seletor [data-testid="olimpiada-card"], .cursor-pointer — o data-testid nunca foi adicionado ao componente, e .cursor-pointer é genérico demais (casa com checkboxes, labels, skeletons) |
| Classificação | Bug de teste (seletor) + Bug de código (data-testid ausente) |
| Resolução | Adicionar data-testid="olimpiada-card" no componente comunicacao-templates.tsx e usar apenas [data-testid="olimpiada-card"] no teste |
| Padrão derivado | Componentes interativos clicados por E2E DEVEM ter data-testid. Nunca usar classes CSS utilitárias (.cursor-pointer, .flex, etc.) como seletor principal |
3. Padrões Derivados — Checklist
Regras consolidadas extraídas do catálogo. Obrigatórias para testes novos e revisão de existentes.
3.1 Seletores
- [ ] Preferir
#idsobre[name]ou[data-testid] - [ ] Inspecionar DOM real em produção antes de definir seletores
- [ ] Nunca assumir que atributo
nameexiste — verificar - [ ] Para formulários: usar o
iddo input que está nohtmlFordo label
3.2 Navegação SPA
- [ ] Não usar
waitForURLpara confirmar login ou navegação interna - [ ] Verificar hidratação via presença de elemento do Dashboard (
nav button, sidebar) - [ ] Usar
waitUntil: 'domcontentloaded'em vez de'load'(evita espera por polling/realtime)
3.3 Timing
- [ ]
TIMEOUTS.login≥ 30s (Argon2id) - [ ] Cold start Edge Functions ≥ 20s
- [ ] Considerar pior caso do staging, não média de produção
- [ ] Se timeout falha, medir tempo real antes de aumentar arbitrariamente
3.4 Interações
- [ ] Verificar padrão de interação real (click vs hold vs hover vs drag)
- [ ] Testar manualmente no browser antes de escrever automação
- [ ] Para hold-to-reveal: usar
mousedown/mouseup - [ ] Para dropdowns shadcn: usar
click+waitForSelectorno popover
3.5 Dados e Staging
- [ ] Se teste espera dados, seed do staging DEVE ter esses dados
- [ ] Nunca aceitar empty state se produção tem dados — corrigir seed
- [ ] Validar que escola/usuário de teste tem as relações necessárias (olimpíadas, templates, turmas)
3.6 Hooks e React Query
- [ ] Se dados não renderizam, verificar se hook é reativo (subscription do React Query)
- [ ] Hooks imperativos que populam cache sem retornar dados são anti-padrão
- [ ] Após fix em hook, rodar teste E2E para confirmar que dados aparecem
4. Como Adicionar Novo Erro
Ao encontrar uma nova falha de teste:
- Seguir o Protocolo de Diagnóstico (Seção 1)
- Criar entrada no Catálogo (Seção 2) com o próximo ID sequencial (
ERR-008, etc.) - Preencher todos os campos: Arquivo, Erro, Causa raiz, Classificação, Resolução, Padrão derivado
- Adicionar padrão à checklist da Seção 3 se for uma regra nova
- Atualizar a data no cabeçalho do documento
Template para nova entrada
markdown
### ERR-XXX — [Descrição curta]
| Campo | Valor |
|-------|-------|
| **Arquivo** | `e2e/xxx.spec.ts` |
| **Erro** | [Mensagem de erro exata] |
| **Causa raiz** | [O que realmente causou] |
| **Classificação** | Bug de teste / Staging infra / Staging dados / Bug de código |
| **Resolução** | [O que foi feito para corrigir] |
| **Padrão derivado** | [Regra para testes futuros] |ERR-010 — password-history-helper.test.ts regex desatualizada
| Campo | Valor |
|---|---|
| Arquivo | supabase/functions/_shared/password-history-helper.test.ts |
| Erro | assertExists(match) falha — match é null |
| Causa raiz | Constante renomeada de HISTORY_LIMIT para HISTORY_SAVE_LIMIT + HISTORY_CHECK_LIMIT durante refatoração. Teste usa regex readTextFile e ficou desatualizado. |
| Classificação | Bug de teste (regex) |
| Resolução | Atualizar regex para HISTORY_SAVE_LIMIT e valor esperado 5 |
| Padrão derivado | Testes que fazem parse de source code via regex devem ser atualizados junto com renomeações de exports |
Referências
- TESTING_MASTER.md — Estratégia de testes (pirâmide, camadas)
- PROBLEM_SOLVING.md — Metodologia de resolução de problemas
- STAGING_REFERENCE.md — Dados e config do staging