-->

How do I recover the “text” from the page originat

2019-01-07 01:01发布

问题:

Basically, when an alert is popped up in javascript, I can dismiss() it from python perfectly OK, by calling selenium.webdriver.common.alert.Alert(browser).dismiss().

However, if the "browser user" dismisses the alert by clicking [OK] (on screen) with their mouse, then the browser alert gets "Lost in Space" the body.text can no longer be accessed from python.

So... How do I recover the "text" from the page originating the alert, esp after the human user has clicked [dismiss] on the page's alert?

Here are the hints and a script to demonstrate the problem...

FYI: The objective of the originating code is it allow the browser user intervene on screen in testing and manually response to specific alerts.

#!/usr/bin/env python
import os,sys,time
import selenium.webdriver
import selenium.webdriver.support.expected_conditions

print dict(python=sys.version,selenium=selenium.__version__)

path=os.path.join(os.getcwd(),"hello_worlds.html")
url="file:///"+path

open(path,"w").write("""<HTML>
  <HEAD><TITLE>Head Title</TITLE></HEAD>
  <BODY><H1>Hello, worlds!</H1></BODY>
</HTML> """)

browser=selenium.webdriver.Firefox()
browser.get(url)

body=browser.find_element_by_tag_name("body")
print "BODY:",body.text

try:

  for enum,world in enumerate("Mercury Venus Earth Mars Asteroids Jupiter Saturn Uranus Neptune".split()):

    if "Earth" in world: world+=": So do MANUALLY dismiss! {Click [OK] now!!!}"
    else: world+=": AUTO PILOT... please DONT dismiss! {done via selenium.dismiss()!}"

    browser.execute_script('alert("Hello, %s!")'%world)
    if selenium.webdriver.support.expected_conditions.alert_is_present():
      print selenium.webdriver.common.alert.Alert(browser).text

    time.sleep(enum+5)
    if "Earth" not in world: selenium.webdriver.common.alert.Alert(browser).dismiss()

    print "BODY:",body.text

finally:
  browser.quit()

Output: (Crash at Earth)

{'python': '2.6.6 (r266:84292, Aug 18 2016, 15:13:37) \n[GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]', 'selenium': '2.53.2'}
BODY: Hello, worlds!
Hello, Mercury: AUTO PILOT... please DONT dismiss! {done via selenium.dismiss()!}!
BODY: Hello, worlds!
Hello, Venus: AUTO PILOT... please DONT dismiss! {done via selenium.dismiss()!}!
BODY: Hello, worlds!
Hello, Earth: So do MANUALLY dismiss! {Click [OK] now!!!}!
BODY:
Traceback (most recent call last):
  File "./js_alert.py", line 37, in <module>
    print "BODY:",body.text
...
selenium.common.exceptions.UnexpectedAlertPresentException: Alert Text: Hello, Earth: So do MANUALLY dismiss! {Click [OK] now!!!}!
Message: Unexpected modal dialog (text: Hello, Earth: So do MANUALLY dismiss! {Click [OK] now!!!}!) The alert disappeared before it could be closed.

The strange thing is that if the browser user triggers another alert (on another page even!), then a selenium.dismiss() will pull body.text back from limbo and selenium with from then will operate as per (my) expectations.

Any suggestions on how to get the browser back to the page.body? (And escape the alert)

Addendum: Here are similar questions (found with intense searching):

  • downloading - Issues downloading file using Selenium + Firefox
  • java alert - Selenium WebDriver - Unexpected modal dialog Alert
  • UnexpectedAlertPresentException - Webdriver error: "No alert is present" after UnexpectedAlertPresentException is thrown
  • DesiredCapabilities - How to handle an Alert with "UnexpectedAlertBehaviour" capability in Selenium?
  • java&javascript - org.openqa.selenium.UnhandledAlertException: unexpected alert open
  • disables exception or DesiredCapabilities - org.openqa.selenium.UnhandledAlertException: unexpected alert open
  • non-click suggestion - When I show a dialog, an exception "UnhandledAlertException: Modal dialog present" is thrown
  • IE and in the wild - https://github.com/SeleniumHQ/selenium-google-code-issue-archive/issues/4839
  • java bug report? https://groups.google.com/forum/#!topic/webdriver/aNyOfEjMENg
  • "still doesn't work." catching exception does not reset the problem - (However almost exactly the same problem) - how to handle javascript alerts in selenium using python
  • suggested doing a driver.findElement(By.id("myAlert")); but that throws same exception - https://sqa.stackexchange.com/questions/22482/why-my-alert-is-not-popping-up
  • browser.refresh(); gives UnexpectedAlertPresentException so doesn't work. https://github.com/angular/protractor/issues/1486
  • browser.switch_to.window(browser.window_handles[0]) then body.text gives: UnexpectedAlertPresentException
  • Similar - Python webdriver to handle pop up browser windows which is not an alert

回答1:

I have been struggling with this issue off and on for a long time; your comment on your question solved the problem for me:

After both UnexpectedAlertPresentException and NoAlertPresentException are thrown...

browser.execute_script('alert("Clearing out past dialogs.")')
browser.switch_to.alert.accept()

As you said in your answer, webdriver is creating a 'dialog' when the alert is present. Closing the alert by hand causes its reference to get lost in limbo, but it's still blocking access to body.text. Creating a new alert seems to allow webdriver to clear out that old 'dialog' and (after accepting) grants access to the page again.



回答2:

No solution yet... I suspect it is a bug in Firefox's webdriver in file modals.js

Firefox's web driver captures the alert popup and replaces it with an element named 'dialog' { e.g. getElementsByTagName('dialog')[0]}

The problem is that if the tester is human and clicks on either "dismiss" or "accept", then the "onclick" for 'dialog' does not call fxdriver.modals.clearFlag_... hence the problem.

https://github.com/SeleniumHQ/selenium/blob/master/javascript/firefox-driver/js/modals.js#LC39

fxdriver.modals.isModalPresent = function(callback, timeout) {
    fxdriver.modaltimer = new fxdriver.Timer();
    fxdriver.modaltimer.runWhenTrue(
    function() {
      var modal = fxdriver.modals.find_();
      return modal && modal.document && modal.document.getElementsByTagName('dialog')[0];
    },
    function() { callback(true) },
    timeout,
    function() { callback(false) });
};


fxdriver.modals.acceptAlert = function(driver) {
  var modal = fxdriver.modals.find_();
  var button = fxdriver.modals.findButton_(modal, 'accept');
  button.click();
  fxdriver.modals.clearFlag_(driver);
};

https://github.com/SeleniumHQ/selenium/blob/master/javascript/firefox-driver/js/modals.js#LC127

fxdriver.modals.setFlag = function(driver, flagValue) {
  driver.modalOpen = flagValue;
};

fxdriver.modals.clearFlag_ = function(driver) {
  fxdriver.modals.setFlag(driver, false);
};

Maybe the file_detector selecting local files has a work around...

  • http://selenium-python.readthedocs.io/api.html#selenium.webdriver.remote.webdriver.WebDriver.file_detector_context

Similar problem:

  • How to debug Firefox alert box closing automatically and being unable to detect the alert in Serenity BDD?

Bug report:

  • https://github.com/SeleniumHQ/selenium/issues/4190