Files
Reem-Notas/docs/BATERIA-DE-TESTES.md
2026-08-28 16:14:38 -03:00

17 KiB
Raw Blame History

Bateria de testes — Reem Notas (ambiente de teste)

Roteiro de regressão para ser executado por um agente (inclusive modelos menores) com a skill agent-browser. Não é preciso conhecer o projeto: siga os casos na ordem e preencha o relatório do final.

Regras de segurança (leia antes de tudo)

  1. Somente leitura + interações seguras. É PROIBIDO:
    • clicar em qualquer botão que abra confirmação (Tem certeza?, Rebuscar o plano? etc.) — se a confirmação abrir por engano, cancele;
    • finalizar, arquivar, excluir ou registrar pagamento de consolidação;
    • criar, editar ou excluir usuários, perfis, contatos, grupos ou eventos;
    • qualquer envio de WhatsApp/notificação.
    • Formulários só podem ser preenchidos nos casos em que o roteiro mandar explicitamente (login e campos de busca).
  2. Ambiente: https://teste.reemtransportes.com.br (nunca o domínio de produção).
  3. Avisos do ambiente de teste (não são falhas):
    • Não há pagamentos registrados (pago_em vazio) — gráficos e tabelas de pagamento vazios são o esperado;
    • O deploy é manual: o site pode estar atrás do código do repositório. Se um caso falhar por algo que parece "código novo que não chegou lá", registre como DEPLOY? em vez de FALHOU.
  4. Screenshots de evidência vão para o diretório de scratchpad da sessão.

Credenciais

  • Admin (web): e-mail admin@reem.com, senha Reem@2026! — em https://teste.reemtransportes.com.br/auth/login, aba "E-mail".
  • Motorista: aba "PIN Motorista" da mesma tela (PIN de 4 dígitos; se nenhum PIN de teste for fornecido na tarefa, marque o caso 8 como PULADO).

Teste 0 — transversal (rodar em TODA página visitada)

Depois de abrir cada página do roteiro, sempre rode:

agent-browser errors                      # deve vir vazio
agent-browser network requests | grep -E " (4[0-9]{2}|5[0-9]{2})$"   # deve vir vazio
  • Qualquer erro de console JS ⇒ FALHOU (anote a mensagem).
  • Qualquer request com status ≥ 400 ⇒ FALHOU (anote a URL — um asset *_controller-*.js com 404 significa Stimulus quebrado na página inteira; foi exatamente assim que o bug do preview do romaneio passou despercebido).

⚠️ 404 de asset engana duas vezes. O Cloudflare guarda os arquivos por um ano, então uma tela pode parecer boa enquanto a origem já não serve nada — sempre confira com cache-buster:

curl -s -o /dev/null -w "%{http_code}\n" "https://teste.reemtransportes.com.br/assets/controllers/<arquivo>.js?cb=$RANDOM"

E se todos derem 404, o problema é o build inteiro, não os arquivos: a tarefa tailwindcss:build aborta o assets:precompile quando falta app/assets/tailwind/application.css. O Propshaft, sem manifesto, continua gerando URLs com o digest certo — por isso a página abre normal e o JS some em silêncio. Confira no servidor com docker compose logs app | grep '\[boot\] assets'.

  • Exceção: chamadas para domínios de terceiros (cloudflareinsights etc.) com falha não reprovam o caso; registre como observação.

Roteiro

Caso 1 — Login por e-mail

agent-browser open https://teste.reemtransportes.com.br/auth/login
agent-browser snapshot -i          # localizar refs de E-mail, Senha e Entrar
agent-browser fill @eX "admin@reem.com"
agent-browser fill @eY "Reem@2026!"
agent-browser press Enter
agent-browser wait --load networkidle
agent-browser get url

PASSOU se: a URL final é /dashboard (ou a home do perfil) e o Teste 0 passa. Obs.: use press Enter — o clique no botão às vezes não navega no primeiro clique.

Caso 2 — Dashboards

agent-browser open https://teste.reemtransportes.com.br/dashboard
agent-browser eval "document.querySelectorAll('canvas').length"      # gráficos Chart.js
agent-browser eval "document.documentElement.scrollWidth <= window.innerWidth"  # sem overflow horizontal
agent-browser screenshot dashboard.png
agent-browser open https://teste.reemtransportes.com.br/dashboard/operacoes
# repetir os três comandos acima (operacoes.png)

PASSOU se: as duas páginas carregam, há pelo menos 1 canvas em cada, sem overflow horizontal, Teste 0 limpo.

Versão mobile (obrigatória no dashboard):

agent-browser set device "iPhone 16"
agent-browser open https://teste.reemtransportes.com.br/dashboard
agent-browser eval "document.documentElement.scrollWidth <= window.innerWidth"
agent-browser screenshot dashboard-mobile.png
agent-browser set viewport 1280 800   # voltar ao desktop

PASSOU se: sem scroll horizontal no mobile (regra do projeto: nada de tabela que exija zoom).

Caso 3 — Consolidações (abas e filtros)

agent-browser open "https://teste.reemtransportes.com.br/consolidacoes?visao=lista"
agent-browser snapshot -i | head -40
agent-browser open "https://teste.reemtransportes.com.br/consolidacoes?visao=motoristas"
agent-browser get url

PASSOU se: as duas visões abrem sem erro; ao trocar de visão os filtros da URL se mantêm (as visões são abas da MESMA tela, não telas separadas); Teste 0 limpo.

Caso 4 — Romaneios (inclui o preview)

agent-browser open https://teste.reemtransportes.com.br/admin/romaneios
agent-browser snapshot -i | head -30          # lista de romaneios
# abrir o primeiro romaneio da lista (link do item):
agent-browser click @eX
agent-browser wait --load networkidle

Na tela do romaneio:

A prévia é um pop-up cujo estado mora na URL (?previa=1) — abre, fecha e troca de folha por navegação normal, sem JavaScript. Teste sempre navegando de verdade, nunca com .click() de dentro do eval: o clique programático já mascarou um bug (com o Turbo carregado, o mecanismo anterior por #hash não abria, mas o .click() fazia parecer que abria).

# 4a. Fechada, o pop-up NÃO existe no HTML (e nenhum PDF é gerado):
agent-browser open "https://teste.reemtransportes.com.br/admin/romaneios/13"
agent-browser eval "document.querySelector('[data-romaneio-target=overlay]') ? 'PRESENTE (erro)' : 'ausente (correto)'"

# 4b. Abrir pelo botão, com clique REAL:
agent-browser snapshot -i | grep -i "prévia"     # pegar o ref do link
agent-browser click @eN
agent-browser eval "(()=>{const o=document.querySelector('[data-romaneio-target=overlay]'); if(!o) return 'NAO ABRIU'; const c=[...o.querySelectorAll('span')].find(s=>s.textContent.includes(' de ')); return 'aberto | '+c.textContent.trim()+' | url='+location.search;})()"
# esperado: "aberto | 1 de 72 · GADE_001 | url=?veiculo=GADE_001&previa=1"

# 4c. Avançar de folha SEM fechar (é o carrossel):
agent-browser eval "(()=>{const o=document.querySelector('[data-romaneio-target=overlay]'); const a=[...o.querySelectorAll('a')].filter(x=>(x.getAttribute('href')||'').includes('previa')); return a.at(-1).getAttribute('href');})()"
# copie o href e navegue nele com `agent-browser open`; o pop-up tem que continuar
# aberto e o contador virar "2 de 72".

# 4d. Fechar pelo ✕ (volta para a URL sem previa) e o pop-up sumir do HTML.

# 4e. O PDF responde e é PDF de verdade (não a página de login):
agent-browser eval "(async()=>{const r=await fetch('/admin/romaneios/13/pdf?veiculo=GADE_001&cb='+Math.random()); const b=await r.blob(); return r.status+' '+b.type+' '+Math.round(b.size/1024)+'KB';})()"
# esperado: "200 application/pdf <N>KB"

PASSOU se: 4a ausente, 4b abre com o contador certo, 4c avança mantendo aberto, 4d fecha, 4e devolve application/pdf. NÃO clicar em "Reimportar plano" (tem confirmação).

⚠️ Se 4e devolver text/html, a sessão caiu no meio do teste — refaça o login e repita, não registre como falha do PDF (já deu falso positivo assim).

Caso 4f — Prévia em branco é o NAVEGADOR, não o sistema

O quadro do PDF pode aparecer branco mesmo com tudo funcionando, porque o navegador se recusa a desenhar PDF em iframe. As três causas conhecidas:

  1. "Baixar PDFs em vez de abri-los" ligado (Chrome/Brave/Edge: chrome://settings/content/pdfDocuments);
  2. bloqueador de conteúdo (Brave Shields, uBlock) barrando o quadro;
  3. bloqueio de pop-up/redirecionamento do navegador.

O sistema não consegue detectar isso (o iframe é opaco por segurança), por isso o pop-up traz um aviso fixo com a saída ("abra em outra aba"). Antes de abrir bug de "prévia não aparece", confirme que não é o navegador:

# Se ISTO devolve application/pdf, o servidor está certo e o problema é o navegador:
agent-browser eval "(async()=>{const r=await fetch('/admin/romaneios/13/pdf?veiculo=GADE_001&cb='+Math.random()); const b=await r.blob(); return r.status+' '+b.type;})()"

PASSOU se: o aviso está visível no rodapé do pop-up e o fetch acima devolve application/pdf. Se o fetch devolve PDF e o quadro está branco, o veredito é "configuração do navegador", não falha do sistema — registre assim.

Caso 4e — Vínculo manual da operação (só leitura)

O bloco "Operação do mês" tem que aparecer em todo romaneio, e o formulário precisa funcionar sem JavaScript<details> nativo + form comum):

agent-browser eval "(()=>{const d=[...document.querySelectorAll('details')].find(x=>x.querySelector('select[name=operacao_tabela]')); return d ? 'existe | aberto:'+d.open+' | opcoes:'+d.querySelectorAll('option').length : 'AUSENTE';})()"

⚠️ Procure pelo select[name=operacao_tabela], não pelo texto "Operação do mês": esse rótulo fica FORA do <details> e é renderizado em maiúsculas pelo CSS, então busca por texto dá falso negativo (já aconteceu num diagnóstico).

PASSOU se: o bloco existe; num romaneio sem operação ele vem aberto:true (a pendência fica à vista) e num com operação vem aberto:false; a lista tem mais de uma option. ⚠️ NÃO enviar o formulário — vincular altera dados do romaneio. Só conferir que o controle está lá e abre.

Caso 5 — Planilha SimpliRoute

agent-browser open https://teste.reemtransportes.com.br/admin/planilha_simpli_route
agent-browser snapshot -i | head -20

PASSOU se: a tela abre com a lista de operações disponíveis, Teste 0 limpo. (Não é preciso baixar o arquivo.)

Caso 6 — Telas de admin

Abrir cada URL e rodar o Teste 0:

/admin/usuarios
/admin/perfis
/admin/configuracoes
/admin/auditoria_logs
/admin/edicao_lancamento

PASSOU se: todas abrem com conteúdo (título + tabela/cards), sem erro. NÃO editar nada nessas telas.

Caso 7 — Notificações

Abrir cada URL e rodar o Teste 0:

/admin/contatos
/admin/grupos
/admin/eventos
/admin/envios

PASSOU se: todas abrem, sem erro. NÃO disparar envio nem mexer no WhatsApp/sessão.

Caso 8 — Login PIN do motorista (mobile)

Somente se um PIN de teste foi fornecido na tarefa; senão marcar PULADO.

agent-browser set device "iPhone 16"
agent-browser open https://teste.reemtransportes.com.br/auth/login
# clicar na aba "PIN Motorista", digitar o PIN, entrar

PASSOU se: cai no dashboard do motorista, valores legíveis sem zoom, Teste 0 limpo. Ao final: agent-browser set viewport 1280 800.

Caso 9 — Tempo de resposta (performance)

Mede o tempo real de cada tela e do PDF. Rode logado, com a rede parada (sem outra aba baixando coisa), e compare com a linha de base.

# Tempo das telas (TTFB | resposta completa | DOM pronto)
for u in /dashboard /dashboard/operacoes "/consolidacoes?visao=lista" /admin/romaneios /admin/romaneios/13; do
  agent-browser open "https://teste.reemtransportes.com.br$u" >/dev/null
  agent-browser eval "(()=>{const n=performance.getEntriesByType('navigation')[0]; return Math.round(n.responseStart-n.requestStart)+'|'+Math.round(n.responseEnd-n.requestStart)+'|'+Math.round(n.domContentLoadedEventEnd-n.startTime);})()"
done
# Tempo do PDF (o mais pesado do sistema). Com cache-buster, senão mede o cache.
agent-browser eval "(async()=>{const t0=performance.now(); const r=await fetch('/admin/romaneios/13/pdf?veiculo=GADE_002&cb='+Math.random()); const b=await r.blob(); return Math.round(performance.now()-t0)+'ms, '+Math.round(b.size/1024)+' KB';})()"

Linha de base medida em 28/08/2026 (romaneio de 2.047 paradas / 72 veículos, ambiente de teste, acesso pelo domínio com Cloudflare na frente):

Alvo TTFB Resposta DOM pronto
/dashboard 339 ms 340 ms 493 ms
/dashboard/operacoes 168 ms 251 ms 402 ms
/consolidacoes?visao=lista 349 ms 351 ms 430 ms
/admin/romaneios 49 ms 50 ms 127 ms
/admin/romaneios/13 71 ms 78 ms 155 ms
PDF de 1 veículo 228 ms (84 KB)
PDF de TODOS (72) 8.947 ms (1,7 MB)

Orçamento — FALHOU se passar de: 1 s de TTFB em qualquer tela; 1 s no PDF de um veículo (é ele que a prévia carrega, tem que abrir na hora); 30 s no PDF completo (acima disso o proxy corta a conexão e o operador recebe erro).

⚠️ Ponto de atenção conhecido: o PDF de todos os veículos leva ~9 s e segura um processo do servidor esse tempo todo. Ainda dentro do aceitável para uma ação manual e pontual, mas é o primeiro candidato a virar download em segundo plano se o volume crescer ou se dois operadores baixarem ao mesmo tempo. Não compare esse número com o do PDF de um veículo: são unidades diferentes (1 folha × 72).

Caso 10 — Mobile: quebras visuais (varredura)

Roda em todas as telas do roteiro com agent-browser set device "iPhone 16" (393×852), logado. São três medições objetivas; anote o número, não só passou/falhou.

10a — Rolagem horizontal

Nenhuma tela pode ter rolagem lateral no celular (diretriz 3: nada que exija zoom).

agent-browser set device "iPhone 16"
for u in /dashboard /dashboard/operacoes "/consolidacoes?visao=lista" "/consolidacoes?visao=motoristas" /admin/romaneios /admin/romaneios/13; do
  agent-browser open "https://teste.reemtransportes.com.br$u" >/dev/null
  agent-browser eval "document.documentElement.scrollWidth+'/'+document.documentElement.clientWidth"
done

PASSOU se: os dois números são iguais (ex.: 393/393) em todas. Para achar o culpado quando falhar:

agent-browser eval "(()=>{const vw=document.documentElement.clientWidth; return [...document.querySelectorAll('*')].filter(e=>{const b=e.getBoundingClientRect(); return b.right>vw+2 && b.width>40 && getComputedStyle(e).position!=='fixed';}).slice(0,5).map(e=>e.tagName+'.'+String(e.className).split(' ').slice(0,2).join('.')+' right='+Math.round(e.getBoundingClientRect().right)).join(' || ');})()"

⚠️ Causa recorrente: contêiner flex sem flex-wrap com botões que não cabem, ou <input class="flex-1"> sem min-w-0 (input não encolhe abaixo da largura intrínseca). Foram as duas causas de 28/08/2026.

10b — Menu inteiro alcançável

Todo item do menu tem que ser alcançável rolando — inclusive o Sair, o último.

agent-browser open "https://teste.reemtransportes.com.br/dashboard"
agent-browser snapshot -i | grep -i "menu"      # pegar o ref do botão "Abrir menu"
agent-browser click @eN
agent-browser eval "(()=>{const nav=document.querySelector('#sidebar nav'); if(!nav) return 'NAV AUSENTE'; const ult=[...document.querySelectorAll('#sidebar a')].at(-1); return 'nav rola='+(nav.scrollHeight>nav.clientHeight)+' overflowY='+getComputedStyle(nav).overflowY+' | ultimo item: '+ult.textContent.trim()+' | fora da tela por '+Math.max(0, Math.round(ult.getBoundingClientRect().bottom-window.innerHeight))+'px';})()"

PASSOU se: overflowY=auto e "fora da tela por 0px" (o item pode estar abaixo da dobra, desde que o <nav> role até ele). FALHOU se: overflowY=visible ou o último item aparece fora por N px — foi o bug de 28/08/2026, em que 7 itens (incluindo Sair) eram inalcançáveis no celular.

O que segura isso é o flex flex-col no <aside id="sidebar">: sem ele o flex-1 overflow-y-auto do <nav> não tem efeito nenhum.

10c — Alvos de toque

agent-browser eval "(()=>{const p=[...document.querySelectorAll('a,button,input,select,summary')].filter(e=>{const b=e.getBoundingClientRect(); return b.height>0 && b.height<44;}); return p.length+' alvos <44px';})()"

Linha de base após as correções de 28/08/2026 (iPhone 16): dashboard tinha 63 antes do ajuste da paginação; as demais telas ficam entre 3 e 5. Um número que cresce entre execuções é regressão — vale investigar o que foi adicionado, não apenas registrar.

Relatório final (obrigatório)

Terminar a execução com uma tabela e a lista de falhas:

Caso Resultado Evidência
0 (por página) PASSOU/FALHOU página + erro
1 Login PASSOU/FALHOU/DEPLOY?/PULADO screenshot
2 Dashboards
3 Consolidações
4 Romaneios/preview
5 Planilha
6 Admin
7 Notificações
8 PIN motorista
9 Performance tabela de tempos
10 Mobile (10a/b/c) larguras, menu, alvos

Depois da tabela, listar somente as falhas, cada uma com: URL, o que era esperado, o que aconteceu (mensagem de erro/console) e o caminho do screenshot. Se tudo passou, dizer isso em uma linha. Encerrar com agent-browser close.