Chapter 09Lesson 04~175 minutes

Alerts, Prompts, Modal Dialogs, and Browser Context Changes: Diagnostics, Failure Modes, and Production Practices

Diagnose dialog failures by preserving the first prompt/modal evidence and identifying the active control plane before changing timeouts, retries, browser state, or application data.

DiagnosticsNoAlertPresentUnexpectedAlertPresentFirst-failure evidenceRecovery

Learning objectives

  • Diagnose NoAlertPresentException and UnexpectedAlertPresentException without masking the original state.
  • Recognize a DOM modal mistaken for a browser alert and prompt input accidentally sent to the page.
  • Identify stale page assumptions after prompt closure and application rerender/navigation.
  • Apply the chapter-wide evidence-first diagnostic sequence to local and remote/Grid failures.
  • Distinguish prompt-policy/browser differences from AUT logic and synchronization defects.
  • Avoid blanket retries, giant sleeps, JavaScript bypasses, restarts, TLS disablement, and production experiments.

1. Failure taxonomy: error name is evidence, not the root cause

The following table organizes the key choices and evidence for Failure taxonomy: error name is evidence, not the root cause. Use it together with the surrounding prose so the rows serve as a comparison aid rather than standalone rules.

Symptom Likely layer First question
NoAlertPresentException prompt presence/timing or wrong control plane Was a browser-native prompt actually open?
UnexpectedAlertPresentException unhandled browser prompt What prompt text/policy/trigger blocked the command?
DOM element not found while overlay visible locator/context/modal lifecycle Is the overlay DOM-based and in the current document/frame?
prompt value missing wrong input target or accept/dismiss branch Was Alert.send_keys() used before acceptance?
post-dialog assertion stale/wrong AUT state changed after closure Did prompt return trigger rerender/navigation?
works locally, fails remotely browser/version/policy/Grid environment What capabilities and prompt evidence differ?

2. Diagnostic sequence to use every time

  1. Preserve first-failure evidence: exception type/message/alert text if available; prompt policy; test step; browser/version.
  2. Confirm Selenium/binding/browser/driver/Grid versions.
  3. Confirm target, environment, and synthetic test data.
  4. Inspect session/capabilities/context: current handle, URL/title when commands are not blocked, returned unhandledPromptBehavior.
  5. Inspect prompt/modal/synchronization state: Alert presence versus DOM dialog visibility.
  6. Inspect AUT/network/browser evidence that explains why the dialog appeared.
  7. Inspect Grid/CI/resource state only when execution is remote.
  8. Apply the least destructive correction and rerun the smallest controlled scenario.

3. Intentionally broken example: ask for an alert that does not exist

This code is broken because the page only opened a DOM modal. The resulting exception is useful: it says the Alert control plane has no active prompt.

from selenium import webdriver
from selenium.common.exceptions import NoAlertPresentException
from selenium.webdriver.common.by import By


driver = webdriver.Chrome()
try:
    driver.get("http://127.0.0.1:8774/index.html")
    driver.find_element(By.ID, "dom-modal-btn").click()
    try:
        print(driver.switch_to.alert.text)  # intentionally wrong API
        raise AssertionError("Expected no browser-native alert")
    except NoAlertPresentException as exc:
        print("diagnostic:", type(exc).__name__)
        modal = driver.find_element(By.ID, "dom-modal")
        print("DOM modal role:", modal.get_attribute("role"))
        print("DOM modal hidden property:", modal.get_property("hidden"))
finally:
    driver.quit()

The repair is not to sleep longer. It is to classify the overlay correctly and use ordinary DOM state.

4. Unexpected prompt: do not erase the blocker before recording it

An unexpected prompt can make a later locator/title/screenshot command fail. With a notify policy, preserve the exception and any reported prompt text. With ignore in a diagnostic session, the prompt remains available for explicit inspection.

from selenium import webdriver
from selenium.common.exceptions import UnexpectedAlertPresentException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

options = Options()
options.unhandled_prompt_behavior = "ignore"
driver = webdriver.Chrome(options=options)
try:
    driver.get("http://127.0.0.1:8774/index.html")
    driver.find_element(By.ID, "alert-btn").click()
    try:
        driver.find_element(By.ID, "page-title")
    except UnexpectedAlertPresentException as exc:
        print("first failure:", type(exc).__name__, exc.alert_text)
        prompt = driver.switch_to.alert
        print("live prompt:", prompt.text)
        prompt.accept()
    assert driver.find_element(By.ID, "native-result").text == "alert:closed"
finally:
    driver.quit()

5. Sending keys to the page instead of the prompt

While a browser-native prompt is open, page interactions are blocked. If the scenario requires prompt text, target the Alert object. Conversely, do not call Alert methods for a DOM modal input.

Target Correct input API Evidence
browser prompt() driver.switch_to.alert.send_keys(...) prompt text + post-accept AUT value
DOM modal input modal.find_element(...).send_keys(...) input value/focus + post-modal AUT value

6. Proceeding without asserting prompt meaning is a diagnostic defect

Consider a test that blindly accepts the first prompt. A certificate warning simulator, destructive confirmation, session-expiry message, or expected “promote” confirm could all be accepted by the same code path. Always assert enough prompt meaning to establish that the intended decision point is being handled.

Security-sensitive rule: never auto-accept real authentication, consent, payment, production-deletion, MFA/CAPTCHA, browser security, or certificate prompts in order to “make the test pass.” Use authorized disposable targets and explicit test contracts.

7. Stale assumptions after the prompt closes

Prompt closure can resume JavaScript that rerenders a component or navigates. A WebElement captured before the prompt may then be stale or semantically outdated. Reacquire state from the current document after the dialog when the application contract allows rerender/navigation.

# Anti-pattern: assume a pre-prompt reference remains valid after application code resumes.
status = driver.find_element(By.ID, "native-result")
driver.find_element(By.ID, "confirm-btn").click()
prompt = driver.switch_to.alert
prompt.accept()

# Safer: reacquire the business-observable state after prompt resolution.
status_after = driver.find_element(By.ID, "native-result")
assert status_after.text == "confirm:true"

8. Browser/policy differences: compare returned state, not UI chrome

Do not diagnose cross-browser prompt problems from screenshot appearance alone. Record browser name/version, returned prompt policy, exception class/alert text, and the same semantic post-dialog assertion. If only one browser differs, reduce to the smallest prompt fixture before changing production code.

9. Troubleshooting shortcuts that hide causes

Do not respond to dialog failures with blanket retries, ten-second sleeps, JavaScript force-clicks behind a modal, browser/Grid restarts, TLS disablement, or experiments against production targets. Those actions either preserve the blocker, destroy evidence, or weaken security.

Performance matters only causally: separate browser/session startup, AUT/network latency, Grid queue time, prompt appearance/handling time, evidence I/O, and retry cost. A prompt that appears instantly but triggers three full browser retries is not “a slow prompt”; it is a poor recovery design.

10. Minimal first-failure evidence packet

  • Selenium/binding version and browser/driver versions.
  • Session ID and returned unhandledPromptBehavior.
  • Step/trigger that preceded the dialog.
  • Exception class/message and alert_text when provided.
  • Prompt text if the prompt remains inspectable.
  • URL/title/DOM modal state once commands are legal again.
  • Screenshot/page source only after considering whether a native prompt blocks capture and whether content requires redaction.
  • Grid/CI node/job identity when remote.

11. Summary and next step

Dialog diagnosis begins by identifying the active control plane and preserving the original evidence. The least destructive repair handles the actual prompt/modal state and verifies the resulting application condition.

Knowledge check

A visible overlay exists, but switch_to.alert raises NoAlertPresentException. What should you inspect next?

Why is retrying the blocked command after UnexpectedAlertPresentException usually wrong?

What evidence should be preserved before accepting an unexpected prompt?

Why reacquire DOM state after a prompt closes?

What is a safer alternative to auto-accepting a real security or identity prompt?

Next lesson

Checkpoint the complete operating pattern

Lesson 5 combines native confirm/prompt, DOM modal, intentional unhandled-prompt failure, evidence capture, repair, and deterministic final-state verification.

Official references and version notes

Version and compatibility note

Version-sensitive behavior was rechecked against current primary documentation on 2026-08-28. Mandatory examples pin Selenium Python 4.47.0, require Python 3.10+, use a supported local Chromium-family browser with Selenium Manager for normal local driver resolution, and target only loopback fixtures. Selenium Python 4.47.0 documents dismiss and notify as the default unhandled_prompt_behavior; the chapter uses ignore only in a controlled failure-injection session so the learner can observe and then explicitly resolve the prompt. Classic WebDriver is sufficient for the mandatory chapter path; BiDi/CDP are not required to handle these dialog semantics.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.