Reputation: 1523
My web app opens a new tab under some conditions. But when I try to get all tabs (await browser.pages())
I get only one back, the initial page.
How can I get the new page's object in my code?
This happens when you don't create new tab with puppeteer with await browser.newPage()
, but when you do something like this:
await (await browser.pages())[0].evaluate(() => {
window.open('http://www.example.com', '_blank');
});
The page won't be available in the browser.pages()
response.
Upvotes: 18
Views: 29500
Reputation: 57115
An alternative to this (perfectly fine!) approach is to promisify the browser's "targetcreated"
event as described in a comment on Puppeteer issue #386:
const puppeteer = require("puppeteer");
const { once } = require('events');
(async () => {
const html = `<a href="https://news.ycombinator.com" target="_blank">click</a>`;
const browser = await puppeteer.launch({headless: false});
const [page] = await browser.pages();
await page.setContent(html);
await page.waitForSelector("a", {visible: true});
console.log((await browser.pages()).length); // => 1
const newPagePromise = once("targetcreated", browser).then(x => x.page());
await page.click("a");
const newPage = await newPagePromise;
console.log((await browser.pages()).length); // => 2
console.log((await newPage.content()));
await browser.close();
})();
Another way to write this is with Promise.all
and a destructuring assignment to get the first element from the result array:
const [newPage] = await Promise.all([
once(browser, "targetcreated").then(x => x.page),
page.click("a")
]);
Upvotes: 0
Reputation: 551
This code will catch the new page in a new tab if it was opened by clicking a link in the original page.
//save target of original page to know that this was the opener:
const pageTarget = page.target();
//execute click on first tab that triggers opening of new tab:
await page.click('#selector');
//check that the first page opened this new page:
const newTarget = await browser.waitForTarget(target => target.opener() === pageTarget);
//get the new page object:
const newPage = await newTarget.page();
Upvotes: 55
Reputation: 18826
It's hard without knowing your conditions when the app opens a new tab. It works perfectly fine for me. Here is a code demonstrating how I can use it. Read the comments to understand the steps.
UPDATED:
window.open()
doesn't return a promise, thus browser.pages() is executed faster than the browser can create and report the event. We can use the targetcreated
event to know if any new tab is created.
browser.on('targetcreated', function(){
console.log('New Tab Created');
})
If you wait for a while or return a promise, you will see it reports it within browser.pages()
count.
await tabOne.evaluate(() => {
window.open('http://www.example.com', '_blank');
});
await tabOne.waitFor(2000); // await for a while
console.log("current page count ", (await browser.pages()).length); // 3
Here is the final code.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
browser.on('targetcreated', function(){
console.log('New Tab Created');
})
// get current tab count
console.log("current page count ", (await browser.pages()).length); // 3
// create a new tab
await browser.newPage();
// lets see if tab increased
console.log("current page count ", (await browser.pages()).length); // 3
// use destructuring for easier usage
const [tabOne, tabTwo] = (await browser.pages());
// use the tabs aka Page objects properly
await tabOne.goto('https://example.com');
console.log("Tab One Title ",await tabOne.title()); // Example Domain
// use the tabs aka Page objects properly
await tabTwo.goto('https://example.com');
console.log("Tab Two Title ",await tabTwo.title()); // Example Domain
await tabOne.evaluate(() => {
window.open('http://www.example.com', '_blank');
});
await tabOne.waitFor(2000); // wait for a while
console.log("current page count ", (await browser.pages()).length); // 3
// close the browser
await browser.close();
})();
If you run it, you'll get the result in following sequence.
/*
current page count 1
New Tab Created
current page count 2
Tab One Title Example Domain
Tab Two Title Example Domain
New Tab Created
current page count 3
*/
Upvotes: 7