</>

Technology

Playwright

Difficulty

Beginner

Interview Question

How do you handle multiple windows or tabs in Playwright?

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

Follow AutomateQA

Related Topics