Domanda WebDriver executeAsyncScript vs executeScript


Qual è la differenza tra executeAsyncScript ed executeScript? Come posso usare eventi come window.onload? Ho provato qualcosa di simile

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

Ma ovviamente non ha funzionato ... Quindi, se qualcuno sa come funziona, scrivi un esempio


29
2017-11-19 11:27


origine


risposte:


Io uso executeScript. Esempio fornito:

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

Per quanto riguarda i dettagli sugli avvisi, è noto un problema. puoi ottenere dettagli Qui

In conformità con la differenza di documentazione è:

executeScript

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

Descrizione copiata dall'interfaccia: JavascriptExecutor    Esegue JavaScript nel contesto del frame o della finestra attualmente selezionato. Il frammento di script fornito verrà eseguito come il corpo di   una funzione anonima. All'interno dello script, utilizzare il documento per fare riferimento a   documento corrente. Nota che le variabili locali non saranno disponibili una volta   lo script ha terminato l'esecuzione, anche se le variabili globali lo saranno   persistere. Se lo script ha un valore di ritorno (ad esempio se lo script contiene   una dichiarazione di ritorno), quindi saranno presi i seguenti passi:

  • Per un elemento HTML, questo metodo restituisce un WebElement
  • Per un decimale, viene restituito un doppio
  • Per un numero non decimale, viene restituito Long
  • Per un booleano, viene restituito un booleano
  • Per tutti gli altri casi, viene restituita una stringa.
  • Per un array, restituisci un elenco con ciascun oggetto seguendo le regole sopra riportate. Supportiamo liste annidate.
  • A meno che il valore sia nullo o non vi sia alcun valore di ritorno, in cui viene restituito un valore nullo

Gli argomenti devono essere un numero, un valore booleano, una stringa, un elemento Web o un elenco   di qualsiasi combinazione di quanto sopra. Un'eccezione verrà generata se il   argomenti non soddisfano questi criteri. Gli argomenti saranno fatti   disponibile per JavaScript tramite la variabile magica "arguments", come se   la funzione è stata chiamata tramite "Function.apply"

Specificato da: executeScript nell'interfaccia JavascriptExecutor   Parametri: script - Il JavaScript da eseguire args - Gli argomenti a   il copione. Può essere vuoto Restituisce: Uno di Boolean, Long, String, List   o WebElement. O null.

executeAsyncScript

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

Descrizione copiata dall'interfaccia: JavascriptExecutor    Esegui un pezzo asincrono di JavaScript nel contesto del frame o della finestra correntemente selezionati. A differenza dell'esecuzione sincrona   JavaScript, gli script eseguiti con questo metodo devono essere esplicitamente segnalati   terminano invocando il callback fornito. Questo è il callback   sempre iniettato nella funzione eseguita come ultimo argomento. Il   il primo argomento passato alla funzione di callback verrà utilizzato come   il risultato del copione Questo valore verrà gestito allo stesso modo del   caso sincrono.

Esempio 1: esecuzione di una sospensione nel browser in prova.

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

Esempio 2: sincronizzazione di un test con un'applicazione 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");

Esempio 3: Iniezione di XMLHttpRequest e attesa del risultato:

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

Gli argomenti script devono essere un numero, un valore booleano, una stringa, WebElement,   o un elenco di qualsiasi combinazione di quanto sopra. Sarà generata un'eccezione   se gli argomenti non soddisfano questi criteri. Gli argomenti saranno   reso disponibile per JavaScript tramite la variabile "arguments".

Specificato da: executeAsyncScript nell'interfaccia JavascriptExecutor   Parametri: script - Il codice JavaScript da eseguire. args - Gli argomenti   alla sceneggiatura. Può essere vuoto Restituisce: uno di Boolean, Long, String,   Elenco, WebElement o null.

La documentazione dettagliata è Qui


22
2017-11-19 12:34



(Mantenendolo semplice, e corretta.)

La differenza rilevante tra execteScript e executeAsyncScript è questo:

La funzione invocata con executeAsyncScript prende un callback 'fatto' come l'ultimo argomento, che dovere essere chiamato per segnalare che lo script è stato eseguito in esecuzione.

Ciò consente di utilizzarlo con un codice che "finisce" solo quando viene utilizzata una richiamata, ad es. setTimeout o XHR asincrono. Se il 'callback fatto' non viene chiamato entro i limiti di timeout, la promessa restituita verrà respinta.

A differenza dell'esecuzione di JavaScript sincrono con #executeScript, script eseguiti con [#executeAsyncScript] deve segnalare esplicitamente che sono finiti invocando il callback fornito. Questo callback sarà sempre iniettato nella funzione eseguita come ultimo argomento ..

Questo è, entrambe le funzioni bloccano il flusso di controllo di WebDriver fino a quando non completano - o eseguendo la fine del codice per executeScript o quando si chiama "callback completato" con executeAsyncScript: "async" nel nome indica il meccanismo del segnale utilizzato e non significa / implica che il codice JavaScript sia effettivamente eseguito in modo asincrono rispetto al WebDriver.


18
2017-11-22 19:53



La differenza principale tra questi è che gli script eseguiti con async devono segnalare esplicitamente che sono finiti richiamando il callback fornito. Questo callback è sempre iniettato nella funzione eseguita come ultimo argomento.


5
2018-05-30 07:57



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

mostrerà l'avviso:

((JavascriptExecutor) driver) .executeAsyncScript () viene utilizzato quando il JS impiega tempo per eseguire, ad esempio, una chiamata al servizio Web.

window.onload assicura che JS venga eseguito quando la pagina viene caricata completamente.


2
2017-11-19 14:55



Ho usato molto tempo per capire questa funzione e finalmente l'ho capito. il codice follwing aiuterà molto:

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

}

1
2018-03-13 14:04