Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebDriver executeAsyncScript vs executeScript

What is the difference between executeAsyncScript and executeScript? How can i use event such as window.onload? I tried something like this

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

But of course it did not work... So if anyone knows how it works please write an example

like image 376
vispart Avatar asked Nov 19 '12 11:11

vispart


People also ask

What is executeScript in Selenium?

JavascriptExecutor consists of two methods that handle all essential interactions using JavaScript in Selenium. executeScript method – This method executes the test script in the context of the currently selected window or frame. The script in the method runs as an anonymous function.

What is executeScript?

The executeScript command executes a snippet of JavaScript in the context of the currently selected frame or window. The script fragment will be executed as the body of an anonymous function. To store the return value, use the 'return' keyword and provide a variable name in the value input field.

Which method of JavascriptExecutor helps to improve the performance of test?

Using the executeAsyncScript, helps to improve the performance of your test. It allows writing test more like a normal coding. The execSync blocks further actions being performed by the Selenium browser but execAsync does not block action.

Why JavascriptExecutor is used in Selenium?

JavaScriptExecutor in Selenium provides two methods through which we can run JavaScript on the selected window or the current page. This method executes JavaScript in the context of the currently selected window or frame in Selenium. The script will be executed as the body of an anonymous function.


4 Answers

(Keeping it simple, and correct.)

The relevant difference between execteScript and executeAsyncScript is this:

The function invoked with executeAsyncScript takes a 'done callback' as the last argument, which must be called to signal that the script is done executing.

This allows it to be used with code that only 'finishes' when a callback is used - eg. setTimeout or asynchronous XHR. If the 'done callback' is not called within the timeout limits the returned promise will be rejected.

Per the webdriver.WebDriver.executeAsyncScript documentation:

Unlike executing synchronous JavaScript with #executeScript, scripts executed with [#executeAsyncScript] must explicitly signal they are finished by invoking the provided callback. This callback will always be injected into the executed function as the last argument..

That is, both functions block the WebDriver control flow until they complete - either running off the end of the code for executeScript or when calling the 'done callback' with executeAsyncScript: "async" in the name signifies the signal mechanism used and does not mean/imply that the JavaScript code is actually executed asynchronously with respect to the WebDriver.

like image 95
user2864740 Avatar answered Oct 19 '22 05:10

user2864740


I use executeScript. Example provided:

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

Concerning details on alerts there is known issue. you can get details here

In accordance with documentation difference is:

executeScript

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

Description copied from interface: JavascriptExecutor Executes JavaScript in the context of the currently selected frame or window. The script fragment provided will be executed as the body of an anonymous function. Within the script, use document to refer to the current document. Note that local variables will not be available once the script has finished executing, though global variables will persist. If the script has a return value (i.e. if the script contains a return statement), then the following steps will be taken:

  • For an HTML element, this method returns a WebElement
  • For a decimal, a Double is returned
  • For a non-decimal number, a Long is returned
  • For a boolean, a Boolean is returned
  • For all other cases, a String is returned.
  • For an array, return a List with each object following the rules above. We support nested lists.
  • Unless the value is null or there is no return value, in which null is returned

Arguments must be a number, a boolean, a String, WebElement, or a List of any combination of the above. An exception will be thrown if the arguments do not meet these criteria. The arguments will be made available to the JavaScript via the "arguments" magic variable, as if the function were called via "Function.apply"

Specified by: executeScript in interface JavascriptExecutor Parameters: script - The JavaScript to execute args - The arguments to the script. May be empty Returns: One of Boolean, Long, String, List or WebElement. Or null.

executeAsyncScript

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

Description copied from interface: JavascriptExecutor Execute an asynchronous piece of JavaScript in the context of the currently selected frame or window. Unlike executing synchronous JavaScript, scripts executed with this method must explicitly signal they are finished by invoking the provided callback. This callback is always injected into the executed function as the last argument. The first argument passed to the callback function will be used as the script's result. This value will be handled in the same way as the synchronous case.

Example #1: Performing a sleep in the browser under test.

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

Example #2: Synchronizing a test with an AJAX application:

 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("[email protected]");

Example #3: Injecting a XMLHttpRequest and waiting for the result:

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

Script arguments must be a number, a boolean, a String, WebElement, or a List of any combination of the above. An exception will be thrown if the arguments do not meet these criteria. The arguments will be made available to the JavaScript via the "arguments" variable.

Specified by: executeAsyncScript in interface JavascriptExecutor Parameters: script - The JavaScript to execute. args - The arguments to the script. May be empty. Returns: One of Boolean, Long, String, List, WebElement, or null.

Detailed documentation is here

like image 28
eugene.polschikov Avatar answered Oct 19 '22 04:10

eugene.polschikov


The main difference between those are that scripts executed with async must explicitly signal they are finished by invoking the provided callback. This callback is always injected into the executed function as the last argument.

like image 9
sphair Avatar answered Oct 19 '22 05:10

sphair


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

will show the alert:

((JavascriptExecutor) driver).executeAsyncScript() is used when the JS takes time to execute e.g.in a Web Service call.

window.onload makes sure the JS is executed when the page is loaded completely.

like image 3
Ishank Avatar answered Oct 19 '22 05:10

Ishank