如何从发出警报的页面中恢复“文本”,尤其是在人类用户 *单击 * 页面的 **警报** 之后**?

IT技术 javascript python alert dismiss selenium-firefoxdriver
2021-03-09 15:22:43

基本上,当在 javascript 中弹出警报时,我可以dismiss()通过调用selenium.webdriver.common.alert.Alert(browser).dismiss().

但是,如果“浏览器用户”通过[OK]用鼠标单击(在屏幕上)解除警报,则浏览器警报将“迷失在空间”,body.text无法再从 python 访问。

那么...如何从发出警报的页面中恢复“文本”,尤其是人类用户单击页面警报上的 [关闭] 之后

以下是演示问题的提示和脚本...

供参考:始发码的目标是它允许浏览器用户干预在屏幕上在测试和手动响应特定警报。

#!/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()

输出:(地球坠毁)

{'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.

奇怪的是,如果浏览器用户触发另一个警报(甚至另一个页面上!),那么 a selenium.dismiss()willbody.text从 limbo 和 selenium with from then 中拉回,将按(我的)期望运行。

关于如何让浏览器回到page.body? (并逃脱警报)

附录:以下是类似的问题(通过大量搜索找到):

2个回答

很长一段时间以来,我一直在为这个问题而苦苦挣扎。您对问题的评论为我解决了问题:

UnexpectedAlertPresentExceptionNoAlertPresentException都被抛出之后......

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

正如您在回答中所说,当出现警报时,webdriver 正在创建一个“对话框”。手动关闭警报会导致其引用在不确定中丢失,但它仍然阻止访问body.text. 创建新警报似乎允许 webdriver 清除旧的“对话框”,并(接受后)再次授予对页面的访问权限。

还没有解决方案......我怀疑这是文件modals.js中 Firefox 的 webdriver 中的一个错误

Firefox 的网络驱动程序捕获警报弹出窗口并将其替换为名为“对话框”的元素 { eg getElementsByTagName('dialog')[0]}

问题是,如果测试人员是人类并单击“拒绝”或“接受”,则“对话框”的“onclick”不会调用fxdriver.modals.clearFlag_......因此问题。

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);
};

也许 file_detector 选择本地文件有一个解决方法......

类似问题:

错误报告: