WebDriver executeAsyncScript vs executeScript

时间:2012-11-19 11:27:12

标签: javascript testing selenium webdriver qa

executeAsyncScript和executeScript有什么区别?我如何使用window.onload等事件?我试过这样的事情

((JavascriptExecutor) driver).executeAsyncScript("window.onload = function() {alert('Hello')}"); 

但当然它不起作用...... 所以如果有人知道它是如何工作的,请写一个例子

6 个答案:

答案 0 :(得分:24)

我使用executeScript。提供的示例:

String cssSelector="...blablabla...";
JavascriptExecutor js = (JavascriptExecutor) driver;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("document.getElementById(\'"+cssSelector +"\').click();");
js.executeScript(stringBuilder.toString());

关于警报的详细信息,已知问题。您可以获得详细信息here

根据文件的不同之处是:

  

<强> executeScript

public java.lang.Object executeScript(java.lang.String script,
                             java.lang.Object... args)
     

从界面复制的说明:JavascriptExecutor   在当前选定的框架或窗口的上下文中执行JavaScript。提供的脚本片段将作为主体执行   一个匿名函数。在脚本中,使用文档来引用   目前的文件。请注意,局部变量不可用一次   脚本已完成执行,但全局变量将执行   坚持。如果脚本具有返回值(即脚本包含的话)   返回声明),然后将采取以下步骤:

     
      
  • 对于HTML元素,此方法返回WebElement
  •   
  • 对于小数,返回Double
  •   
  • 对于非十进制数字,返回Long
  •   
  • 对于布尔值,返回布尔值
  •   
  • 对于所有其他情况,返回一个String。
  •   
  • 对于数组,按照上述规则返回包含每个对象的List。我们支持嵌套列表。
  •   
  • 除非值为null或没有返回值,否则返回null
  •   
     

参数必须是数字,布尔值,字符串,WebElement或List   以上的任何组合。如果是,将抛出异常   参数不符合这些标准。这些论点将被提出   通过“arguments”魔术变量可以使用JavaScript,就好像   该函数通过“Function.apply”

调用      

指定者:接口JavascriptExecutor中的executeScript   参数:script - 要执行args的JavaScript - 要执行的参数   剧本。可能为空返回:Boolean,Long,String,List之一   或WebElement。或者null。

     

<强> executeAsyncScript

public java.lang.Object executeAsyncScript(java.lang.String script,
                                  java.lang.Object... args)
     

从界面复制的说明:JavascriptExecutor   在当前选定的框架或窗口的上下文中执行异步JavaScript。与执行同步不同   JavaScript,使用此方法执行的脚本必须明确发出信号   它们是通过调用提供的回调来完成的。这个回调是   总是将执行函数作为最后一个参数注入。   传递给回调函数的第一个参数将被用作   脚本的结果。该值的处理方式与   同步案例。

     

示例#1:在被测浏览器中执行睡眠。

 long start = System.currentTimeMillis();
   ((JavascriptExecutor) driver).executeAsyncScript(
       "window.setTimeout(arguments[arguments.length - 1], 500);");
   System.out.println(
       "Elapsed time: " + (System.currentTimeMillis() - start));  
     

示例#2:将测试与AJAX应用程序同步:

 WebElement composeButton = driver.findElement(By.id("compose-button"));
   composeButton.click();
   ((JavascriptExecutor) driver).executeAsyncScript(
       "var callback = arguments[arguments.length - 1];" +
       "mailClient.getComposeWindowWidget().onload(callback);");
   driver.switchTo().frame("composeWidget");
   driver.findElement(By.id("to")).sendKeys("bog@example.com");
     

示例#3:注入XMLHttpRequest并等待结果:

 Object response = ((JavascriptExecutor) driver).executeAsyncScript(
       "var callback = arguments[arguments.length - 1];" +
       "var xhr = new XMLHttpRequest();" +
       "xhr.open('GET', '/resource/data.json', true);" +
       "xhr.onreadystatechange = function() {" +
       "  if (xhr.readyState == 4) {" +
       "    callback(xhr.responseText);" +
       "  }" +
       "}" +
       "xhr.send();");
   JSONObject json = new JSONObject((String) response);
   assertEquals("cheese", json.getString("food"));
     

脚本参数必须是数字,布尔值,字符串,WebElement,   或上述任何组合的清单。将抛出异常   如果参数不符合这些标准。争论将是   通过“arguments”变量提供给JavaScript。

     

指定者:接口JavascriptExecutor中的executeAsyncScript   参数:script - 要执行的JavaScript。 args - 论点   到脚本。可能是空的。返回:Boolean,Long,String之一,   List,WebElement或null。

详细文档为here

答案 1 :(得分:22)

(保持简单更正。)

execteScriptexecuteAsyncScript之间的相关区别是:

使用executeAsyncScript调用的函数需要完成回调&#39;作为最后一个参数,必须被调用以表示脚本已完成执行。

这使得它可以用于仅完成&#39;的代码。当使用回调时 - 例如setTimeout或异步XHR。如果完成回调&#39;在超时限制内未调用返回的承诺将被拒绝。

  

与使用#executeScript执行同步JavaScript不同,使用[#executeAsyncScript] 执行的脚本必须通过调用提供的回调明确表示它们已完成。这个回调将始终作为最后一个参数注入到执行的函数中。

也就是说, 这两个函数都会阻止WebDriver控制流 ,直到它们完成 - 运行executeScript的代码末尾或调用& #39;完成回调&#39;与executeAsyncScript:&#34; async&#34;在名称中表示使用的信号机制,并不表示/暗示JavaScript代码实际上是相对于WebDriver异步执行的。

答案 2 :(得分:8)

这些之间的主要区别在于,使用async执行的脚本必须通过调用提供的回调明确表示它们已完成。这个回调总是作为最后一个参数注入到执行的函数中。

答案 3 :(得分:2)

((JavascriptExecutor) driver).executeScript("alert('Hello');"); 

将显示警告:

  

((JavascriptExecutor)驱动程序)当JS花费时间执行例如Web服务调用时,使用.executeAsyncScript()。

window.onload确保在页面完全加载时执行JS。

答案 4 :(得分:2)

我花了很多时间来完成这个功能,最后我得到了它。以下代码将有很多帮助:

/**
 * executeAsyncScript document mentioned callback is a browser intrinsic function for returning deferred value (e.g 123 in example) from
 * js environment to Java environment
 * 
 */
@Test
public void testAsyncScript() {
    webDriver.manage().timeouts().setScriptTimeout(1, TimeUnit.SECONDS);
    Integer a = 23;
    TestUtil.elapse("first", () -> {
        Object value = getJsExecutor().executeAsyncScript("window.setTimeout(arguments[arguments.length - 1](123), 500);", a);
        // following code should be executed after 500ms timeout
        System.out.println("a is " + a); // a has nothing to do with the documented "callback"
        assertEquals(123, value);
    });

}

答案 5 :(得分:0)

这个简单的Async脚本侦听在DOM上单击的元素,并通过回调解析 executeAsyncScript

  var clicked_element = await driver.executeAsyncScript('var callback=arguments[arguments.length - 1]; window.document.addEventListener("click", function(e){ var element = event.srcElement ||event.target; callback(element); });');