2012-11-19 12 views
27

Jaka jest różnica między executeAsyncScript i executeScript? Jak mogę użyć zdarzenia takiego jak window.onload? Próbowałem coś jak tenWebDriver executeAsyncScript kontra executeScript

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

Ale oczywiście to nie działa ... Więc jeśli ktoś wie jak to działa napisz przykład

+6

Główna różnica między nimi polega na tym, że skrypty wykonywane z asynchronicznie muszą jawnie sygnalizować, że są zakończone przez wywołanie dostarczonego wywołania zwrotnego. To wywołanie zwrotne jest zawsze wprowadzane do wykonanej funkcji jako ostatni argument. – sphair

+0

Dzięki za opinie! – vispart

+0

@sphair powinieneś był złożyć odpowiedź, jej zwięzłe i poprawne, przesiewanie niektórych śmieci poniżej było trudne. – Pykler

Odpowiedz

21

używam executeScript. Podany przykład:

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

Odnośnie szczegółów dotyczących ostrzeżeń, znany jest problem. można uzyskać szczegółowe here

Zgodnie z różnicy dokumentacja jest:

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.

Szczegółowa dokumentacja jest here

+5

"Opis" powyżej (skopiowany z dokumentacji interfejsu) ORAZ powiązana z nim dokumentacja są nieaktualne. Lista "obiektów" zostanie zwrócona jako Lista >. Gdzie każdy klucz jest właściwością obiektu. Nie wiem, jak uzyskać szczegółowe informacje na ten temat, ale spłonęło mnie po przeczytaniu tego, więc pomyślałem, że przyczynię się do tego. – dmansfield

+0

@ eugene.polschikov Odwołuję się do przykładu 3, a kiedy wykonuję linię w konsoli otrzymuję komunikat "Uncaught ReferenceError: argumenty nie są zdefiniowane pod adresem : 1: 16 '. Jestem całkowicie nowy w JS i twoja pomoc jest doceniana. –

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

pokaże Alert:

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

window.onload sprawia pewien, że JS jest wykonywane po całkowitym załadowaniu strony.

5

Główna różnica między nimi polega na tym, że skrypty wykonywane z asynchronicznie muszą jawnie sygnalizować, że zostały zakończone przez wywołanie podanego wywołania zwrotnego. To wywołanie zwrotne jest zawsze wprowadzane do wykonanej funkcji jako ostatni argument.

+0

Dlaczego ta zła dokumentacja tego nie mówi? Dokumentacja mówi tylko: "Wykonuje JavaScript asynchronicznie w kontekście aktualnie wybranej klatki lub okna." – Elmue

13

(. Utrzymywanie go prosty i poprawne)

Odpowiednia różnica między execteScript i executeAsyncScript to:

Funkcja wywoływana z executeAsyncScript bierze „zwrotnego Gotowe” jako ostatni argument , który musi być musi sygnalizować wykonanie skryptu.

Umożliwia to używanie go z kodem, który "kończy się" tylko wtedy, gdy używane jest wywołanie zwrotne - np. setTimeout lub asynchroniczny XHR. Jeśli "callback" nie zostanie wywołany w limicie czasu, zwrócona obietnica zostanie odrzucona.

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

Oznacza to, obie funkcje blokowania przepływu kontrola WebDriver do czasu ukończenia - albo zjechania na końcu kodu dla executeScript lub podczas wywoływania „zwrotnego Gotowe” z executeAsyncScript: „async” w nazwa oznacza wykorzystywany mechanizm sygnału i nie oznacza/sugeruje, że kod JavaScript jest faktycznie wykonywany asynchronicznie w odniesieniu do WebDriver.

1

Zużyłem wiele czasu, aby objąć tę funkcję i wreszcie ją otrzymałem. Kodu follwing pomoże bardzo:

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

}