@pilutech/botai-playwright
v0.2.0
Published
Fixture do Playwright que gera uma pessoa brasileira de teste reproduzível e preenche formulários com o motor do Botaí
Maintainers
Readme
@pilutech/botai-playwright
Fixture do Playwright que gera uma pessoa brasileira de teste (nome, CPF, RG, CNPJ, celular, CEP real com rua e cidade certas, cartão de teste) reproduzível, e preenche formulários com o mesmo motor da extensão Botaí.
Instalação
npm install -D @pilutech/botai-playwright
# ou
pnpm add -D @pilutech/botai-playwright@playwright/test (1.59.1 ou mais novo na linha 1.x) é peer dependency: o seu projeto já o tem. O pacote é só ESM; num projeto CommonJS, use o Node 20.19+ ou 22.12+.
Uso
import { test, expect } from '@pilutech/botai-playwright'
test('cadastro', async ({ page, botai }) => {
await page.goto('/cadastro')
const resultado = await botai.preencher(page) // percorre todos os frames
expect(resultado.naoReconhecidos).toEqual([])
await expect(page.getByLabel('E-mail')).toHaveValue(
botai.pessoa.email.endereco,
)
})botai.preencher aceita:
- uma
Page: todos os frames, inclusive iframes de outro domínio; - um
Locator: só aquele elemento (um<form>, uma seção ou um campo só), inclusive dentro de iframe (page.frameLocator('iframe').locator('form')).
A pessoa é a mesma a cada execução
Sem opção nenhuma, a semente é o nome do projeto, o arquivo e os títulos do teste: chromium › cadastro.e2e.ts › cadastro. Retry e worker não entram, então a nova tentativa preenche com a mesma pessoa. O fixture registra no relatório:
- a anotação
botai-semente(a semente) e abotai-hoje(a data usada); - quando o teste falha, o anexo
botai-pessoa.json, com{ formato, motor, semente, hoje, pessoa }(o cartão da pessoa leva oprovedore ocenario).
Para gerar a mesma pessoa fora do teste (Python, Go, banco de dados…):
npx @pilutech/botai-core pessoa --semente "chromium › cadastro.e2e.ts › cadastro" --hoje 2026-10-05A pessoa de uma semente só muda em versão major do @pilutech/botai-core. Para reproduzir, fixe a versão.
Opções
| Opção | Padrão | O quê |
| ------------------- | ---------------------- | ------------------------------------------------------------------------- |
| botaiSemente | projeto + título | número ou texto; 42 e '42' dão a mesma pessoa |
| botaiHoje | hoje em São Paulo | AAAA-MM-DD; idade, nascimento e validade do cartão contam a partir dela |
| botaiUf | sorteada | UF do endereço (e do DDD, do CPF e do título) |
| botaiDominioEmail | tuamaeaquelaursa.com | domínio do e-mail |
| botaiCartao | stripe, aprovado | { provedor, cenario } do cartão de teste (veja abaixo) |
test.use({ botaiHoje: '2026-10-05', botaiUf: 'PI' })Ou para o projeto inteiro, no playwright.config.ts: use: { botaiHoje: '2026-10-05' }.
Cartão de teste por cenário
O cartão da pessoa usa só números de teste oficiais, da Stripe ou do simulador da Pagar.me. Escolha o provedor e o cenário com botaiCartao:
test.describe('pagamento recusado', () => {
test.use({ botaiCartao: { provedor: 'pagarme', cenario: 'recusado' } })
test('mostra o erro do cartão', async ({ page, botai }) => {
await page.goto('/checkout')
await botai.preencher(page) // o número do cartão é 4000 0000 0000 0028
await page.getByRole('button', { name: 'Pagar' }).click()
await expect(page.getByText('Pagamento recusado')).toBeVisible()
})
})| Provedor | Cenários |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| stripe | aprovado, recusado, pendente (exige 3DS), recusado-saldo, recusado-roubado, recusado-perdido, recusado-expirado, recusado-cvc, erro-processamento |
| pagarme | aprovado, recusado, pendente (processa e aprova), pendente-recusado, pendente-cancelado, chargeback |
- O cenário muda só o cartão: com a mesma semente, o resto da pessoa é igual em qualquer cenário. A semente padrão inclui os títulos do teste, então dois
describegeram pessoas diferentes; para comparar cenários com a mesma pessoa, fixebotaiSemente. - Cenário que o provedor não tem falha no setup do teste com
botaiCartao: cenário desconhecido "…" para o provedor … (use …). - Para gerar a mesma pessoa fora do teste:
npx @pilutech/botai-core pessoa --semente "<semente>" --hoje <hoje> --cartao pagarme --cenario recusado.
Resultado
interface ResultadoDoPreenchimento {
preenchidos: { frame: string; rotulo: string; seletor: string }[]
naoReconhecidos: { frame: string; rotulo: string; seletor: string }[]
recusados: { frame: string; rotulo: string; seletor: string }[]
}frame é a URL do frame. recusados são campos reconhecidos que não aceitaram o valor (não cabe no maxlength, a página o desfez, o <select> não tem a opção).
Segunda passada
Sites que buscam o CEP sobrescrevem rua, bairro e complemento logo depois. botai.preencher só termina depois de regravar o que mudou (uma passada, 1 s depois de escrever). Para pular: botai.preencher(page, { segundaPassada: false }).
Junto com outros fixtures
import { mergeTests } from '@playwright/test'
import { test as testBotai } from '@pilutech/botai-playwright'
import { test as testDoProjeto } from './fixtures'
export const test = mergeTests(testDoProjeto, testBotai)Ou estenda um test que você já tem (playwright-bdd, por exemplo):
import { fixturesBotai, type FixturesBotai } from '@pilutech/botai-playwright'
export const test = base.extend<FixturesBotai>(fixturesBotai())Como funciona
O motor (@pilutech/botai-core/navegador) é injetado em cada frame por frame.evaluate, que passa pela CSP da página, e cria um único global, __botaiNavegador. Ele escreve pelo setter nativo e dispara focus, input, change e blur sintéticos, sem roubar o foco: React controlado, máscaras e validação no blur enxergam o valor. Não pinta contorno nenhum na página.
Limites
- Shadow root fechada fica de fora (o Playwright não a alcança). A aberta é preenchida.
- Checkbox, radio, contenteditable e combobox sem
<select>nativo não são preenchidos. - O código roda no mundo da página: um site que troca protótipos nativos pode interferir.
- Com
page.clock.install(), o relógio falso segura a segunda passada: use{ segundaPassada: false }ou avance o relógio. - CPF, CNPJ e celular gerados podem pertencer a gente real; use só em ambiente de teste. A caixa
tuamaeaquelaursa.comé pública: para dado sensível, usebotaiDominioEmailcom um domínio seu.
Licença
MIT © PiluTech
