【问题标题】:How can I capture the "load" event by adding my own listener through ExecuteScript?如何通过 ExecuteScript 添加自己的侦听器来捕获“加载”事件?
【发布时间】:2015-01-09 09:10:26
【问题描述】:

我正在尝试使用 Selenium 捕捉 load(不是 onload)事件。

我的代码如下所示(参见 cmets):

// d is my webdriver
// go to url
d.Navigate().GoToUrl(url);
WebDriverWait wait = new WebDriverWait(d, TimeSpan.FromSeconds(30));

// create a function that add an element with id="my_123456789"
string javascript = 
   "my_readyFCT = function(){"
     + "alert('READY');"
     + "var e = document.createElement('div');"
     + "e.id = 'my_123456789';"
     + "document.body.appendChild(e);"
   + "};"
// call the function once 'load' event is fired
   + "window.addEventListener('load', my_readyFCT, false);"

((IJavaScriptExecutor)d).ExecuteScript(javascript);

// Selenium wait until the element with id "my_123456789" exists
wait.Until<IWebElement>(ExpectedConditions.ElementExists(By.Id("my_123456789")));

我总是遇到超时异常(30 秒),我看不出我做错了什么。

有什么想法吗?

注意:我尝试自己执行函数my_readyFCT,它创建了插入DOM的具有正确ID的元素。

编辑

这里是javascript:

my_readyFCT = function() {
   alert('READY');
   var e = document.createElement('div');
   e.id = 'my_123456789';
   document.body.appendChild(e);
};
// call the function once 'load' event is fired
window.addEventListener('load', my_readyFCT, false);

编辑 2

我必须说我找到了一种方法来避免GoToUrl 的常见行为(这是页面加载的方式):

var fb = new FirefoxBinary();
fb.Timeout = TimeSpan.FromMinutes(4);
FirefoxProfile fp = new FirefoxProfile();
// 'unstable' allow us to avoid the implicit wait in GoToUrl
fp.SetPreference("webdriver.load.strategy", "unstable");
d = new FirefoxDriver(fb, fp, TimeSpan.FromMinutes(1));

当我想更改网址时:

d.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(0));
try {
   d.Navigate().GoToUrl(url);
}
catch(WebDriverException) /* will be thrown everytime */ 
{ }

WebDriverWait wait = new WebDriverWait(d, TimeSpan.FromSeconds(30));
/*
*  ...
*   ETC. See code above
*  ...
*/

【问题讨论】:

    标签: javascript c# .net selenium


    【解决方案1】:

    你试图做的事情无法完成。 GoToUrl 的文档(对于 Java 和 Python 以及可能 Selenium 支持的其他语言是 get)明确表示它会阻塞“直到加载完成”。

    你可以测试一下。采用以下 HTML:

    <!DOCTYPE html>
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8"/>
        <script>
          window.addEventListener("load", function () {
              window.loaded_inline = true;
          });
        </script>
       </head>
      <body>
      </body>
    </html>
    

    并运行以下 Selenium 脚本。抱歉,我不会 C#,所以这是 Python。应该不难理解:

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    driver.get("file:///tmp/t2/index.html")  # This gets the page above.
    
    # This checks whether the load handler in the page was called.
    print "Inline:", driver.execute_script("return window.loaded_inline")
    
    driver.set_script_timeout(2)
    
    # This is an asynchronous script. It will end when the load event is
    # emitted by the browser. Or timeout if the event does not happen.
    driver.execute_async_script("""
    var done = arguments[0];
    window.addEventListener('load', done, false);
    """)
    
    driver.quit()
    

    执行此操作时,我得到Inline: True,然后超时。您可以随意增加超时时间,它永远不会改变结果。

    这表明load 事件发生在get 返回之前,到那时再向load 添加更多侦听器为时已晚。

    如何让页面加载立即返回?

    它也不起作用。首先,在我看来,你必须将webdriver.load.strategy 设置为值unstable 的事实应该是一个线索,你知道,这可能不是稳定的东西。该设置是文档中的marked "beta"。文档还说:

    这可能会导致立即查找的 [原文如此] 中断,因此请务必也使用隐式或显式等待。

    他们谈论的用例是立即加载页面,然后在其上搜索元素。 此搜索在 HTML 完全加载之前无法完成,这意味着 load 已经发生了。

    如果您确实尝试在找到元素之前运行脚本,那么脚本根本不会执行。

    【讨论】:

    • 我已经找到了避免这个问题的解决方法:我明确地说 selenium 不要等待GoToUrl 不要等待页面加载结束。我从FirefoxProfile fp = new FirefoxProfile(); fp.SetPreference("webdriver.load.strategy", "unstable"); 开始,在GoToUrl 之前:d.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(0)); try { d.Navigate().GoToUrl(url); } catch(WebDriverException) /* will be thrown everytime */ { }
    • 哼。我明白了,我需要找到其他东西。谢谢你的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 2010-11-26
    相关资源
    最近更新 更多