{"id":9010,"date":"2026-02-06T18:10:00","date_gmt":"2026-02-06T12:40:00","guid":{"rendered":"https:\/\/www.testleaf.com\/blog\/?p=9010"},"modified":"2026-02-06T18:10:35","modified_gmt":"2026-02-06T12:40:35","slug":"playwright-ai-assisted-pop-up-handling-recipes","status":"publish","type":"post","link":"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/","title":{"rendered":"Playwright + AI-Assisted Pop-Up Handling Recipes"},"content":{"rendered":"<div style=\"margin-top: 0px; margin-bottom: 0px;\" class=\"sharethis-inline-share-buttons\" ><\/div><!--[if lt IE 9]><script>document.createElement('audio');<\/script><![endif]-->\n<audio class=\"wp-audio-shortcode\" id=\"audio-9010-1\" preload=\"none\" style=\"width: 100%;\" controls=\"controls\"><source type=\"audio\/mpeg\" src=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/Playwright-AI-Assisted-Pop-Up-Handling-Recipes.mp3?_=1\" \/><a href=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/Playwright-AI-Assisted-Pop-Up-Handling-Recipes.mp3\">https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/Playwright-AI-Assisted-Pop-Up-Handling-Recipes.mp3<\/a><\/audio>\n<p>&nbsp;<\/p>\n<p>If your Playwright suite is \u201cgreen locally, red on CI,\u201d here\u2019s the uncomfortable truth:<\/p>\n<p><strong>Your tests aren\u2019t flaky. Your popup strategy is.<\/strong><\/p>\n<p>Cookie banners, newsletter modals, chat widgets, \u201crate your experience\u201d overlays, payment windows, login providers\u2014popups are not edge cases anymore. They\u2019re part of the product.<\/p>\n<p>And when we treat them like surprises, we create the real enemy of <a href=\"https:\/\/www.testleaf.com\/blog\/which-is-better-to-learn-ui-automation-or-api-automation\/\">UI automation<\/a>: <strong>loss of trust<\/strong>.<\/p>\n<p>This isn\u2019t a niche problem. A survey of developers found <strong>59%<\/strong> deal with flaky tests monthly\/weekly\/daily. And in a separate developer survey, people reported they\u2019re less worried about rerun compute cost and <strong>more worried about losing trust in test outcomes<\/strong>.<\/p>\n<p><strong data-start=\"869\" data-end=\"899\">Where teams struggle most:<\/strong> Pop-ups often appear only under specific conditions\u2014CI runners, geo-based cookie banners, A\/B experiments, and first-time user flows (common with India\/global traffic). That\u2019s why your approach needs a <strong data-start=\"1102\" data-end=\"1121\">state checklist<\/strong> (cookies, storage state, experiments, locale) before you trust failures.<\/p>\n<p>So if we want reliable automation in 2026 and beyond, we need a better model than \u201cadd waits.\u201d<\/p>\n<h2 data-start=\"753\" data-end=\"781\"><span class=\"ez-toc-section\" id=\"Key_Takeaways\"><\/span><strong>Key Takeaways\u00a0<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2><div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Key_Takeaways\" >Key Takeaways\u00a0<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#The_big_idea_Popups_are_interrupt_contracts\" >The big idea: Popups are interrupt contracts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#A_quick_framework_you_can_reuse_ICE\" >A quick framework you can reuse: ICE<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#The_7_recipes_Playwright-native_AI-assisted\" >The 7 recipes (Playwright-native + AI-assisted)<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Recipe_1_Native_dialogs_alertconfirmprompt\" >Recipe 1: Native dialogs (alert\/confirm\/prompt)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Recipe_2_New_tab_popup_window_opened_by_click\" >Recipe 2: New tab \/ popup window opened by click<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Recipe_3_Overlays_that_intercept_clicks_the_hidden_flake_factory\" >Recipe 3: Overlays that intercept clicks (the hidden flake factory)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Recipe_4_%E2%80%9CSometimes_it_appears%E2%80%9D_AB_tests_geo_cookies\" >Recipe 4: \u201cSometimes it appears\u201d (A\/B tests, geo, cookies)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Recipe_5_Permissions_prompts\" >Recipe 5: Permissions prompts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Recipe_6_Modal_%E2%86%92_confirm_%E2%86%92_download_combined_flows\" >Recipe 6: Modal \u2192 confirm \u2192 download (combined flows)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Recipe_7_Make_flakiness_visible_with_traces_retries_not_%E2%80%9Cmore_retries%E2%80%9D\" >Recipe 7: Make flakiness visible with traces + retries (not \u201cmore retries\u201d)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Where_AI_helps%E2%80%94and_where_it_hurts\" >Where AI helps\u2014and where it hurts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#Starter_kit_a_clean_team-scale_approach\" >Starter kit: a clean, team-scale approach<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#FAQS\" >FAQ\u2019S<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#1_Why_does_Playwright_click_timeout_when_a_modal_is_present\" >1. Why does Playwright click timeout when a modal is present?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#2_How_do_I_handle_a_popup_windownew_tab_in_Playwright\" >2. How do I handle a popup window\/new tab in Playwright?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#3_How_do_I_handle_JavaScript_dialogs\" >3. How do I handle JavaScript dialogs?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#4_How_do_I_debug_CI-only_popup_failures\" >4. How do I debug CI-only popup failures?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/#5_A_reliable_Playwright_suite_is_a_set_of_explicit_interrupt_contracts\" >5. A reliable Playwright suite is a set of explicit interrupt contracts.<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n\n<ul>\n<li data-start=\"784\" data-end=\"951\">Popups aren\u2019t \u201crandom flake\u201d\u2014they expose missing <strong data-start=\"833\" data-end=\"856\">interrupt contracts<\/strong> (dialogs, overlays, new tabs, permissions, downloads).<\/li>\n<li>Use Playwright events (popup\/dialog\/download) + centralized utilities to make handling repeatable and reviewable.<\/li>\n<li>Make <a href=\"https:\/\/www.testleaf.com\/blog\/self-healing-playwright-login-session-failures\/\">failures<\/a> diagnosable: enable <strong data-start=\"1144\" data-end=\"1168\">trace on first retry<\/strong> and use AI only for triage\/suggestions\u2014not silent auto-fixes.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"The_big_idea_Popups_are_interrupt_contracts\"><\/span><strong>The big idea: Popups are <em>interrupt contracts<\/em><\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Popups don\u2019t \u201cbreak tests.\u201d They expose missing contracts.<\/p>\n<p>A popup is an <strong>interrupt<\/strong>: it changes what the user can do <strong>right now<\/strong>.<br \/>\nA stable test suite needs an <strong>explicit contract<\/strong> for each interrupt category:<\/p>\n<ul>\n<li><strong>Native browser dialogs<\/strong>: alert\/confirm\/prompt\/beforeunload<\/li>\n<li><strong>New page\/tab popups<\/strong>: links or flows that open a new window<\/li>\n<li><strong>In-page overlays<\/strong>: cookie banner, newsletter modal, chat widget<\/li>\n<li><strong>Policy\/permission prompts<\/strong>: notifications, geolocation, camera\/mic<\/li>\n<li><strong>Combined flows<\/strong>: modal \u2192 confirm \u2192 download<\/li>\n<\/ul>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-9014\" src=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/5-categories-every-suite-must-handle.webp\" alt=\"5 categories every suite must handle\" width=\"1920\" height=\"1080\" srcset=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/5-categories-every-suite-must-handle.webp 1920w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/5-categories-every-suite-must-handle-300x169.webp 300w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/5-categories-every-suite-must-handle-1024x576.webp 1024w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/5-categories-every-suite-must-handle-768x432.webp 768w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/5-categories-every-suite-must-handle-1536x864.webp 1536w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/5-categories-every-suite-must-handle-150x84.webp 150w\" sizes=\"(max-width: 1920px) 100vw, 1920px\" \/><\/p>\n<p>Playwright already gives you strong primitives for each one. Your job is to turn those primitives into repeatable \u201crecipes.\u201d Then AI can help\u2014<strong>not by auto-fixing tests<\/strong>, but by accelerating discovery and triage.<\/p>\n<p><strong>Additional Resources:<\/strong> <a href=\"https:\/\/www.testleaf.com\/blog\/2025-top-automation-testing-infosys-interview-questions-with-expert-answers-from-testleaf-for-2-to-5-years-experience\/\">Automation testing interview questions<\/a><\/p>\n<h2><span class=\"ez-toc-section\" id=\"A_quick_framework_you_can_reuse_ICE\"><\/span><strong>A quick <a href=\"https:\/\/www.testleaf.com\/blog\/top-20-automation-testing-frameworks-in-2025-features-pros-best-use-cases\/\">framework<\/a> you can reuse: ICE<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>When an interrupt appears, think <strong>ICE<\/strong>:<\/p>\n<ol>\n<li><strong>Identify<\/strong> the interrupt type (overlay? new tab? dialog?)<\/li>\n<li><strong>Capture<\/strong> it deterministically (events\/handlers\u2014not sleeps)<\/li>\n<li><strong>Eliminate<\/strong> repetition (centralize into one helper\/util)<\/li>\n<\/ol>\n<p>This is how teams stop \u201cfixing popups\u201d and start <strong>engineering reliability<\/strong>.<\/p>\n<h1><span class=\"ez-toc-section\" id=\"The_7_recipes_Playwright-native_AI-assisted\"><\/span><strong>The 7 recipes (Playwright-native + AI-assisted)<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h1>\n<h2><span class=\"ez-toc-section\" id=\"Recipe_1_Native_dialogs_alertconfirmprompt\"><\/span><strong>Recipe 1: Native dialogs (alert\/confirm\/prompt)<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><strong>Symptom:<\/strong> your click hangs or the test freezes after an action.<br \/>\n<strong>Root cause:<\/strong> dialogs are modal; if you add a listener, you must handle it.<\/p>\n<p>Playwright warns clearly: if you attach a page.on(&#8216;dialog&#8217;) listener, it <strong>must<\/strong> accept() or dismiss() or your action can stall.<\/p>\n<p><strong>Playwright-native fix (pattern):<\/strong><\/p>\n<pre>page.once('dialog', async (dialog) =&gt; {\u00a0 \r\n\r\n\/\/ Rule-based decisions only:\u00a0 \r\n\r\nconst msg = dialog.message();\u00a0 \r\n\r\nif (\/delete|remove|are you sure\/i.test(msg)) await dialog.accept();\u00a0 \r\n\r\nelse await dialog.dismiss();\r\n\r\n});\u00a0\r\n\r\nawait page.getByRole('button', { name: \/delete\/i }).click();<\/pre>\n<p><strong>AI assist (safe):<\/strong><\/p>\n<ul>\n<li>classify the dialog message and suggest a rule (\u201caccept delete confirmations, dismiss leave-site prompts\u201d)<\/li>\n<\/ul>\n<p><strong>Guardrail:<\/strong><\/p>\n<ul>\n<li>never let AI decide silently; store decisions as deterministic rules.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Recipe_2_New_tab_popup_window_opened_by_click\"><\/span><strong>Recipe 2: New tab \/ <a href=\"https:\/\/www.testleaf.com\/blog\/your-playwright-tests-fail-for-this-reason-frames-popups-downloads\/\">popup<\/a> window opened by click<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><strong>Symptom:<\/strong> assertions fail because your test keeps running on the original page.<br \/>\n<strong>Root cause:<\/strong> the app opened a new page; you didn\u2019t capture it.<\/p>\n<p>Playwright\u2019s event docs show the key idea: start waiting for the popup <strong>before<\/strong> clicking.<\/p>\n<p><strong>Playwright-native fix:<\/strong><\/p>\n<pre>const popupPromise = page.waitForEvent('popup'); \/\/ no await\r\n\r\nawait page.getByRole('button', { name: \/pay now\/i }).click();\u00a0\r\n\r\nconst popup = await popupPromise;\r\n\r\nawait popup.waitForLoadState();\r\n\r\n\/\/ Continue inside the popup...<\/pre>\n<p><strong>AI assist (safe):<\/strong><\/p>\n<ul>\n<li>read the trace and flag: \u201cclick triggered a popup; test continued on old page\u201d<\/li>\n<li>propose the exact wrapper pattern above<\/li>\n<\/ul>\n<p><strong>Guardrail:<\/strong><\/p>\n<ul>\n<li>do not \u201cre-find\u201d selectors blindly on the old page as a workaround.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Recipe_3_Overlays_that_intercept_clicks_the_hidden_flake_factory\"><\/span><strong>Recipe 3: Overlays that intercept clicks (the hidden flake factory)<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><strong>Symptom:<\/strong> locator.click() times out; logs suggest element is visible but not clickable.<br \/>\n<strong>Root cause:<\/strong> overlays intercept pointer events.<\/p>\n<p><a href=\"https:\/\/www.testleaf.com\/blog\/playwright-storage-state-reuse-login-multiple-users\/\">Playwright\u2019s<\/a> actionability checks include <strong>Receives Events<\/strong>\u2014it verifies nothing (like an overlay) captures the click at the action point.<\/p>\n<p><strong>Playwright-native fix:<\/strong> build a <strong>central overlay cleanup helper<\/strong> and call it at predictable points (after navigation, before critical actions).<\/p>\n<pre>export async function closeCommonOverlays(page: Page) {\u00a0 \r\n\r\n\/\/ Cookie banners\u00a0 \r\n\r\nconst cookie = page.getByRole('dialog', { name: \/cookie\/i });\u00a0 \r\n\r\nif (await cookie.isVisible().catch(() =&gt; false)) {\u00a0\u00a0\u00a0 \r\n\r\nawait cookie.getByRole('button', { name: \/accept|agree|ok\/i }).click();\u00a0\r\n\r\n }\u00a0\u00a0 \r\n\r\n\/\/ Newsletter \/ promo\u00a0 \r\n\r\nconst promo = page.getByRole('dialog', { name: \/newsletter|offer|promo\/i });\u00a0\r\n\r\n if (await promo.isVisible().catch(() =&gt; false)) {\u00a0\u00a0\u00a0 \r\n\r\nawait promo.getByRole('button', { name: \/close|no thanks|dismiss\/i }).click();\u00a0 }\u00a0\u00a0 \r\n\r\n\/\/ Escape often closes modals (when supported)\u00a0 \r\n\r\nawait page.keyboard.press('Escape').catch(() =&gt; {});}<\/pre>\n<p><strong>AI assist (safe):<\/strong><\/p>\n<ul>\n<li>suggest candidate selectors based on accessible roles\/names<\/li>\n<li>cluster repeated failures across many runs: \u201csame banner blocked 23 tests\u201d<\/li>\n<\/ul>\n<p><strong>Guardrail:<\/strong><\/p>\n<ul>\n<li>never accept \u201cclick at coordinates\u201d as a fix (it\u2019s brittle and unreviewable).<\/li>\n<\/ul>\n<p><a href=\"https:\/\/playwright-webinar.testleaf.com\/?utm_source=Playwright_Webinar&amp;utm_medium=Organic&amp;utm_campaign=Playwright_Webinar_blog\"><img decoding=\"async\" class=\"aligncenter wp-image-7702 size-full\" src=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/11\/Playwright-Masterclass.png\" alt=\"Playwright Masterclass\" width=\"2048\" height=\"512\" srcset=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/11\/Playwright-Masterclass.png 2048w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/11\/Playwright-Masterclass-300x75.png 300w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/11\/Playwright-Masterclass-1024x256.png 1024w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/11\/Playwright-Masterclass-768x192.png 768w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/11\/Playwright-Masterclass-1536x384.png 1536w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/11\/Playwright-Masterclass-150x38.png 150w\" sizes=\"(max-width: 2048px) 100vw, 2048px\" \/><\/a><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Recipe_4_%E2%80%9CSometimes_it_appears%E2%80%9D_AB_tests_geo_cookies\"><\/span><strong>Recipe 4: \u201cSometimes it appears\u201d (A\/B tests, geo, cookies)<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><strong>Symptom:<\/strong> passes in dev, fails in staging; fails only on CI; fails only on rerun.<br \/>\n<strong>Root cause:<\/strong> your user state is inconsistent.<\/p>\n<p>This isn\u2019t a locator problem. It\u2019s an <strong>environment contract<\/strong> problem:<\/p>\n<ul>\n<li>cookies differ<\/li>\n<li>experiments differ<\/li>\n<li>first-time user flows differ<\/li>\n<li>data seeds differ<\/li>\n<\/ul>\n<p><strong>Playwright-native fix:<\/strong><\/p>\n<ul>\n<li>make state explicit: reset storage, seed the account, stabilize feature flags (where possible)<\/li>\n<li>isolate contexts per test to reduce cross-test leakage<\/li>\n<\/ul>\n<p>Playwright contexts are designed for isolation.<\/p>\n<p><strong>AI assist (safe):<\/strong><\/p>\n<ul>\n<li>generate a \u201cstate <a href=\"https:\/\/www.testleaf.com\/blog\/a-testers-checklist-for-test-automation-in-2025\/\">checklist<\/a>\u201d from failure patterns (first-time modal, new geo banner, etc.)<\/li>\n<\/ul>\n<p><strong>Guardrail:<\/strong><\/p>\n<ul>\n<li>don\u2019t hide state issues by increasing timeouts.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Recipe_5_Permissions_prompts\"><\/span><strong>Recipe 5: Permissions prompts<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><strong>Symptom:<\/strong> flaky first-run flows around notifications\/geolocation.<br \/>\n<strong>Root cause:<\/strong> permissions are not UI; they\u2019re configuration.<\/p>\n<p><strong>Playwright-native fix:<\/strong><\/p>\n<ul>\n<li>define permissions at the browser context level (deny by default; allow only when test requires it)<\/li>\n<\/ul>\n<p>This keeps your tests deterministic and auditable.<\/p>\n<p><strong>AI assist (safe):<\/strong><\/p>\n<ul>\n<li>highlight tests that depend on real-world state (\u201cthis flow assumes real location\u201d)<\/li>\n<\/ul>\n<p><strong>Guardrail:<\/strong><\/p>\n<ul>\n<li>do not let AI \u201capprove\u201d permission prompts inside the UI as a generic step.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Recipe_6_Modal_%E2%86%92_confirm_%E2%86%92_download_combined_flows\"><\/span><strong>Recipe 6: Modal \u2192 confirm \u2192 download (combined flows)<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Your draft has the right instinct here: treat the whole thing as one recipe. (In Playwright, downloads are first-class events.)<\/p>\n<p><strong>Playwright-native fix:<\/strong><\/p>\n<pre>export async function exportReport(page: Page) {\u00a0 \r\n\r\nconst downloadPromise = page.waitForEvent('download'); \/\/ no await\u00a0\u00a0 \r\n\r\nawait page.getByRole('button', { name: \/export report\/i }).click();\u00a0\u00a0 \r\n\r\nconst confirm = page.getByRole('dialog', { name: \/export\/i });\u00a0 \r\n\r\nif (await confirm.isVisible().catch(() =&gt; false)) {\u00a0\u00a0\u00a0 await confirm.getByRole('button', { name: \/continue|ok\/i }).click();\u00a0 \r\n\r\n}\u00a0\u00a0 \r\n\r\nconst download = await downloadPromise;\u00a0 \r\n\r\nawait download.saveAs(`downloads\/${download.suggestedFilename()}`);\r\n\r\n}<\/pre>\n<p><strong>AI assist (safe):<\/strong><\/p>\n<ul>\n<li>detect repeated \u201cexport flow\u201d failures and recommend centralizing into a utility<\/li>\n<\/ul>\n<p><strong>Guardrail:<\/strong><\/p>\n<ul>\n<li>keep file naming and storage predictable; don\u2019t let AI improvise file paths in CI.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Recipe_7_Make_flakiness_visible_with_traces_retries_not_%E2%80%9Cmore_retries%E2%80%9D\"><\/span><strong>Recipe 7: Make <a href=\"https:\/\/www.testleaf.com\/blog\/is-playwright-automation-the-end-of-flaky-tests-heres-the-truth\/\">flakiness<\/a> visible with traces + retries (not \u201cmore retries\u201d)<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Retries are useful\u2014but only as a <strong>diagnostic signal<\/strong>. Playwright supports retries and also recommends recording traces on CI \u201con-first-retry\u201d to debug failures without tracing every passing test.<\/p>\n<p><strong>Playwright-native config pattern:<\/strong><\/p>\n<ul>\n<li>retries on CI<\/li>\n<li>trace on first retry<\/li>\n<\/ul>\n<p>This turns \u201crandom failure\u201d into \u201cinspectable evidence.\u201d<\/p>\n<p><strong>AI assist (high value):<\/strong><\/p>\n<ul>\n<li>summarize a trace into: <em>What interrupt happened? Which recipe applies? What minimal deterministic fix is suggested?<\/em><\/li>\n<li>cluster failure tags over time (e.g., POPUP_BLOCKED_VIEW across multiple tests)<\/li>\n<\/ul>\n<p><strong>Guardrail:<\/strong><\/p>\n<ul>\n<li>AI summarizes and suggests; humans approve and codify.<\/li>\n<\/ul>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-9015\" src=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/7-playwright-pop-up-handling-recipes.webp\" alt=\"7 playwright pop-up handling recipes\" width=\"1920\" height=\"1080\" srcset=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/7-playwright-pop-up-handling-recipes.webp 1920w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/7-playwright-pop-up-handling-recipes-300x169.webp 300w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/7-playwright-pop-up-handling-recipes-1024x576.webp 1024w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/7-playwright-pop-up-handling-recipes-768x432.webp 768w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/7-playwright-pop-up-handling-recipes-1536x864.webp 1536w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/7-playwright-pop-up-handling-recipes-150x84.webp 150w\" sizes=\"(max-width: 1920px) 100vw, 1920px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Where_AI_helps%E2%80%94and_where_it_hurts\"><\/span><strong>Where AI helps\u2014and where it hurts<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>A mistake teams make in 2026: using AI to <em>generate fixes<\/em> faster than they can review them.<\/p>\n<p>That\u2019s risky even in normal development. For example, Veracode reported <strong>45%<\/strong> of AI-generated code samples failed security tests and introduced vulnerabilities aligned with OWASP <a href=\"https:\/\/www.testleaf.com\/blog\/top-10-test-strategy-optimization-techniques-for-2025\/\">Top 10 categories<\/a>.<\/p>\n<p>UI automation \u201cauto-fixes\u201d can have a similar shape:<\/p>\n<ul>\n<li>they make the suite green<\/li>\n<li>but they reduce correctness, clarity, and auditability<\/li>\n<\/ul>\n<p>So keep AI in the lane where it\u2019s strongest:<\/p>\n<p>\u2705 <strong>Good AI use (evergreen)<\/strong><\/p>\n<ul>\n<li>classify failures using traces\/screenshots<\/li>\n<li>suggest which recipe applies<\/li>\n<li>recommend selector improvements based on accessibility patterns<\/li>\n<li>dedupe and centralize repeated fixes<\/li>\n<\/ul>\n<p>\ud83d\udeab <strong>Bad AI use<\/strong><\/p>\n<ul>\n<li>silent auto-changes to test logic<\/li>\n<li>coordinate-click hacks<\/li>\n<li>\u201cforce everything\u201d patterns<\/li>\n<li>bypassing security\/payment warnings<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9016\" src=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/AI-in-test-automation.webp\" alt=\"AI in test automation\" width=\"1920\" height=\"1080\" srcset=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/AI-in-test-automation.webp 1920w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/AI-in-test-automation-300x169.webp 300w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/AI-in-test-automation-1024x576.webp 1024w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/AI-in-test-automation-768x432.webp 768w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/AI-in-test-automation-1536x864.webp 1536w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2026\/02\/AI-in-test-automation-150x84.webp 150w\" sizes=\"(max-width: 1920px) 100vw, 1920px\" \/><\/p>\n<p><strong>Related Articles:<\/strong> <a href=\"https:\/\/www.testleaf.com\/blog\/playwright-testing-in-2026-the-zero-flake-setup-guide\/\">Playwright testing in 2026<\/a><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Starter_kit_a_clean_team-scale_approach\"><\/span><strong>Starter kit: a clean, team-scale approach<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you want one change that improves reliability fast:<\/p>\n<p><strong>Create a shared \u201cinterrupt contract layer\u201d<\/strong> and call it consistently.<\/p>\n<ul>\n<li>closeCommonOverlays(page) at start of flows<\/li>\n<li>registerDialogPolicy(page) before actions that might trigger dialogs<\/li>\n<li>capturePopupOnClick(page, locator) wrapper for known popup links<\/li>\n<li>exportReport(page) utilities for combined flows<\/li>\n<\/ul>\n<p>When you centralize these, your test files become readable again\u2014and failures become diagnosable.<\/p>\n<p>These patterns work whether your CI runs on <a href=\"https:\/\/github.com\/features\/actions\">GitHub Actions<\/a>, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Azure_DevOps_Server\">Azure DevOps<\/a>, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Jenkins_(software)\">Jenkins<\/a>, or local runners.<\/p>\n<p><strong>Worried about your testing career in 2026?<\/strong><br data-start=\"291\" data-end=\"294\" \/><a href=\"https:\/\/playwright-webinar.testleaf.com\/?utm_source=Playwright_Webinar&amp;utm_medium=Organic&amp;utm_campaign=Playwright_Webinar_blog\"><strong>Become a Playwright + AI engineer in 90 minutes<\/strong><\/a> \u2014 join our Playwright + AI webinar.<\/p>\n<h2><\/h2>\n<h2><span class=\"ez-toc-section\" id=\"FAQS\"><\/span><strong>FAQ\u2019S<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h2><span class=\"ez-toc-section\" id=\"1_Why_does_Playwright_click_timeout_when_a_modal_is_present\"><\/span><strong>1. Why does Playwright click timeout when a modal is present?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Because Playwright checks actionability, including whether the element <strong>receives events<\/strong> and isn\u2019t covered by an overlay.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"2_How_do_I_handle_a_popup_windownew_tab_in_Playwright\"><\/span><strong>2. How do I handle a popup window\/new tab in Playwright?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Use page.waitForEvent(&#8216;popup&#8217;) and start waiting before the click.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"3_How_do_I_handle_JavaScript_dialogs\"><\/span><strong>3. How do I handle JavaScript dialogs?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Use page.on(&#8216;dialog&#8217;), and ensure you accept() or dismiss()\u2014otherwise actions can stall.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"4_How_do_I_debug_CI-only_popup_failures\"><\/span><strong>4. How do I debug CI-only popup failures?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Record and inspect traces; Playwright\u2019s Trace Viewer is built for CI debugging.<\/p>\n<p>At Testleaf, we teach automation like engineering\u2014not magic.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"5_A_reliable_Playwright_suite_is_a_set_of_explicit_interrupt_contracts\"><\/span><strong>5. A reliable Playwright suite is a set of explicit interrupt contracts.<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>AI doesn\u2019t replace that. It accelerates how quickly you discover the missing contract, and how consistently you turn it into a reusable recipe.<\/p>\n<p>If you adopt one habit this week:<br \/>\n<strong>Every popup failure must end in a centralized recipe\u2014not a one-off patch.<\/strong><\/p>\n<p>&nbsp;<\/p>\n<h5><strong>We Also Provide Training In:<\/strong><\/h5>\n<ul>\n<li><a href=\"https:\/\/www.testleaf.com\/course\/selenium-automation-certification-training-course.html?utm_source=blog_post&amp;utm_medium=Organic&amp;utm_campaign=Blog_Post\"><strong>Advanced Selenium Training<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/www.testleaf.com\/course\/playwright.html?utm_source=blog-post&amp;utm_medium=Organic&amp;utm_campaign=Blog_Post\"><strong>Playwright Training<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/www.testleaf.com\/course\/genai-qa-engineers-training-course.html?utm_source=blog-post&amp;utm_medium=Organic&amp;utm_campaign=Blog_Post\"><strong>Gen AI Training<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/www.testleaf.com\/course\/aws-cloud-architect-certification-training-course.html?utm_source=blog-post&amp;utm_medium=Organic&amp;utm_campaign=Blog_Post\"><strong>AWS Training<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/www.testleaf.com\/course\/rest-api-testing-certification-training-course.html?utm_source=blog-post&amp;utm_medium=Organic&amp;utm_campaign=Blog_Post\"><strong>REST API Training<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/www.testleaf.com\/course\/full-stack-developer-certification-training-course.html?utm_source=blog-post&amp;utm_medium=Organic&amp;utm_campaign=Blog_Post\"><strong>Full Stack Training<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/www.testleaf.com\/course\/appium-mobile-automation-certification-training-course.html?utm_source=blog-post&amp;utm_medium=Organic&amp;utm_campaign=Blog_Post\"><strong>Appium Training<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/www.testleaf.com\/course\/dev-ops-master-certification-training-course.html?utm_source=blog-post&amp;utm_medium=Organic&amp;utm_campaign=Blog_Post\"><strong>DevOps Training<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/www.testleaf.com\/course\/apache-jmeter-testing-training-course.html?utm_source=blog-post&amp;utm_medium=Organic&amp;utm_campaign=Blog_Post\"><strong>JMeter Performance Training<\/strong><\/a><\/li>\n<\/ul>\n<h6><strong>Author\u2019s Bio<\/strong>:<\/h6>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-6744 size-full alignleft\" src=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/09\/Kadhir.png\" sizes=\"(max-width: 200px) 100vw, 200px\" srcset=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/09\/Kadhir.png 200w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/09\/Kadhir-150x150.png 150w, https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/09\/Kadhir-96x96.png 96w\" alt=\"Kadhir\" width=\"200\" height=\"200\" \/><\/p>\n<p>Content Writer at Testleaf, specializing in SEO-driven content for test automation, software development, and cybersecurity. I turn complex technical topics into clear, engaging stories that educate, inspire, and drive digital transformation.<\/p>\n<p><strong>Ezhirkadhir Raja<\/strong><\/p>\n<p>Content Writer \u2013 Testleaf<\/p>\n<p><a href=\"http:\/\/linkedin.com\/in\/ezhirkadhir\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.testleaf.com\/blog\/wp-content\/uploads\/2025\/07\/linkedin.png\" alt=\"LinkedIn Logo\" width=\"28\" height=\"28\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; If your Playwright suite is \u201cgreen locally, red on CI,\u201d here\u2019s the uncomfortable truth: Your tests aren\u2019t flaky. Your popup strategy is. Cookie banners, newsletter modals, chat widgets, \u201crate your experience\u201d overlays, payment windows, login providers\u2014popups are not edge cases anymore. They\u2019re part of the product. And when we treat them like surprises, we &hellip;<\/p>\n<p class=\"read-more\"> <a class=\"\" href=\"https:\/\/www.testleaf.com\/blog\/playwright-ai-assisted-pop-up-handling-recipes\/\"> <span class=\"screen-reader-text\">Playwright + AI-Assisted Pop-Up Handling Recipes<\/span> Read More &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":9013,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"site-sidebar-layout":"default","site-content-layout":"default","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","footnotes":""},"categories":[345],"tags":[729,797,150,998,796,824,996],"class_list":["post-9010","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-playwright","tag-genai","tag-online-playwright-course","tag-playwright","tag-playwright-ai","tag-playwright-course-online","tag-playwright-features","tag-playwright-with-ai"],"acf":[],"aioseo_notices":[],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/posts\/9010","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/comments?post=9010"}],"version-history":[{"count":4,"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/posts\/9010\/revisions"}],"predecessor-version":[{"id":9019,"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/posts\/9010\/revisions\/9019"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/media\/9013"}],"wp:attachment":[{"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/media?parent=9010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/categories?post=9010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.testleaf.com\/blog\/wp-json\/wp\/v2\/tags?post=9010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}