Pular para o conteúdo principal

Testes E2E com Cypress

Introdução ao documento

Este documento descreve a estrutura, configuração e execução dos testes end-to-end (E2E) utilizando Cypress no projeto Dhedalos Dashboard.

Versionamento

  • Versão do documento: 1.0.0
  • Última atualização: 2026-03-09
  • Responsável: Marivaldo Vinicius

Referencial teórico

Objetivo dos testes

Os testes Cypress validam fluxos end-to-end críticos do dashboard administrativo, incluindo:

  • Autenticação e controle de acesso
  • Funcionalidades de CRUD (usuários, manutenção)
  • Validação de cache e atualização de dados
  • Dashboard e visualizações de dados
  • Integrações com APIs externas (AoVivo, WordPress)
  • Exportação de dados
  • Gestão de permissões e roles

Os testes garantem que a interface administrativa funcione corretamente do ponto de vista do usuário final, complementando os testes unitários e de feature do Pest PHP.

Estrutura de pastas

cypress/
├── e2e/ # Especificações de testes E2E
│ ├── 01-cache-validation.cy.js
│ ├── aovivo.cy.js
│ ├── crud-user.cy.js
│ ├── dashboard.cy.js
│ ├── exportacao-cadastros.cy.js
│ ├── manutencao.cy.js
│ ├── perfil-inscritos.cy.js
│ ├── permissoes.cy.js
│ ├── produtos.cy.js
│ └── forms/ # Page Objects para formulários
│ ├── LoginForm.js
│ ├── MaintenanceForm.js
│ └── UserForm.js
└── support/ # Arquivos de suporte
├── commands.js # Comandos customizados
├── e2e.js # Configuração global e handlers
└── helpers.js # Funções auxiliares

Evidências:

  • Estrutura de pastas: cypress/e2e/, cypress/support/
  • Arquivos de teste: 12 arquivos .cy.js em cypress/e2e/
  • Page Objects: 3 arquivos em cypress/e2e/forms/

Configuração

Arquivo de configuração

O arquivo cypress.config.js define as configurações principais:

{
chromeWebSecurity: false,
baseUrl: process.env.CYPRESS_BASE_URL || "http://localhost:8000",
specPattern: "cypress/e2e/**/*.cy.{js,jsx,ts,tsx}",
supportFile: "cypress/support/e2e.js",
testIsolation: false,
viewportHeight: 960,
viewportWidth: 1536,
video: true,
videoCompression: true,
retries: {
runMode: 1,
openMode: 1,
}
}

Configurações principais:

  • chromeWebSecurity: false: Desabilita segurança do Chrome para permitir testes com iframes e cross-origin
  • baseUrl: URL base da aplicação (configurável via CYPRESS_BASE_URL)
  • testIsolation: false: Testes compartilham estado (sessão, cookies) entre specs
  • viewport: Resolução padrão 1536x960
  • video: true: Grava vídeos dos testes para debugging
  • retries: 1 tentativa adicional em caso de falha (runMode e openMode)

Evidências:

  • Configuração: cypress.config.js:3-45

Variáveis de ambiente

Variáveis utilizadas pelos testes Cypress:

VariávelObrigatóriaDescriçãoEvidência
CYPRESS_BASE_URLNãoURL base da aplicação (default: http://localhost:8000)cypress.config.js:30
CYPRESS_PROJECT_IDNãoID do projeto no Cypress Cloud (para recording)cypress.config.js:7
CYPRESS_RECORD_KEYNãoChave para gravar testes no Cypress Cloud.github/workflows/cypress.yml:149
CYPRESS_USER_EMAILSim (CI)Email do usuário de teste.github/workflows/cypress.yml:108
CYPRESS_USER_PASSWORDSim (CI)Senha do usuário de teste.github/workflows/cypress.yml:108

Variáveis de ambiente da aplicação (necessárias para testes):

  • REDSHIFT_DB_HOST, REDSHIFT_DB_DATABASE, REDSHIFT_DB_USERNAME, REDSHIFT_DB_PASSWORD
  • WORDPRESS_API_URL, WORDPRESS_API_TOKEN
  • AO_VIVO_API, AO_VIVO_TOKEN
  • GEMINI_API_KEY

Evidências:

  • Variáveis Cypress: cypress.config.js:7,30
  • Variáveis de aplicação: .github/workflows/cypress.yml:50-62

Comandos de execução

Local (desenvolvimento)

Pré-requisitos:

  • Aplicação Laravel rodando em http://localhost:8000
  • Dependências Node instaladas (npm install)
  • Usuário de teste criado no banco de dados

Comandos disponíveis:

# Abrir Cypress Test Runner (interface gráfica)
npm run cypress:open

# Executar testes em modo headless
npm run cypress:run

Evidências:

  • Scripts: package.json:4-9 (na branch origin/feat/cypress)

Execução passo a passo:

  1. Iniciar aplicação:

    docker compose up
  2. Criar usuário de teste (se necessário):

    docker compose exec laravel php artisan tinker
    # Criar usuário com email e senha conhecidos
  3. Executar testes:

    npm run cypress:open  # Interface gráfica
    # ou
    npm run cypress:run # Headless

CI/CD (GitHub Actions)

Os testes Cypress são executados automaticamente no pipeline CI/CD:

Workflow: .github/workflows/cypress.yml

Triggers:

  • Pull requests
  • Push para branches main e develop

Processo:

  1. Setup PHP 8.3 e Node.js 22
  2. Instalação de dependências (Composer e npm)
  3. Configuração de ambiente (.env com variáveis de secrets)
  4. Build de assets frontend (npm run build)
  5. Execução de migrações e seeders
  6. Criação de usuário de teste via Tinker
  7. Inicialização do servidor Laravel (php artisan serve)
  8. Execução dos testes Cypress com recording no Cypress Cloud
  9. Upload de artifacts (vídeos e screenshots)

Evidências:

  • Workflow: .github/workflows/cypress.yml:1-155
  • Recording: .github/workflows/cypress.yml:140-150

Fixtures e mocks

Status: Não há fixtures ou mocks configurados explicitamente.

Os testes utilizam:

  • Dados reais da aplicação: Testes interagem com banco de dados real (SQLite no CI, MySQL local)
  • APIs externas reais: Testes dependem de integrações com Redshift, WordPress API, AoVivo API e Gemini API
  • Usuários de teste: Criados via seeders ou Tinker antes da execução

Pendências:

  • Considerar uso de fixtures para dados de teste isolados
  • Avaliar mocks para APIs externas em testes de integração

Custom commands

getIframeBody(selector)

Comando customizado para acessar conteúdo de iframes:

Cypress.Commands.add("getIframeBody", (selector) => {
return cy
.get(selector, { timeout: 15000 })
.should(($el) => {
expect($el.contents().find("body")).to.not.be.empty;
})
.then(($el) => {
return cy.wrap($el.contents().find("body"));
});
});

Uso: Acessar elementos dentro de iframes (ex.: gráficos embutidos, widgets externos).

Evidências:

  • Definição: cypress/support/commands.js:20-30

Helpers

Funções auxiliares em cypress/support/helpers.js:

deleteItems(searchTerm, escapedTerm)

Remove todas as linhas de uma tabela CRUD que correspondem ao termo de busca, clicando em "Excluir" iterativamente.

Parâmetros:

  • searchTerm: Texto para buscar na tabela
  • escapedTerm: Versão regex-safe do termo para matching

Uso: Limpar dados de teste após execução de testes de CRUD.

Evidências:

  • Definição: cypress/support/helpers.js:8-35

anoAtualLabel() e anoAnteriorLabel()

Retornam labels de ano atual e anterior para filtros de data.

Uso: Testes que precisam filtrar dados por ano (ex.: dashboard, relatórios).

Evidências:

  • Definições: cypress/support/helpers.js:37-47

Page Objects

Page Objects organizados em cypress/e2e/forms/:

LoginForm.js

Classe para encapsular ações de login:

  • Método makeLogin(user): Realiza login com credenciais fornecidas

Evidências:

  • Uso: cypress/e2e/01-cache-validation.cy.js:3,8
  • Uso: cypress/e2e/dashboard.cy.js:3,8

MaintenanceForm.js e UserForm.js

Page Objects para formulários de manutenção e usuários (estrutura similar).

Evidências:

  • Arquivos: cypress/e2e/forms/MaintenanceForm.js, cypress/e2e/forms/UserForm.js

Convenções observadas

  1. Nomenclatura de arquivos:

    • Arquivos de teste: *.cy.js
    • Page Objects: *Form.js (PascalCase)
    • Helpers: helpers.js (camelCase)
  2. Estrutura de testes:

    • Uso de describe() para agrupar testes relacionados
    • Testes descritivos em português (BDD-style)
    • Page Objects para encapsular interações com formulários
  3. Isolamento:

    • testIsolation: false permite compartilhamento de sessão entre specs
    • Testes dependem de estado compartilhado (login, cookies)
  4. Aguardar elementos:

    • Uso de cy.wait() com delays fixos (não ideal, mas presente)
    • Timeouts customizados quando necessário (ex.: getIframeBody com 15s)
  5. Tratamento de erros:

    • Handler global em e2e.js ignora erros de hidratação React e classList null
    • Evidências: cypress/support/e2e.js:18-28

Limitações e pendências

Limitações conhecidas

  1. Dependência de APIs externas:

    • Testes falham se Redshift, WordPress API, AoVivo API ou Gemini API estiverem indisponíveis
    • Não há fallback ou mocks para APIs externas
  2. Dados de teste:

    • Testes dependem de dados reais no banco de dados
    • Não há isolamento completo de dados entre execuções
    • Usuários de teste precisam ser criados manualmente ou via seeders
  3. Performance:

    • Uso de cy.wait() com delays fixos pode tornar testes lentos
    • testIsolation: false pode causar efeitos colaterais entre specs
  4. Ambiente local:

    • Requer aplicação rodando localmente
    • Requer configuração manual de variáveis de ambiente

Pendências

  1. Fixtures e mocks:

    • Implementar fixtures para dados de teste isolados
    • Avaliar mocks para APIs externas (opcional, para testes mais rápidos)
  2. Melhorias de performance:

    • Substituir cy.wait() fixos por esperas baseadas em condições (cy.get().should())
    • Avaliar uso de testIsolation: true para maior isolamento
  3. Cobertura:

    • Expandir cobertura de testes para mais funcionalidades
    • Adicionar testes de edge cases e cenários de erro
  4. Documentação:

    • Documentar padrões de escrita de novos testes
    • Criar guia de troubleshooting comum
  5. CI/CD:

    • Avaliar execução paralela de testes (atualmente sequencial)
    • Considerar retry automático apenas para testes flaky específicos

Troubleshooting

Problemas comuns

1. Testes falham com "Element not found":

  • Verificar se aplicação está rodando em http://localhost:8000
  • Verificar se viewport está correto (1536x960)
  • Aumentar timeout se elemento demora para aparecer

2. Erros de autenticação:

  • Verificar se usuário de teste existe no banco de dados
  • Verificar credenciais em CYPRESS_USER_EMAIL e CYPRESS_USER_PASSWORD
  • Limpar cookies antes de executar testes: cy.clearAllCookies()

3. Testes falham no CI mas passam localmente:

  • Verificar logs do servidor Laravel no CI
  • Verificar se todas as variáveis de ambiente estão configuradas
  • Verificar se migrações e seeders foram executados corretamente

4. Vídeos não são gerados:

  • Verificar se video: true está configurado em cypress.config.js
  • Verificar espaço em disco (vídeos podem ser grandes)
  • Verificar permissões de escrita na pasta cypress/videos

5. Erros de iframe:

  • Verificar se chromeWebSecurity: false está configurado
  • Usar comando customizado getIframeBody() para acessar conteúdo de iframes

Integração com outros testes

Os testes Cypress complementam:

  • Testes Pest PHP: Testes unitários e de feature do backend
  • Storybook: Testes de componentes React isolados

Cobertura:

  • Pest PHP: Lógica de negócio, controllers, services, jobs
  • Cypress: Fluxos end-to-end, interface do usuário, integrações completas
  • Storybook: Componentes React isolados

Evidências:

  • Testes Pest: tests/Unit/, tests/Feature/
  • Storybook: stories/