How to Manage Unexpected Popups in Playwright Testing
Newsletter Signups, Discount Offers, and Survey and Live Chat Invitations

Sometimes when you're testing a website, things don't go as planned. You might be filling out a form or clicking a button, and suddenly — boom — a popup appears out of nowhere. It could be a newsletter signup, a discount offer when you're about to leave the page, a survey, or even a live chat window asking if you need help. These overlays can block the main content and interrupt your test flow.
The tricky part? These popups don’t always show up. Sometimes they appear, sometimes they don’t. That makes it hard to write stable tests because you can’t predict when they’ll show up.
That’s where Playwright’s special function comes in — addLocatorHandler.
This function lets you set up a handler that watches for a specific popup or overlay. If it appears, the handler kicks in and takes care of it (like clicking the close button), so your test can continue without getting stuck.
In this blog, I’ll show you how to use this feature to handle those unexpected overlays and keep your tests running smoothly.
Demo:
let me show you a demo. I have created a very simple site, and which might show subscribe newsletter popup 60% of the time.
To launch a site locally, follow these steps:
- save this file with .html extension
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Newsletter Popup Demo</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
overflow: auto;
}
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.6);
z-index: 1000;
justify-content: center;
align-items: center;
}
.modal {
background: white;
padding: 30px;
border-radius: 10px;
width: 300px;
text-align: center;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
position: relative;
}
.modal input[type="email"] {
width: 90%;
padding: 10px;
margin: 10px 0;
}
.modal button {
padding: 10px 20px;
margin-top: 10px;
}
.close-btn {
position: absolute;
top: 10px;
right: 15px;
font-size: 20px;
font-weight: bold;
color: #999;
cursor: pointer;
}
.close-btn:hover {
color: #333;
}
.content {
padding: 20px;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div class="overlay" id="newsletterOverlay">
<div class="modal">
<span class="close-btn" onclick="closeOverlay()">×</span>
<h2>Subscribe to our Newsletter</h2>
<p>Get the latest updates and offers!</p>
<input type="email" placeholder="Enter your email" />
<br />
<button onclick="subscribe()">Subscribe</button>
</div>
</div>
<div class="content" id="mainContent">
<h1>Welcome to Our Awesome Site!</h1>
<p>Enjoy browsing our content. You might get a surprise!</p>
<div><label>Your name:</label><input type="text" id="name" /></div>
<br />
<div><label>Your age:</label><input type="number" id="age" /></div>
<br />
<div>
<label>Your profession:</label><input type="text" id="profession" />
</div>
<br />
<div><label>Your city:</label><input type="text" id="city" /></div>
<br />
<div><label>Your state:</label><input type="text" id="state" /></div>
<br />
<div><label>Your country:</label><input type="text" id="country" /></div>
<br />
<div>
<label>Your continent:</label><input type="text" id="continent" />
</div>
<br />
</div>
<script>
function showOverlay() {
const shouldShow = Math.random() < 0.5; // 50% chance
if (shouldShow) {
document.getElementById("newsletterOverlay").style.display = "flex";
document.getElementById("mainContent").classList.add("hidden");
document.body.style.overflow = "hidden";
}
}
function closeOverlay() {
document.getElementById("newsletterOverlay").style.display = "none";
showForm();
}
function subscribe() {
alert("Thanks for subscribing!");
closeOverlay();
}
function showForm() {
document.getElementById("mainContent").classList.remove("hidden");
document.body.style.overflow = "auto";
}
window.onload = function () {
showForm(); // Show form initially
setTimeout(showOverlay, 2000); // Show popup after 2 seconds
};
</script>
</body>
</html>
- run the .html file with live server in vscode

- Copy the url. Same should be used inside the page.goto() method

Playwright code:
Logic is simple
Some popups might appear (the popup locator is provided to Playwright). If this locator appears, then do the following:
We have set up a handler to detect if the given locator appears on the screen using the addLocatorHandler function. then do this action mentioned in the async function
Then it fills data in each textbox, and I have set a 1-second timeout for each fill. This allows time for the newsletter popup to appear; otherwise, the automation might finish before the popup shows up.
import { test } from "@playwright/test";
test("custom site with overlay handler", async ({ page }) => {
// Register a handler to close the newsletter popup if it appears
await page.addLocatorHandler(
page.getByText("Subscribe to our Newsletter"),
async () => {
await page.locator("span.close-btn").click();
}
);
// Proceed with the test
await page.goto("http://127.0.0.1:5501/over.html");
// you have to change this url. steps are available in below
await page.locator("#name").fill("Your Name");
await page.waitForTimeout(1000);
//given timeout otherwise test will be completed before the overlay appears
await page.locator("#age").fill("30");
await page.waitForTimeout(1000);
await page.locator("#profession").fill("Software Engineer");
await page.waitForTimeout(1000);
await page.locator("#city").fill("Bangalore");
await page.waitForTimeout(1000);
await page.locator("#state").fill("Karnataka");
await page.waitForTimeout(1000);
await page.locator("#country").fill("India");
await page.waitForTimeout(1000);
await page.locator("#continent").fill("Asia");
});
Conclusion:
Dealing with unexpected popups during test automation can be frustrating, especially when they don’t always show up. But with Playwright’s addLocatorHandler, we now have a clean way to handle these overlays without breaking our tests. It helps us keep our scripts smooth and focused on the actual task, even when something tries to interrupt. Try it out in your tests and get rid of all flaky tests.



