Playwright Frame and New Windows

This chapter introduces how to handle iframes, dialogs, new tabs, and the Playwright event system.


iframe Operations

Playwright usesframeLocator()to locate and manipulate elements within iframes.

page.frameLocator() to Locate iframes

Example

test('Operate elements in iframe', async ({ page }) => {
  await page.goto('https://www.example.com/iframe-demo');

  // Locate the iframe, then locate the element inside it
  const iframe = page.frameLocator('#my-iframe');

  // Operate the element inside the iframe
  await iframe.getByRole('button', { name: 'Submit' }).click();
  await iframe.getByLabel('Username').fill('example_user');

  // Assert inside the iframe
  await expect(iframe.getByText('Operation successful')).toBeVisible();
});

Get All Frames

Example

// Get all frames on the page (including the main frame and iframes)
const frames = page.frames();
console.log('The page has ', frames.length, ' frames');

frames.forEach(frame => {
  console.log('Frame:', frame.name(), frame.url());
});

Nested iframes

Playwright'sframeLocator()supports chained calls, allowing deep access into nested iframes.

Example

// Nested iframe: outer → inner → element
const innerButton = page
  .frameLocator('#outer-frame')
  .frameLocator('#inner-frame')
  .getByRole('button', { name: 'Confirm' });

await innerButton.click();

Handling Dialogs

Playwright has a default handling strategy for browser native dialogs (alert, confirm, prompt).

Default Behavior

Playwright by defaultautomatically dismissesall dialogs:

Dialog TypeDefault Behavior
alert()Automatically dismiss (close)
confirm()Automatically accept (returns true)
prompt()Automatically accept (returns empty string)

Custom Dialog Handling

Usingpage.on('dialog')you can intercept and customize dialog handling.

Example

test('Custom dialog handling', async ({ page }) => {
  // Register a listener before triggering the dialog
  page.on('dialog', async dialog => {
    console.log('Dialog type:', dialog.type());
    console.log('Dialog message:', dialog.message());

    if (dialog.type() === 'confirm') {
      // Cancel the confirm dialog
      await dialog.dismiss();
    } else if (dialog.type() === 'prompt') {
      // Enter custom content
      await dialog.accept('Content entered by EXAMPLE');
    } else {
      // For other types, just accept
      await dialog.accept();
    }
  });

  // The operation that triggers the dialog
  await page.getByRole('button', { name: 'Delete' }).click();
});

Dialog Object Methods

MethodDescription
dialog.accept(promptText?)Accept the dialog (can pass input text for prompt)
dialog.dismiss()Dismiss the dialog
dialog.message()Get the dialog message
dialog.type()Get the dialog type:'alert' | 'confirm' | 'prompt' | 'beforeunload'

New Windows and New Tabs

When clicking a link or button opens a new tab, Playwright provides multiple ways to get the new page.

page.waitForEvent('popup') to Wait for Popup

Example

test('Handle new tab', async ({ page }) => {
  // Prepare to wait for the new page event before clicking
  const popupPromise = page.waitForEvent('popup');

  // Click the link that opens a new window
  await page.getByRole('link', { name: 'Open new window' }).click();

  // Get the newly opened page
  const popup = await popupPromise;

  // Operate on the new page
  await expect(popup).toHaveTitle(/EXAMPLE/);
  await popup.getByRole('button', { name: 'OK' }).click();

  // Close the new page
  await popup.close();
});

context.on('page') to Listen for New Pages

Example

test('Listen for all new pages in the Context', async ({ context, page }) => {
  // Listen for new page creation across the entire Context
  context.on('page', async newPage => {
    console.log('A new page opened:', newPage.url());
    // Wait for the new page to finish loading
    await newPage.waitForLoadState();
    // Operate on the new page
  });

  await page.goto('https://www.example.com/');
  // Subsequent operations that open new windows will automatically trigger the above listener
});

Playwright Event System

Playwright's Page and Context objects are event emitters, and you can listen for various events.

Common Page Events

EventTrigger Timing
requestWhen the page initiates a network request
responseWhen a network response is received
dialogWhen an alert/confirm/prompt dialog appears
downloadWhen a file download starts
popupWhen a new page (popup/new tab) opens
consoleWhen the page outputs a console message
pageerrorWhen an uncaught JavaScript error occurs on the page
loadWhen the page finishes loading
closeWhen the page closes

Event Listening Methods

Example

// Listen continuously
page.on('request', request => {
  console.log('Request:', request.method(), request.url());
});

// Listen once (automatically removed after being triggered once)
page.once('dialog', dialog => {
  dialog.accept();
});

// Remove listener
const handler = (request) => { /* ... */ };
page.on('request', handler);
page.off('request', handler);
Other Extensions