How to Handle Alert Dialog in Playwright?

Alert dialogs are a common part of modern web applications and sites. They are used to display messages, warnings, confirmations, and more to the user. When automating with Playwright, you'll often come across alerts while interacting with pages. Playwright provides a clean API to handle them properly. Let's take a look at how to do it.

What are Alert Dialogs in Playwright?

Alert dialogs refer to the popup modal windows displayed by the browser during webpage interaction. These are created via JavaScript using:

  • window.alert() – Shows an alert message
  • window.confirm() – Displays confirm (yes/no) dialog
  • window.prompt() – Prompts user to enter text

When any of these are called, the browser will halt execution and display the modal dialog, waiting for user action. In Playwright scripts, we want to detect when an alert pops up and programmatically handle it by:

  • Closing the alert
  • Clicking OK/Cancel on confirms
  • Entering text for prompts

This allows the script to continue past the alert instead of hanging indefinitely, waiting for non-existent user input.

Why Handle Alerts in Playwright?

Here are some key reasons you'll want to handle alerts in Playwright properly:

1. Prevent Script Blocking

The main reason is to prevent the script from blocking.

Without handling, the script will pause execution and wait forever at the alert. By detecting and closing/responding to the alert, we allow the script to continue.

2. Verify Alert Contents

Alert handling also lets you read and verify the alert message text.

For example, you may want to confirm a success alert appears after submitting a form. Checking the alert text allows validating it.

3. Click Confirmation Dialogs

For window.confirm() popups, programmatically clicking OK or Cancel allows testing both code paths.

Your script can first run through clicking OK, then again clicking Cancel to cover all scenarios.

4. Enter Text for Prompts

When testing window.prompt() you can enter expected text to cover different user inputs.

How to Handle Alerts in Playwright

Playwright provides a straightforward API for handling alerts through the page.on('dialog') event handler. To use it:

  1. Attach a callback function to the dialog event
  2. Inside the callback, handle the dialog using dialog.accept()/dismiss()/text()

Here is an example skeleton:

page.on('dialog', handleDialog);

function handleDialog(dialog) {
  // Handle dialog
}

This will invoke handleDialog() each time a dialog appears on the page. Inside the callback, we can handle different dialog types:

Handling Alert Messages

function handleDialog(dialog) {
  console.log(dialog.message());
  dialog.dismiss(); 
}
  • dialog.message() gets the alert text
  • dialog.dismiss() clicks OK/close

Handling Confirm Dialogs

function handleDialog(dialog) {
  if (dialog.message() === 'Confirm Delete') {
    dialog.accept(); // Click OK
  } else {
    dialog.dismiss(); // Click Cancel
  }
}
  • Check dialog.message() to identify the confirm
  • Call dialog.accept() to click OK
  • dialog.dismiss() for clicking Cancel

Entering Text for Prompts

function handleDialog(dialog) {
  if (dialog.type() === 'prompt') {
    dialog.accept('Expected Text');
  } else {
    dialog.dismiss();
  }
}
  • Check dialog.type() for the prompt dialog type
  • Pass text to dialog.accept() to enter it

This covers the basics of handling alerts. Next, we'll go over some best practices.

Best Practices for Alert Handling

Here are some tips for smoothly handling alerts in your scripts:

Use a Single Handler

Define one reusable top-level dialog handler instead of repeating the logic. For example:

// dialog.js
export default async function handleDialog(dialog) {
  // shared logic
}

// script.js 
import handleDialog from './dialogs';

page.on('dialog', handleDialog);

This avoids duplication and makes alert handling consistent across tests.

Isolate UI Logic

Keep the alert handling logic isolated from your test code. For example, call a separate method from your test:

// tests.js
test('submit form', async ({page}) => {
  // interact with page
  
  await handleFormSubmitAlert(page);
  
  // assert on results
});

// alerts.js
export async function handleFormSubmitAlert(page) {
  page.on('dialog', handleDialog);
  // ...
}

This separates the UI logic from the test and improves maintainability.

Add Context-Specific Logic

While reusing a single top-level handler, add any context-specific logic within the handler:

function handleDialog(dialog) {

  if (isSubmitAlert(dialog)) {
    // handle submit alert
  } else if (isDeleteAlert(dialog)) {
    // handle delete alert
  } else {
   // default handling  
  }

}

This keeps the alert handling centralized while allowing custom logic per dialog.

Disable When Not Needed

Dialog handling introduces some overhead. Avoid having it enabled for every test run by:

// Enable for specific test
test('alert test', async ({page}) => {
  page.on('dialog', handleDialog); 
  
  // steps to cause alert

});

// Or conditionally enable 
if (handleAlerts) { 
  page.on('dialog', handleDialog);
}

This prevents unnecessary processing for tests not requiring alerts. By following these best practices, you can implement robust alert handling in your scripts. Next, we'll look at some common issues that may come up.

Common Issues and Solutions

Here are some common problems that may occur with Playwright alert handling:

Alerts Not Getting Handled

If alerts in the browser are not getting handled by your script, the most common reasons are:

  • The page.on('dialog') handler wasn't added
  • It was added after the alert occurs on the page
  • The page instance changed, and the handler needs to be reattached

Double-check page.on('dialog') is called early in your test code before any alerts could appear on the page. Reattach it after any page navigations or new page instantiations.

Can't Identify Alert Type

To handle prompts and confirm dialogs, we need to identify the alert type. This can be done via:

  • dialog.type() – Returns 'alert''confirm''prompt'
  • dialog.message() – Text indicates alert type
  • dialog.defaultValue() – Shows default text for prompt

If these aren't working, double-check for an upstream Playwright issue. Sometimes browser versions and webpages can trigger unexpected alert behavior.

Prompt Text Not Entered

When trying to enter text with dialog.accept('text') for a prompt, if the input is not appearing in the browser, there are a few possible issues:

  • The dialog type is not actually a 'prompt'. Double check with dialog.type().
  • There is a race condition where the prompt closes before the text can be entered. Slow down the script steps leading up to the prompt.
  • An exception is swallowing the error, which would reveal the prompt is not interacting as expected.

Adding some logging and slowing down interactions around the prompt can help troubleshoot unexpected behavior.

Alerts During Navigation

If a page navigation triggers an alert, it can cause tricky behavior:

  • The alert appears in the previous page context, not the new one
  • The alert may get dismissed automatically without handling

To fix, manually dismiss any alerts before navigating:

await page.dismissAlerts();
await page.goto(url);

And reattach the dialog handler after navigating to the new page. With a few tweaks, these common issues can typically be addressed when handling alerts in Playwright.

Alert Handling Recipes

To put it all together, here are some examples of handling different alert scenarios in Playwright:

Close Alert After Form Submission

// Handle alert after form submit
const handleSubmitAlert = async page => {
  await page.on('dialog', async dialog => {
    console.log(dialog.message());
    await dialog.dismiss();
  });
}

await handleSubmitAlert(page);

await page.fill('#email', '[email protected]');
await page.click('#submitButton');

This handles a generic alert that appears after submitting a form. We attach the dialog handler, log the message, and then dismiss the alert.

Handle Confirm Before Deleting

const handleDeleteConfirm = async page => {
  await page.on('dialog', async dialog => {
    if (dialog.type() === 'confirm') {
      await dialog.accept(); 
    } else {
      await dialog.dismiss();
    }
  });
}

await handleDeleteConfirm(page);

await page.click('#deleteButton');

For a window.confirm() before deleting, we check the dialog type, and then call dialog.accept() to click OK.

Enter Text for Signup Prompt

const handleSignupPrompt = async page => {
  await page.on('dialog', async dialog => {
   if (dialog.type() === 'prompt') {
      await dialog.accept('MyExpectedText');
    } else {
      await dialog.dismiss();  
    }
  });
}

await handleSignupPrompt(page);

await page.click('#signup');

When a window.prompt() appears during signup, we verify it's a prompt, then pass our expected string to dialog.accept() to enter it.

Summary

Handling browser alerts is a key technique for stable automation with Playwright. By listening to the dialog event and programmatically handling dialogs, we can seamlessly interact with websites that use alerts and prompts.

The examples above demonstrate handling common cases like closing alerts, clicking confirm, and entering prompt text. Following the best practices will lead to robust alert handling in your tests. I hope this guide provides a comprehensive overview of how to smoothly handle browser dialog popups in Playwright using its built-in APIs!

John Rooney

John Rooney

John Watson Rooney, a self-taught Python developer and content creator with a focus on web scraping, APIs, and automation. I love sharing my knowledge and expertise through my YouTube channel, My channel caters to all levels of developers, from beginners looking to get started in web scraping to experienced programmers seeking to advance their skills with modern techniques. I have worked in the e-commerce sector for many years, gaining extensive real-world experience in data handling, API integrations, and project management. I am passionate about teaching others and simplifying complex concepts to make them more accessible to a wider audience. In addition to my YouTube channel, I also maintain a personal website where I share my coding projects and other related content.

We will be happy to hear your thoughts

      Leave a reply

      Proxy-Zone
      Compare items
      • Total (0)
      Compare
      0