1

I have a test that has been running fine for months. One thing it does is cause an alert and then verify the alert text. This is running with Selenium, Java and Chrome Driver 76.0.3809.68.

Lately it has been giving me the error:

"No such alert".

What happens is it clicks a button and waits for an alert if there:

 try {
    button.click();
 } catch (UnhandledAlertException ex) {
   // nothing
 }

 // then here goes code to accept the alert and get the text

when stepping through I see the alert. When I run it, I see the alert but it disappears. I did read something in the (Chrome Driver) release notes about unexpected alerts but it was a bit vague.

We have a global page which sets the options for Chrome, but everyone uses it and I don't want to screw up for other people. I did do it locally (did not git push) and it worked when I set the options before creating the driver.

Then I tried to do this, which does not seem to work. Should it, or once the web page is retrieved, can you not change options?

 // Somewhere after web page retrieved this gets called:

public void setIgnoreAlert() {
    ChromeDriver cd = (ChromeDriver) driver;
    ChromeOptions cap = new ChromeOptions();
    cap.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE);
    Capabilities other = cap;
    cd.getCapabilities().merge(other);
 }

Which I was really hoping would work, but did not. Do you have to set the behavior before the Chrome instance comes up? That is, can you not set it as I did above? Any other suggestions on how to set it after the Chrome instance is up?

--- added later to answer question

This is done immediately after the try-catch block with button.click():

The method configPage.getAndHandleAlertPopUp() does the following:

public String getAndHandleAlertPopUp() {
    Alert alert = driver.switchTo().alert();
    String alertPopup = alert.getText();
    alert.accept();
    return alertPopup;
}
Tony
  • 1,127
  • 1
  • 18
  • 29
  • set it in options before initializing the driver. options.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE) This will throw an expection upon executing certain subsequent actions IF the alert still exists. If you handle the alert yourself, you should be good. – pcalkins Aug 13 '19 at 21:45
  • btw, default seems to be DISMISS_AND_NOTIFY now... which closes the prompt, but still throws the exception (that's the "notify" part I guess). ACCEPT and DISMISS will close all prompts without throwing an exception down the line. – pcalkins Aug 13 '19 at 21:50
  • btw, if you can leave the options as they are, but just be aware that you have to deal with the prompt right when it appears. The code you are using to check for the text may be throwing the exception depending on what it does. This shows the W3C algorithms that the new Chromedriver is following: https://www.w3.org/TR/webdriver1/#navigation Whenever you see, "Handle any user prompts"... that's where the unexpected alert behavior comes into play. – pcalkins Aug 13 '19 at 22:21

1 Answers1

3

You saw it right. As per the User Prompts section within WebDriver - W3C Recommendation:

The common denominator for user prompts is that they are modal windows requiring users to interact with them before the event loop is unpaused and control is returned to the current top-level browsing context.

By default user prompts are not handled automatically unless a user prompt handler has been defined. When a user prompt appears, it is the task of the subsequent command to handle it. If the subsequent requested command is not one listed in this chapter, an unexpected alert open error will be returned.

User prompts that are spawned from beforeunload event handlers, are dismissed implicitly upon navigation or close window, regardless of the defined user prompt handler.

A user prompt has an associated user prompt message that is the string message shown to the user, or null if the message length is 0.


As per the discussion in ChromeDriver should return user prompt (or alert) text in unhandled alert error response:

When a user prompt handler is triggered, the W3C Specification states that the error response should return an "annotated unexpected alert open error" which includes an optional dictionary containing the text of the user prompt. ChromeDriver should supply the optional information.


Clearly, ChromeDriver was not compliant with this standard as the @Test were annotated with @NotYetImplemented as follows:

  @Test
  @NotYetImplemented(CHROME)
  @NotYetImplemented(CHROMIUMEDGE)
  @Ignore(value = HTMLUNIT, reason = "https://github.com/SeleniumHQ/htmlunit-driver/issues/57")
  @NotYetImplemented(value = MARIONETTE,
      reason = "https://bugzilla.mozilla.org/show_bug.cgi?id=1279211")
  @NotYetImplemented(EDGE)
  public void testIncludesAlertTextInUnhandledAlertException() {
    driver.get(alertPage("cheese"));

    driver.findElement(By.id("alert")).click();
    wait.until(alertIsPresent());

    assertThatExceptionOfType(UnhandledAlertException.class)
    .isThrownBy(driver::getTitle)
    .withMessageContaining("cheese")
    .satisfies(ex -> assertThat(ex.getAlertText()).isEqualTo("cheese"));
  }

Now this feature have been implemented with ChromeDriver v76.0:

Resolved issue 2869: ChromeDriver should return user prompt (or alert) text in unhandled alert error response [Pri-2]

So you have to handle the alert as a mandatory measure.


A bit more of your code code block for ...then here goes code to accept the alert and get the text... would have helped us to debug the issue in a better way. However here are the options:

Note: Once the WebDriver and Web Browser instances are initialized you won't be able to change the configuration on the run. Even if you are able to extract the Session ID, Cookies and other capabilities and session attributes from the Browsing Session still you won't be able to alter those attributes of the WebDriver.

You can find a detailed discussion in How can I reconnect to the browser opened by webdriver with selenium?

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • yes but I think by setIgnoreAlert() was ineffective as the driver had already been created. I did get our lead to give me a property I could set in my @DataProvider to bring the driver up with the ignore. I could not do it myself. I have to set the property. If it is not set, then it will remain the default which I guess is accept and dismiss (but throw the error) – Tony Aug 14 '19 at 19:48
  • I added a few paragraphs into the question showing how the alert had been handled before the new Chromedriver version. Now with the new one it is dismissed, so it could not be switched to. – Tony Aug 14 '19 at 19:58
  • @Tony Checkout the answer update and let me know if any queries. – undetected Selenium Aug 14 '19 at 20:01
  • Thanks. I had them add a way for me to specify "ignore" before the driver is created. That works. I suppose also, instead of switching to the alert and getting the text and accepting, I could just catch the alert error and get the text from the alert message, and simulate actually intercepting the error. – Tony Aug 15 '19 at 11:34
  • @DebanjanB what maven dependency should I add and what library to import in order to use `opt.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE)` ? Currently my IntelliJ doesn't know what is `CapabilityType` and what is `UnexpectedAlertBehaviour`? Thanks in advance! – Prophet Aug 25 '21 at 18:19