update tutorial node node.js automated-tests google-chrome-headless puppeteer

node.js - tutorial - npm



Titiritero: ¿Cómo manejar múltiples pestañas? (7)

Actualmente no puede: siga https://github.com/GoogleChrome/puppeteer/issues/386 para saber cuándo se agrega la habilidad al titiritero (con suerte pronto)

Escenario: formulario web para el registro de aplicaciones de desarrollador con un flujo de trabajo de dos partes.

Página 1: Complete los detalles de la aplicación para desarrolladores y haga clic en el botón para crear el ID de la aplicación, que se abre, en una nueva pestaña ...

Página 2: La página de ID de la aplicación. Necesito copiar la ID de la aplicación de esta página, luego cerrar la pestaña y volver a la página 1 y completar la ID de la aplicación (guardada desde la página 2), luego enviar el formulario.

Entiendo el uso básico: cómo abrir la página 1 y hacer clic en el botón que abre la página 2, pero ¿cómo puedo controlar la página 2 cuando se abre en una nueva pestaña?

Ejemplo:

const puppeteer = require(''puppeteer''); (async() => { const browser = await puppeteer.launch({headless: false, executablePath: ''/Applications/Google Chrome.app''}); const page = await browser.newPage(); // go to the new bot registration page await page.goto(''https://register.example.com/new'', {waitUntil: ''networkidle''}); // fill in the form info const form = await page.$(''new-app-form''); await page.focus(''#input-appName''); await page.type(''App name here''); await page.focus(''#input-appDescription''); await page.type(''short description of app here''); await page.click(''.get-appId''); //opens new tab with Page 2 // handle Page 2 // get appID from Page 2 // close Page 2 // go back to Page 1 await page.focus(''#input-appId''); await page.type(appIdSavedFromPage2); // submit the form await form.evaluate(form => form.submit()); browser.close(); })();

Actualización 2017-10-25

Sigo buscando un buen ejemplo de uso.


En teoría, podría anular la función window.open para abrir siempre "nuevas pestañas" en su página actual y navegar a través del historial.

Su flujo de trabajo sería entonces:

  1. Anular la función window.open :

    await page.evaluateOnNewDocument(() => { window.open = (url) => { top.location = url } })

  2. Ve a tu primera página y realiza algunas acciones:

    await page.goto(PAGE1_URL) // ... do stuff on page 1

  3. Vaya a su segunda página haciendo clic en el botón y realice algunas acciones allí:

    await page.click(''#button_that_opens_page_2'') await page.waitForNavigation() // ... do stuff on page 2, extract any info required on page 1 // e.g. const handle = await page.evaluate(() => { ... })

  4. Regresa a tu primera página:

    await page.goBack() // or: await page.goto(PAGE1_URL) // ... do stuff on page 1, injecting info saved from page 2

Este enfoque, obviamente, tiene sus inconvenientes, pero me parece que simplifica drásticamente la navegación de múltiples pestañas, lo cual es especialmente útil si ya está ejecutando trabajos paralelos en varias pestañas. Desafortunadamente, la API actual no hace que sea una tarea fácil.


Esto funcionará para usted en la última rama alfa:

const newPagePromise = new Promise(x => browser.once(''targetcreated'', target => x(target.page()))); await page.click(''my-link''); // handle Page 2: you can access new page DOM through newPage object const newPage = await newPagePromise; await newPage.waitForSelector(''#appid''); const appidHandle = await page.$(''#appid''); const appID = await page.evaluate(element=> element.innerHTML, appidHandle ); newPage.close() [...] //back to page 1 interactions

Asegúrese de usar la última versión del titiritero (de la rama maestra de Github) configurando la dependencia package.json en

"dependencies": { "puppeteer": "git://github.com/GoogleChrome/puppeteer" },

Fuente: JoelEinbinder @ https://github.com/GoogleChrome/puppeteer/issues/386#issuecomment-343059315


Hace dos días se browser.pages() un nuevo parche y ahora puede usar browser.pages() para acceder a todas las páginas en el navegador actual. Funciona bien, me probé ayer :)

Editar:

Un ejemplo de cómo obtener un valor JSON de una nueva página abierta como enlace ''target: _blank''.

const page = await browser.newPage(); await page.goto(url, {waitUntil: ''load''}); // click on a ''target:_blank'' link await page.click(someATag); // get all the currently open pages as an array let pages = await browser.pages(); // get the last element of the array (third in my case) and do some // hucus-pocus to get it as JSON... const aHandle = await pages[3].evaluateHandle(() => document.body); const resultHandle = await pages[3].evaluateHandle(body => body.innerHTML, aHandle); // get the JSON value of the page. let jsonValue = await resultHandle.jsonValue(); // ...do something with JSON


Podría eliminar la necesidad de cambiar de página en caso de que sea causada por el atributo target="_blank" - estableciendo target="_self"

Ejemplo:

element = page.$(selector) await page.evaluateHandle((el) => { el.target = ''_self''; }, element) element.click()


Según la documentación oficial :

browser.pages ()

  • devuelve: < Promise < Array < Page >>> Promise que se resuelve en un array de todas las páginas abiertas. Las páginas no visibles, como "background_page" , no se mostrarán aquí. Puedes encontrarlos usando target.page() .

Una matriz de todas las páginas dentro del navegador. En el caso de múltiples contextos de navegador, el método devolverá una matriz con todas las páginas en todos los contextos de navegador.

Ejemplo de uso:

let pages = await browser.pages(); await pages[0].evaluate( () => { /* ... */ } ); await pages[1].evaluate( () => { /* ... */ } ); await pages[2].evaluate( () => { /* ... */ } );


Si su acción de clic emite una carga de página, los guiones posteriores que se ejecutan se pierden efectivamente. Para solucionar esto, debe activar la acción (un clic en este caso) pero no await . En su lugar, espere la carga de página:

page.click(''.get-appId''); await page.waitForNavigation();

Esto permitirá que su script espere efectivamente al próximo evento de carga de página antes de continuar con otras acciones.