QA Learning / Playwright

Módulo 4: Rede e preparo pra CI

page.route pra mock/intercept de rede, um atalho de login mais rápido, e o que muda quando os testes rodam no CI.

🎥 Prefere ver antes de ler?

Esse vídeo (6min18) explica o que é um status code, o que significa "mockar" uma resposta, como o page.route intercepta a rede antes dela sair do navegador, o que são addInitScript e localStorage, a diferença entre um método static e um método de instância, o que é CI e o que significa rodar headless, e termina explicando linha por linha o workflow do GitHub Actions. Fecha com os dois erros (real e mockado) e o login pulado acontecendo de verdade no site de treino. Não substitui o texto abaixo, mas ajuda a visualizar antes de praticar.

1. Erro de verdade vs. erro mockado

O QA Treino tem uma rota que sempre responde 500 (/api/erro), pra testar como a tela reage a um erro de servidor sem depender de derrubar nada de verdade. Mais uma Page Object nova, pages/RedePage.js:

const rede = new RedePage(page);
await rede.goto();
await rede.forceErrorButton.click();
await expect(rede.errorMessage).toContainText("500");

Isso testa o servidor real. Mas às vezes você quer testar como a tela reage a um erro que o servidor não produz hoje: um timeout, um 503 de manutenção, um corpo de resposta estranho. É aí que entra page.route: ele intercepta a requisição antes dela sair do navegador e você decide a resposta:

await page.route("**/api/erro", (route) =>
  route.fulfill({
    status: 503,
    contentType: "application/json",
    body: JSON.stringify({ erro: "Fora do ar pra manutencao (mock)." }),
  })
);
await rede.goto();
await rede.forceErrorButton.click();
await expect(rede.errorMessage).toContainText("503");

O padrão (**/api/erro) usa glob: ** casa qualquer coisa antes, então funciona não importa a origem exata (localhost:3000 hoje, outra coisa amanhã).

2. Pular o login com addInitScript

O login em si já foi testado no Módulo 1. Repetir a tela de login em todo teste que só precisa estar logado custa tempo (e é mais um lugar pra flakiness acontecer). page.addInitScript injeta um script que roda antes de qualquer script da página, em toda navegação. Dá pra escrever a sessão direto. Como isso não pertence a nenhuma página específica (é sobre a sessão, não sobre o login.html), virou um método estático na própria LoginPage:

// dentro de pages/LoginPage.js
static async pularLogin(page, nome = "Maria") {
  await page.addInitScript((nomeInjetado) => {
    localStorage.setItem("qa-treino-sessao", JSON.stringify({ nome: nomeInjetado }));
  }, nome);
}

No teste:

await LoginPage.pularLogin(page, "Maria");
await page.goto("/index.html");
await expect(page.getByTestId("nav-account-name")).toHaveText("Maria");

Quando usar qual: se o teste é sobre o login (Módulo 1), passe pela UI de verdade. Se o login é só um pré-requisito pra testar outra coisa (carrinho, paginação, mock de produto), pular direto é mais rápido e mais estável: menos passos, menos chance de um deles falhar por motivo que não tem nada a ver com o que você está testando.

Fora desta trilha: o addInitScript funciona porque aqui a sessão é só um item no localStorage. Em projetos reais o Playwright tem um jeito oficial pra isso: storageState. A ideia é fazer o login pela UI uma vez, salvar cookies e localStorage num arquivo JSON (await page.context().storageState({ path: "sessao.json" })) e depois reaproveitar esse arquivo em todos os testes via playwright.config.js (use: { storageState: "sessao.json" }). É o padrão usado em produção porque funciona com qualquer mecanismo de sessão (cookie de verdade, token, o que for), não só localStorage manual como fizemos acima.

3. Os testes deste módulo

Arquivo já existe em tests/04_rede_ci.spec.js. Não precisa digitar, só rodar:

npx playwright test tests/04_rede_ci.spec.js

4. O que muda pra rodar em CI

Os comandos que você já roda (npx playwright test) já executam headless por padrão (sem abrir janela de navegador), então já funcionam num servidor de CI sem alteração nenhuma. Como o alvo (QA Treino) já está publicado, o CI nem precisa subir nada: só instalar os navegadores do Playwright na máquina do runner e rodar. Um workflow do GitHub Actions pra isso, pra ler (não precisa rodar agora, depende do repositório estar público, que ainda não é o caso):

name: Playwright
on: [push, pull_request]
jobs:
  testes:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci
        working-directory: trilha-7
      - run: npx playwright install --with-deps chromium
        working-directory: trilha-7
      - run: npx playwright test
        working-directory: trilha-7

É a mesma lógica da Trilha 6: o pipeline só automatiza os mesmos comandos que você já roda à mão, um atrás do outro. Se tiver curiosidade de como isso se encaixa num workflow de verdade, vale revisar aquela trilha.

Exercício

Em tests/04_rede_ci.spec.js, escreva um teste chamado "produto mockado aparece na lista" que combina as duas técnicas do módulo: pule o login com LoginPage.pularLogin(page, "Maria") e use page.route em "**/api/produtos*" pra devolver um produto inventado ({ id: 999, nome: "Produto Mockado", preco: 9.9, emoji: "🧪" }), depois confira que product-card-999 aparece com esse nome. Rode python verificar.py 4 até dar 5 [ok]. Gabarito em trilha-7/GABARITO.md.

📁 Ver estrutura de pastas da trilha-7/
trilha-7/
├── playwright.config.js
├── package.json
├── verificar.py
├── GABARITO.md
├── README.md
├── fixtures/
│   └── exemplo.png
├── pages/
│   ├── LoginPage.js   ← pularLogin() usado neste exercício
│   ├── CadastroPage.js
│   ├── ProdutosPage.js
│   ├── ProdutoPage.js
│   └── RedePage.js
└── tests/
    ├── 01_primeiro_teste.spec.js
    ├── 02_selecionadores.spec.js
    ├── 03_cenarios.spec.js
    └── 04_rede_ci.spec.js   ← este exercício

Olhar de QA

Mockar rede é uma faca de dois gumes. Pra baixo: testa como a tela reage a um cenário (erro, vazio, dado estranho) sem precisar reproduzir esse cenário no servidor de verdade: mais rápido, mais estável, cobre casos difíceis de forçar. Pra cima: se você mockar tudo, nunca testa se o front-end e o back-end ainda concordam sobre o formato da resposta, e um contrato quebrado passa despercebido. A prática mais segura: ter alguns testes de ponta a ponta contra o servidor real (como os Módulos 1 a 3 fizeram) e usar mock pontualmente pros cenários que o servidor real não reproduz de forma confiável.

Terminou este módulo? Marque: o ✓ aparece no índice da trilha e a barra de progresso anda no começo do site. Fica salvo só no seu navegador.