← Back to libraryQuestion 182 of 273
🎭PlaywrightIntermediate

Dialogs, Downloads, New Tabs & Popups

📌 Definition:

Playwright handles browser-native dialogs (alert/confirm/prompt), file downloads, file uploads, and new tabs/popups through dedicated events and APIs, so these traditionally awkward flows are deterministic and easy to assert on.

📖 Detailed Explanation:

JavaScript dialogs auto-dismiss unless you register a page.on('dialog', ...) handler, where you can accept/dismiss and read the message. Downloads are captured via the 'download' event: trigger the action, await the download, then inspect suggestedFilename() or save it and assert contents — no fragile filesystem polling. Uploads use locator.setInputFiles(path) on a file input (or intercept the chooser). New tabs/popups are captured with the 'popup' event or context.waitForEvent('page'), returning a Page object you can drive and assert on, then close. In Selenium these flows need window-handle juggling and OS-level workarounds; Playwright models them as first-class events, which removes a whole category of brittle code.

🔑 Key Points:
  • Dialogs: page.on('dialog', d => d.accept()/d.dismiss()); read d.message()
  • Downloads: await the 'download' event; use suggestedFilename() / saveAs()
  • Uploads: locator.setInputFiles('path') — no OS file-picker automation
  • New tabs/popups: capture via 'popup' event or waitForEvent('page'), then drive the Page
  • Replaces Selenium's window-handle switching and native-dialog hacks
🌍 Real-World Example:

Clicking 'Export CSV' opens a download. The test awaits the download event, checks download.suggestedFilename() is 'orders.csv', saves it, and asserts the file contains the expected header row — verifying the export end to end without brittle filesystem polling or OS dialogs.

📎 Code Example:
// Native confirm() dialog
page.on('dialog', dialog => {
  expect(dialog.message()).toContain('Delete this item?');
  return dialog.accept();
});
await page.getByRole('button', { name: 'Delete' }).click();

// Download
const [download] = await Promise.all([
  page.waitForEvent('download'),
  page.getByRole('button', { name: 'Export CSV' }).click(),
]);
expect(download.suggestedFilename()).toBe('orders.csv');
await download.saveAs('./tmp/orders.csv');

// Upload
await page.getByLabel('Attachment').setInputFiles('./fixtures/resume.pdf');

// New tab / popup
const [popup] = await Promise.all([
  page.waitForEvent('popup'),
  page.getByRole('link', { name: 'Open invoice' }).click(),
]);
await expect(popup).toHaveTitle(/Invoice/);
🎯 Scenario-Based Interview Question:

Scenario: A Selenium test for a 'download report' button is flaky and slow: it polls the Downloads folder in a loop and sometimes reads a partial file. A related test juggles window handles for a popup and often targets the wrong window. How does Playwright make both robust?