📚 Módulo 13: QA - Garantia de Qualidade com Testes E2E (Playwright) no Next.js e NestJS
Neste módulo final de Garantia de Qualidade (QA) da TecLoja 04, cobriremos testes ponta a ponta (End-to-End - E2E) utilizando o framework moderno Playwright.
Como a nossa TecLoja 04 adota uma arquitetura corporativa avançada baseada em Next.js (App Router) com renderização do lado do servidor (SSR), controle de rotas por Middleware, e autenticação com cookies protegidos HttpOnly (BFF), o Playwright é a ferramenta recomendada por sua alta velocidade de execução, suporte nativo a isolamento de contextos de navegadores e depuração profunda de Server Actions.
🗺️ 1. Arquitetura do Fluxo de Testes E2E com Playwright
O diagrama abaixo ilustra a esteira de validação controlando o fluxo de ponta a ponta desde a interface do usuário no Next.js até a persistência no banco corporativo:
flowchart TD
%% Styling
classDef pw fill:#2e8b57,stroke:#1e5e3a,stroke-width:2px,color:#fff;
classDef browser fill:#2088ff,stroke:#005cc5,stroke-width:2px,color:#fff;
classDef next fill:#000000,stroke:#333333,stroke-width:2px,color:#fff;
classDef nest fill:#e0234e,stroke:#9f1239,stroke-width:2px,color:#fff;
subgraph Playwright_Engine ["⚙️ Playwright Runner"]
A[Playwright Spec Script]:::pw -->|Controlar via CDP / WebDriver| B[Navegador Chrome/Webkit Headless]:::browser
end
subgraph App_Server_Architecture ["💻 Infraestrutura Corporativa"]
B -->|Acessar e Cliques| C[Next.js App Server - localhost:3000]:::next
C -->|Autenticação BFF via HttpOnly Cookies| D[NestJS API Server - localhost:4000]:::nest
end
⚙️ 2. Instalação e Setup do Playwright no Next.js
Acesse a pasta raiz do seu repositório frontend Next.js e execute a CLI interativa do Playwright para realizar a instalação de todas as dependências nativas e navegadores:
# Executar a instalação interativa recomendada
npm init playwright@latest
Durante o prompt de inicialização no console, responda da seguinte forma:
- Where do you want to put your end-to-end tests?
tests(pressione Enter) - Add a GitHub Actions workflow?
y(Adiciona esteira de CI/CD automática) - Install Playwright browsers?
y(Baixa os binários isolados do Chromium/Firefox/Webkit)
Após a finalização do setup, edite o arquivo de configuração playwright.config.ts criado na raiz do seu projeto Next.js para apontar para a porta local padrão da aplicação:
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000', // Porta padrão de desenvolvimento do Next.js
trace: 'on-first-retry',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
],
});
🧪 3. Escrevendo o Teste do Fluxo E2E (checkout_flow.spec.ts)
Nossos cenários validarão o comportamento do catálogo renderizado no servidor (SSR), o fluxo do carrinho com Zustand e o redirecionamento com base no cookie HttpOnly gerenciado pelo middleware do Next.js.
Crie o arquivo de testes em tests/checkout_flow.spec.ts:
import { test, expect } from '@playwright/test';
test.describe('Fluxo Comercial E2E - TecLoja 04', () => {
test.beforeEach(async ({ page }) => {
// Acessar a Home Page e garantir limpeza de cookies de autenticação
await page.context().clearCookies();
await page.goto('/');
});
test('Deve carregar produtos SSR, adicionar ao carrinho e redirecionar no checkout', async ({ page }) => {
// 1. Confirmar se a página foi renderizada pelo servidor com sucesso
await expect(page.locator('h1')).toContainText('TecLoja 04');
// 2. Localizar o primeiro card de produto
const primeiroProduto = page.locator('.produto-card').first();
await expect(primeiroProduto).toBeVisible();
// Guardar o nome do produto adicionado
const nomeProduto = await primeiroProduto.locator('.produto-nome').innerText();
// 3. Adicionar o produto ao carrinho (Zustand state trigger)
await primeiroProduto.locator('button:has-text("Adicionar ao Carrinho")').click();
// 4. Confirmar que a Navbar (Client Component) foi notificada do incremento do estado
await expect(page.locator('.navbar-carrinho-count')).toContainText('1');
// 5. Ir para o carrinho e confirmar presença do item correto
await page.goto('/carrinho');
await expect(page.locator('.carrinho-list')).toContainText(nomeProduto);
// 6. Tentar finalizar compra (Middleware deve barrar se não houver cookie HttpOnly)
await page.click('button:has-text("Finalizar Compra")');
// 7. Esperado: O middleware intercepta a requisição e redireciona para a tela de autenticação
await expect(page).toHaveURL(/\/login/);
});
test('Deve realizar o login seguro via BFF e finalizar a transação', async ({ page }) => {
// 1. Ir para a tela de login
await page.goto('/login');
// 2. Preencher formulário de credenciais
await page.fill('input[name="email"]', 'maria@gmail.com');
await page.fill('input[name="password"]', '123456');
await page.click('button[type="submit"]');
// 3. Confirmar que o login foi bem sucedido (Cookie HttpOnly configurado em background)
await expect(page).toHaveURL('/');
await expect(page.locator('.navbar-user-section')).toContainText('Maria');
// 4. Adicionar item e fazer o checkout completo
await page.locator('.produto-card').first().locator('button:has-text("Adicionar ao Carrinho")').click();
await page.goto('/carrinho');
// 5. Finalizar pedido (Agora com permissão)
await page.click('button:has-text("Finalizar Compra")');
// 6. Validar a mensagem de sucesso pós-processamento da transação pelo NestJS
const containerSucesso = page.locator('.checkout-sucesso-aviso');
await expect(containerSucesso).toBeVisible();
await expect(containerSucesso).toContainText('Compra faturada com sucesso');
});
});
🚀 4. Executando e Depurando os Testes
Você pode executar o Playwright em diferentes modos usando o terminal:
Modo Headless (Execução Rápida / CI)
Roda os testes em segundo plano e exibe o relatório no final:
npx playwright test
Modo UI (Interface Gráfica de Depuração)
O Playwright abre uma interface gráfica espetacular com time-travel debugging, onde você pode rever o DOM, as requisições de rede feitas pela API Next.js e logs em cada linha de código do teste:
npx playwright test --ui
Verificando Relatório HTML
Caso ocorram erros de asserção, abra o relatório rico em HTML gerado localmente:
npx playwright show-report
✅ Pré-Requisitos deste Módulo
Antes de iniciar os testes E2E, confirme se:
- A API NestJS está respondendo na porta 4000 (
npm run start:devou porta equivalente do backend do Módulo 05). - Você rodou as migrações e o seed de dados no PostgreSQL Neon (
npx prisma db seed). - O servidor de desenvolvimento do Next.js está de pé na porta 3000 (
npm run dev).
🤔 Por que fizemos assim?
- Por que escolher Playwright ao invés de Cypress para a TecLoja 04? O Next.js utiliza React Server Components (RSC). Elementos renderizados no servidor não existem no lado do cliente na primeira carga. O Cypress roda injetando scripts JavaScript na página do navegador do cliente, o que pode mascarar erros de carregamento e hidratamento assíncronos do lado do servidor (Hydration mismatches). O Playwright controla o navegador remotamente via Chrome DevTools Protocol (CDP), operando de forma externa e isolada, o que garante 100% de realismo para testes de páginas server-side.
- Por que testar a segurança do Cookie HttpOnly nos testes? Tokens JWT guardados em Cookies HttpOnly não são visíveis pelo JavaScript (
document.cookieretorna vazio para mitigar ataques XSS). Para validar o login, precisamos testar o comportamento do aplicativo de forma empírica: enviando a requisição e certificando que o middleware Next.js intercepta e decodifica as informações em background para autorizar a rota. O Playwright permite gerenciar e auditar o estado dos cookies do navegador nativamente em cada sessão de teste.
🔍 Checkpoint
- Relatório Verde: Execute
npx playwright teste verifique se as execuções nos navegadores Chromium e Firefox passam sem falhas. - Depuração com Trace Viewer: Rode
npx playwright test --uie clique em cada etapa do teste. Valide a requisição de checkout batendo no BFF do Next.js e confirmando o retorno HTTP 201.
⚠️ Erros Comuns
| Erro | Causa | Solução |
|---|---|---|
Target closed ou timeout na inicialização do teste |
O servidor Next.js ou API NestJS não estão de pé ou a URL base informada no arquivo config está incorreta. | Certifique-se de iniciar as duas aplicações antes de rodar os testes e confirme se a porta de escuta do Next.js coincide com o baseURL do Playwright. |
| Erro de hidratação (Hydration error) ao carregar a página nos testes | O HTML renderizado pelo Next.js no servidor difere do primeiro estado que o React monta no navegador (comum com manipulações locais de Zustand ou datas). | Verifique se as telas com carregamento local dinâmico usam hooks com tratamento para suspender a renderização até o cliente hidratar (com tratamento useEffect ou component dynamic import desativando SSR). |
TargetPage.fill: Timeout 30000ms exceeded |
O Playwright não encontrou o seletor correspondente ao formulário de e-mail ou senha na tela de login. | Certifique-se de que os atributos name ou classes CSS dos campos input no seu formulário Next.js condizem com as chaves declaradas no script do teste. |