@agrotools1/at-e2e-kit
v1.0.0
Published
Helpers e fixtures de Playwright compartilhados entre os microfrontends Agrotools (login via athost + navegação de módulo)
Readme
at-e2e-kit
Helpers e fixtures de Playwright compartilhados entre os microfrontends Agrotools: login automático via athost + navegação de módulo.
📦 npm: @agrotools1/at-e2e-kit
Setup
1. Instalar (@playwright/test >=1.40.0 é peer dep):
pnpm add -D @agrotools1/at-e2e-kit @playwright/test
pnpm exec playwright install chromium2. playwright.config.ts na raiz:
import { createE2EConfig } from '@agrotools1/at-e2e-kit/config'
export default createE2EConfig({
moduleBasePath: '/paineladministrativo', // path do módulo dentro do shell (athost)
})Configura sozinho: retries, reporter, trace/screenshot/video on-failure, bypass de cert para api-test-homolog.agrotools.com.br, e os projects setup (login) + chromium (dependencies: ['setup'], injeta a sessão salva). Testes em ./tests/e2e. automaticLogin: false se o módulo não precisa de login; overrides pra sobrescrever campo pontual (ex: viewport).
3. Auto-login — crie um *.setup.ts em tests/e2e/ (regex do project setup é /.*\.setup\.ts/):
// tests/e2e/auth.setup.ts
import '@agrotools1/at-e2e-kit/setup'O import já registra o teste de bootstrap, roda no project setup antes do resto, salva a sessão em tests/e2e/.auth/user.json e reaproveita enquanto for válida — não loga de novo a cada run.
4. Env vars — .env.test, .env.development etc., no mínimo:
PLAYWRIGHT_USER_EMAIL="[email protected]"
PLAYWRIGHT_USER_PASSWORD="sua-senha"Lista completa + ordem de cascata: Variáveis de ambiente.
5. .gitignore — sessão e evidências nunca vão pro commit:
tests/e2e/.auth
tests/e2e/videos
/test-results
/playwright-report
/playwright/.cache6. Primeiro teste:
// tests/e2e/exemplo.spec.ts
import { expect, test } from '@playwright/test'
import { openRoute } from '@agrotools1/at-e2e-kit'
test('exemplo', async ({ page }) => {
await openRoute(page, '/minha-rota')
await expect(page.locator('h1')).toBeVisible()
})openRoute já garante o boot da sessão (ensureShellBooted) antes de navegar. Não chame page.goto direto.
7. Rodar — scripts sugeridos pro package.json do consumidor:
{
"scripts": {
"test:e2e": "playwright test",
"test:e2e:headed": "playwright test --headed --workers=1",
"test:e2e:ui": "playwright test --ui",
"test:e2e:evidence": "cross-env RECORD_EVIDENCE=true playwright test --headed --workers=1",
"test:e2e:login:reset": "node -e \"require('fs').rmSync('tests/e2e/.auth/user.json', { force: true })\""
}
}| Script | Faz |
| --- | --- |
| test:e2e | Headless (sem browser visível — normal, não é bug) |
| test:e2e:headed | Browser de verdade, pra debugar |
| test:e2e:ui | UI mode |
| test:e2e:evidence | Grava vídeo de cada teste (evidência em vídeo) |
| test:e2e:login:reset | Reseta a sessão salva, força login de novo (sessão expirada / trocou usuário de teste) |
API
Navegação
openRoute(page, path) e ensureShellBooted(page) — o segundo é chamado internamente pelo primeiro, só use direto se precisar do boot sem navegar em seguida.
⚠️ Mocks e ordem LIFO
ensureShellBooted registra mockCertBypassRoute internamente toda vez que a page ainda não está na URL do módulo (pode rodar mais de uma vez durante boot/navegação). Playwright resolve page.route() em LIFO — último handler registrado ganha. Isso quebra a intuição: se você registrar um mock específico (page.route('**/minha-api/**', ...)) antes de openRoute, e o host da API coincidir com api-test-homolog.agrotools.com.br, o bypass genérico registrado depois pode vencer o seu — mesmo o seu tendo sido registrado primeiro.
Sintoma: componente recebe {} do bypass em vez do seu fixture, quebra silencioso em qualquer código que espere array/objeto.
Fix: registre mocks específicos depois de openRoute, com reload se o fetch já tiver disparado:
await openRoute(page, '/')
await page.route('**/minha-api/**', (route) => route.fulfill({ status: 200, body: '...' }))
await page.reload()
await page.waitForLoadState('networkidle')mockCertBypassRoute(page) também é exportado — chame direto num beforeEach se quiser garantir que o bypass já está registrado antes de qualquer coisa. É o que a maioria dos módulos faz na prática, em vez de depender só do registro interno.
Helpers de UI
| Helper | Faz |
| --- | --- |
| findFirstVisible(page, selectors) | Primeiro Locator visível de uma lista de seletores, ou null |
| openAnyDropdown(page) | Clica no primeiro trigger de dropdown visível ([role="combobox"], Radix, Reka UI), retorna { trigger, content } |
| computedStyle(locator, property) | CSS computado do elemento |
| boundingBoxOrFail(locator, name) | Como boundingBox(), mas lança erro descritivo (com name) se vier null |
Console
import { collectConsole, assertNoForbiddenConsole } from '@agrotools1/at-e2e-kit'
test('sem erros de console proibidos', async ({ page }) => {
const messages = collectConsole(page)
// ...
assertNoForbiddenConsole(messages)
})collectConsole acumula console.error/console.warning/pageerror conforme acontecem. assertNoForbiddenConsole lança erro se alguma mensagem contiver Portal, Floating UI ou Reka UI — vazamento clássico de warning de UI lib por uso incorreto de componente.
Evidência em vídeo
saveVideoEvidence(page, videoName) fecha a page e renomeia o vídeo gravado pelo Playwright pra tests/e2e/videos/<videoName>-<timestamp>.webm, resgatando o arquivo antes do cleanup padrão de retain-on-failure (não precisa mexer em video.mode). Gate por RECORD_EVIDENCE pra só gravar quando pedido:
if (process.env.RECORD_EVIDENCE) {
await saveVideoEvidence(page, 'exemplo-evidence')
}Variáveis de ambiente
Cascata (primeiro valor definido vence): .env.test.local → .env.test → .env.development.local → .env.development → .env.local → .env.homolog → .env
| Variável | Descrição |
| --- | --- |
| E2E_BASE_URL | URL base do shell (athost). Default http://localhost:3333 |
| E2E_MODULE_BASE_PATH | Path base do módulo dentro do shell (ex: /paineladministrativo) |
| E2E_API_HOST | Host da API usado no bypass de certificado (mockCertBypassRoute + launchOptions de auto-select de certificado). Default api-test-homolog.agrotools.com.br |
| PLAYWRIGHT_USER_EMAIL / PLAYWRIGHT_USER_PASSWORD | Credenciais de login via Global Account |
| RECORD_EVIDENCE | Liga a gravação de vídeo via saveVideoEvidence |
Nunca commite valor real em .env.development/.env.homolog/etc versionados — use .env.*.local (gitignored).
Dev do kit
pnpm build # dist/ via tsup
pnpm typecheck # tsc --noEmit
pnpm lint # eslint --fix
pnpm test # vitest run
pnpm test:watch # vitest watchBranches: main (protegida, PR obrigatório) · test (espelha o ambiente de teste)
PR a partir de uma branch de feature. Antes de abrir: pnpm typecheck && pnpm test && pnpm build (mesmo comando do prepublishOnly).
