Answer
Handling Multiple Windows and Tabs in Playwright
Playwright has native support for multiple browser pages (tabs/windows) within a BrowserContext. This is a key advantage over Selenium which requires complex window handle switching.
Scenario 1 — Click Opens a New Tab
TypeScript
import { test, expect } from '@playwright/test';
test('link opens in new tab', async ({ page, context }) => {
await page.goto('https://example.com');
// Wait for new page BEFORE clicking the link that opens it
const [newPage] = await Promise.all([
context.waitForEvent('page'),
page.getByRole('link', { name: 'Open in new tab' }).click(),
]);
// Wait for the new tab to finish loading
await newPage.waitForLoadState('domcontentloaded');
await expect(newPage).toHaveURL('https://partner.com');
await expect(newPage.getByRole('heading')).toHaveText('Welcome');
});
Scenario 2 — window.open() Opens New Window
TypeScript
test('popup window', async ({ page, context }) => {
await page.goto('/dashboard');
const [popup] = await Promise.all([
context.waitForEvent('page'),
page.getByRole('button', { name: 'Open Report' }).click(),
]);
await popup.waitForLoadState();
console.log(await popup.title()); // "Monthly Report"
// Close popup when done
await popup.close();
});
Scenario 3 — Manually Open a New Tab
TypeScript
test('work with multiple tabs', async ({ context }) => {
const page1 = await context.newPage();
const page2 = await context.newPage();
await page1.goto('https://myapp.com/products');
await page2.goto('https://myapp.com/cart');
// Get product name from page1
const productName = await page1.locator('.product-name').first().innerText();
// Verify cart on page2
await page2.getByRole('button', { name: 'Add' }).click();
await expect(page2.locator('.cart-item')).toContainText(productName);
});
Scenario 4 — Get All Open Pages
TypeScript
test('list all pages', async ({ context }) => {
await context.newPage(); // page 1
await context.newPage(); // page 2
const pages = context.pages();
console.log(pages.length); // 2
// Switch to specific page by index
const secondPage = pages[1];
await secondPage.bringToFront();
});
Key Difference from Selenium
Selenium:
Java
Set<String> handles = driver.getWindowHandles();
for (String handle : handles) {
driver.switchTo().window(handle);
}
Playwright:
TypeScript
// No switching needed — each page is its own object
const [newPage] = await Promise.all([
context.waitForEvent('page'),
page.click('#open-tab'),
]);
// Work with newPage directly
