🕵️ Módulo 13: QA Frontend - Testes End-to-End Automatizados com Cypress

✅ Pré-Requisitos deste Módulo

Confirme antes de começar:

# Terminal 1 — backend
./mvnw spring-boot:run   # deve iniciar em localhost:8080

# Terminal 2 — frontend
cd web && npm start       # deve iniciar em localhost:4200

Você deve ter concluído o Módulo 06 (projeto Angular funcionando). O ng add @cypress/schematic requer acesso à internet para baixar pacotes npm.

Nota: o primeiro teste (redirect do guard) não precisa do backend e pode ser executado apenas com o Angular rodando.


No Módulo 09, nós criamos uma blindagem robusta no nosso backend Java utilizando o JUnit 5 para garantir que a regra de negócios (como cálculos de estoque e faturamento) funcione perfeitamente. No entanto, em um ecossistema de software profissional, testar apenas a API não é suficiente.

Como garantimos que o botão “Comprar” no Angular ou no Ionic não quebrou após uma atualização de CSS? Como garantimos que o formulário de login está de fato redirecionando o usuário? É aqui que entram os Testes End-to-End (E2E).


🤖 O que é o Cypress E2E?

Diferente de testes unitários que testam funções isoladas no código, os Testes E2E simulam um ser humano real utilizando o seu software do início ao fim (End-to-End).

O Cypress é o framework líder de mercado para esta tarefa. Ele abre um navegador (Chrome/Edge/Firefox) controlado por robôs, digita em campos de texto, clica em botões e verifica se a tela renderizou as informações corretas.

flowchart TD
    classDef cypress fill:#17202C,stroke:#04C38E,stroke-width:2px,color:#fff;
    classDef browser fill:#ffffff,stroke:#4285F4,stroke-width:2px,color:#000;
    classDef server fill:#ea2845,stroke:#3b0713,stroke-width:2px,color:#fff;

    A[Cypress Runner]:::cypress -->|Controla Navegador Nativo| B{Navegador Chrome}:::browser
    B -->|cy.visit('/login')| C[Abre Página Angular]:::browser
    B -->|cy.get('input').type('...')| D[Preenche Formulário Real]:::browser
    B -->|cy.get('button').click()| E[Clica no Botão e Dispara HTTP]:::browser
    E --> F[Spring Boot API Local]:::server
    F -- Retorna JSON/Token --> B
    B -->|cy.contains('Bem-vindo')| G[Verifica se o login visual funcionou!]:::cypress

🤔 Por que Cypress E2E e não mais testes unitários?

Testes unitários (JUnit, Jasmine/Jest) verificam funções isoladas: “dado esse input, retorna esse output?” Eles são rápidos e baratos, mas não provam que as peças funcionam juntas.

Imagine que o AuthGuard está correto, o LoginComponent está correto, mas o RouterModule foi configurado errado — todos os unitários passam, mas o usuário não consegue fazer login. O Cypress capturaria esse bug imediatamente porque abre o navegador real e executa o fluxo completo.

A regra prática:

Use os dois em camadas — não um em substituição ao outro.


🛠️ 1. Configurando o Cypress no Projeto Angular

Navegue até a pasta do seu frontend web e adicione o Cypress utilizando o esquemático oficial do Angular. Ele configurará automaticamente os pacotes e pastas necessários.

cd web
ng add @cypress/schematic

Ao confirmar as perguntas no terminal, o Cypress criará uma pasta cypress/e2e/ na raiz do seu frontend.


📝 2. Escrevendo o Roteiro de Testes (Test Spec)

Vamos criar um robô que testa o nosso fluxo mais crítico: o Login e a Visualização do Catálogo. Dentro da pasta cypress/e2e/, crie o arquivo jornada-compras.cy.ts:

// cypress/e2e/jornada-compras.cy.ts

describe('Jornada de Compras do Cliente (E2E)', () => {

  it('Deve bloquear o acesso ao painel admin sem login', () => {
    // Tenta acessar a rota restrita do painel administrativo
    cy.visit('/admin/produtos');
    
    // O adminGuard do Angular deve redirecionar de volta para o login.
    cy.url().should('include', '/login');
    
    // Verifica se a tela de login foi carregada de forma visual
    cy.contains('Acesse sua conta').should('be.visible');
  });

  it('Deve fazer login com sucesso e carregar o catálogo de produtos', () => {
    // Visita a página de login
    cy.visit('/login');

    // 1. O robô preenche o formulário com credenciais corretas e seletores HTML reais
    cy.get('input[name="username"]').type('admin@tecloja.com');
    cy.get('input[name="senha"]').type('admin123'); // Credenciais populadas pelo DataSeeder.java
    
    // 2. O robô clica no botão Entrar
    cy.get('button[type="submit"]').click();
    
    // 3. Aguarda o redirecionamento para o catálogo principal (rota raiz '/')
    cy.url().should('eq', Cypress.config().baseUrl + '/');
    
    // 4. Verifica se a barra de navegação contém o e-mail do usuário logado
    cy.get('.navbar').contains('admin@tecloja.com').should('be.visible');
    
    // 5. Verifica se os cards de produtos (ex: MacBook) foram carregados a partir da API e renderizados
    cy.get('.product-card').should('have.length.greaterThan', 0);
    cy.contains('MacBook').should('be.visible');
  });

});

🔍 💡 Dica de Ouro: Evitando Tela em Branco no Cypress (Bootstrap do Angular & Zone.js)

Se ao rodar os testes você notar que a tela do navegador de testes do Cypress fica completamente preta/azul escura (#0a0f1d) e nenhum elemento é renderizado, você se deparou com um comportamento comum de aplicações Angular standalone: o motor do Cypress não consegue gerenciar a zona reativa de detecção de mudanças sem o polyfill zone.js devidamente importado.

Como Corrigir em 2 Segundos:

Abra o seu arquivo principal de entrada no frontend em web/src/main.ts e garanta que o import do zone.js esteja inserido logo na primeira linha do arquivo:

// web/src/main.ts
import 'zone.js'; // 🚀 Garante o bootstrap limpo em ambientes de testes como o Cypress!
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));

Com essa importação simples no topo do main.ts, o ciclo de vida do Angular inicializará de forma limpa em qualquer ambiente de testes automatizados!


🚀 3. Como Executar os Testes (E2E)

Para que o robô consiga navegar, você precisa estar com a sua API Java e o seu Frontend rodando localmente em abas separadas do terminal.

  1. Inicie a API Java: ./mvnw spring-boot:run
  2. Inicie o Angular: npm start
  3. Em um terceiro terminal, dispare o Cypress:

Modo Interativo (Interface Gráfica)

Abre uma janela visual onde você vê o robô digitando e clicando em tempo real. Ideal para quando estamos programando os testes.

npx cypress open

Modo Headless (CI/CD Automático)

Roda ocultamente no terminal sem abrir interface gráfica. É perfeito para configurar no deploy-frontend.yml do GitHub Actions, bloqueando deploys defeituosos.

npx cypress run

🔍 Checkpoint

Execute apenas o primeiro teste (redirect do guard) — ele não precisa do backend:

  1. Com npm start rodando (localhost:4200), abra um segundo terminal:
    cd web
    npx cypress open
    
  2. Na interface Cypress, selecione E2E Testing → Chrome → Start E2E Testing
  3. Clique em jornada-compras.cy.ts
  4. Observe o Cypress abrir o Chrome, visitar /admin/produtos e ser redirecionado para /login

Resultado esperado: O primeiro it exibe um ✅ verde:

✓ Deve bloquear o acesso ao painel admin sem login (< 1s)

Se o zone.js não estiver importado em main.ts, a tela ficará escura — veja a Dica de Ouro acima.

⚠️ Erros Comuns

Sintoma Causa Solução
Tela do Cypress completamente preta/escura zone.js não importado em main.ts Adicione import 'zone.js'; como primeira linha de web/src/main.ts (veja a Dica de Ouro)
ng add @cypress/schematic falha com erro npm Versão do Angular CLI incompatível Tente npx @angular/cli@latest add @cypress/schematic para usar a versão mais recente
Error: connect ECONNREFUSED 127.0.0.1:4200 Angular não está rodando Execute npm start em outro terminal antes de abrir o Cypress
Segundo teste falha: ERR_CONNECTION_REFUSED :8080 Backend não está rodando Execute ./mvnw spring-boot:run na pasta backend/ antes do teste de login
cy.get('.product-card') não encontra elementos Seletor CSS diverge do HTML real Inspecione o HTML gerado no DevTools e ajuste o seletor no spec — use data-cy attributes para seletores estáveis

🏁 Conclusão da Trilha de Qualidade

Agora sim! Você possui a tríade da qualidade de software configurada:

  1. JUnit e Mockito: Testando a matemática e a lógica profunda do servidor.
  2. Docker e GitHub Actions: Testando os processos de infraestrutura e hospedagem.
  3. Cypress E2E: Testando a interface do usuário (UI) como se fosse um cliente final.

Dominar estas ferramentas é o que separa programadores juniores de Engenheiros de Software Sêniores. Você está pronto para implementar qualidade em sistemas críticos e evitar prejuízos gigantescos em produção!


Voltar para o Sumário