Iframes e janelas
O navegador.iife.js preenche um documento por chamada. Os iframes da página, da mesma origem ou de outra, ficam de fora da chamada no documento principal.
Um documento por chamada
O resultado traz iframesDeFora: quantos iframes de outra origem o documento tem. Os da mesma origem não entram na conta.
iframesDeFora: 0 não quer dizer "preenchi tudo". Um iframe da mesma origem também fica de fora da chamada, e não aparece nessa contagem.
Para preencher os frames, injete o motor e chame em cada um. No Playwright, page.frames() dá todos, inclusive os de outra origem:
for (const frame of page.frames()) {
await frame.evaluate(TEXTO_DO_IIFE)
const r = await frame.evaluate(
({ pessoa, hoje }) =>
window.__botaiNavegador.preencher(document, pessoa, hoje, {
segundaPassada: false,
}),
{ pessoa, hoje },
)
console.log(frame.url(), r.preenchidos.length)
}
Numa página com um campo próprio, um iframe da mesma origem e um de outra origem, cada um com um campo:
http://localhost:3000/checkout 1
http://localhost:3000/filho 1
http://outro.localhost:4000/filho 1
TEXTO_DO_IIFE é o conteúdo do arquivo (como ler). Injetar o texto com evaluate também funciona sob CSP estrita.
O fixture @pilutech/botai-playwright faz isso sozinho: botai.preencher(page) percorre todos os frames em paralelo, de qualquer origem, inclusive srcdoc e páginas abertas depois do fixture. Veja Preencher.
Na extensão é diferente: ela soma os iframes da mesma origem e deixa de fora os de outro domínio (Stripe Elements, Pagar.me), por causa da permissão activeTab.
A armadilha da janela
O motor só reconhece os campos da janela em que foi instalado.
Instalado numa janela e chamado com o document de outra (um iframe, por exemplo), o motor termina sem erro e com 0 preenchidos. Instale o motor na janela do documento que você quer preencher.
O jeito certo é avaliar o texto do IIFE na própria janela do documento e chamar o __botaiNavegador dela:
const resultado = await page.evaluate(
async ({ pessoa, hoje, TEXTO_DO_IIFE }) => {
const win = document.getElementById('app').contentWindow
const errado = await window.__botaiNavegador.preencher(
win.document,
pessoa,
hoje,
{
segundaPassada: false,
},
)
win.eval(TEXTO_DO_IIFE)
const certo = await win.__botaiNavegador.preencher(
win.document,
pessoa,
hoje,
{
segundaPassada: false,
},
)
return {
errado: errado.preenchidos.length,
certo: certo.preenchidos.length,
}
},
{ pessoa, hoje, TEXTO_DO_IIFE },
)
console.log(resultado)
Com o motor já instalado na página e um iframe #app da mesma origem com um campo de CPF:
{ errado: 0, certo: 1 }
O caso típico é o Cypress: o spec roda numa janela, e o app, em outra. Importar o motor no spec cai nessa armadilha; avaliar o IIFE na janela do app (cy.window() e win.eval) não. Veja Cypress.