Playwright·Cookbook Field Manual
Part 09 · Interaction Toolkit Card 46

Browser Dialogs

Card 46: Browser Dialogs

The portable agent skills for this pattern are playwright-interactions and playwright-assertions.

What This Pattern Solves

alert(), confirm(), prompt() and beforeunload open native dialogs that block the page’s JavaScript until someone answers. A role locator cannot find them because they live outside the DOM. When no listener is registered, Playwright dismisses every dialog for you. The test keeps running, confirm() returns false, and the app takes its cancel path while you think you tested the happy path.

How It Works

  1. Register before the trigger: page.once('dialog', handler) before the click that opens the dialog.
  2. Inspect: dialog.type() is alert, confirm, prompt or beforeunload. dialog.message() is the text. dialog.defaultValue() is a prompt’s prefilled value.
  3. Answer: dialog.accept(), dialog.accept(text) for a prompt, or dialog.dismiss().
  4. Assert the outcome on the page: the dialog only proves it appeared. The status text proves the app acted on the answer.

Code Example

// Bad: no listener. Playwright dismisses, confirm() returns false.
await page.getByRole('button', { name: 'Delete account' }).click();
await expect(page.getByRole('status')).toHaveText('Kept');

// Good: record and answer the next dialog, then assert after the click.
let message = '';
page.once('dialog', async (dialog) => {
  message = dialog.message();
  await dialog.accept();
});
await page.getByRole('button', { name: 'Delete account' }).click();
await expect(page.getByRole('status')).toHaveText('Deleted');
expect(message).toBe('Delete your account?');

// prompt: accept with a value
page.once('dialog', (dialog) => dialog.accept('Quarterly report'));

Key Concepts

When to Use This Pattern

Isolated examples

The spec builds its dialog page with page.setContent. Run the tests to see the auto-dismiss trap, then each dialog handled.

Run This Example

pnpm test src/46-browser-dialogs