Quelle est la différence entre executeAsyncScript et executeScript? Comment puis-je utiliser un événement tel que window.onload? J'ai essayé quelque chose comme ça
((JavascriptExecutor) driver).executeAsyncScript("window.onload = function() {alert('Hello')}");
Mais bien sûr, cela n'a pas fonctionné ... Donc, si quelqu'un sait comment cela fonctionne, veuillez écrire un exemple
J'utilise executeScript
. Exemple fourni:
String cssSelector="...blablabla...";
JavascriptExecutor js = (JavascriptExecutor) driver;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("document.getElementById(\'"+cssSelector +"\').click();");
js.executeScript(stringBuilder.toString());
Concernant les détails des alertes, il existe un problème connu. vous pouvez obtenir des détails ici
Conformément à la documentation, la différence est:
executeScript
public Java.lang.Object executeScript(Java.lang.String script, Java.lang.Object... args)
Description copiée depuis l'interface: JavascriptExecutor Exécute JavaScript dans le contexte du cadre ou de la fenêtre actuellement sélectionné. Le fragment de script fourni sera exécuté comme le corps d'une fonction anonyme. Dans le script, utilisez document pour faire référence au document actuel. Notez que les variables locales ne seront pas disponibles une fois l'exécution du script terminée, bien que les variables globales persistent. Si le script a une valeur de retour (c'est-à-dire si le script contient une instruction de retour), les étapes suivantes seront suivies:
- Pour un élément HTML, cette méthode renvoie un WebElement
- Pour une décimale, un Double est retourné
- Pour un nombre non décimal, un Long est retourné
- Pour un booléen, un booléen est retourné
- Pour tous les autres cas, une chaîne est renvoyée.
- Pour un tableau, renvoyez une liste avec chaque objet en suivant les règles ci-dessus. Nous prenons en charge les listes imbriquées.
- Sauf si la valeur est nulle ou s'il n'y a pas de valeur de retour, dans laquelle null est retourné
Les arguments doivent être un nombre, un booléen, une chaîne, un élément Web ou une liste de toute combinaison des éléments ci-dessus. Une exception sera levée si les arguments ne répondent pas à ces critères. Les arguments seront mis à disposition du JavaScript via la variable magique "arguments", comme si la fonction était appelée via "Function.apply"
Spécifié par: executeScript dans l'interface JavascriptExecutor Paramètres: script - Le JavaScript pour exécuter les arguments - Les arguments du script. Peut être vide Renvoie: Un de Boolean, Long, String, List ou WebElement. Ou nul.
executeAsyncScript
public Java.lang.Object executeAsyncScript(Java.lang.String script, Java.lang.Object... args)
Description copiée depuis l'interface: JavascriptExecutor Exécute un morceau asynchrone de JavaScript dans le contexte du cadre ou de la fenêtre actuellement sélectionné. Contrairement à l'exécution de JavaScript synchrone, les scripts exécutés avec cette méthode doivent signaler explicitement qu'ils sont terminés en appelant le rappel fourni. Ce rappel est toujours injecté dans la fonction exécutée comme dernier argument. Le premier argument passé à la fonction de rappel sera utilisé comme résultat du script. Cette valeur sera traitée de la même manière que le cas synchrone.
Exemple # 1: Réalisation d'un sommeil dans le navigateur sous test.
long start = System.currentTimeMillis(); ((JavascriptExecutor) driver).executeAsyncScript( "window.setTimeout(arguments[arguments.length - 1], 500);"); System.out.println( "Elapsed time: " + (System.currentTimeMillis() - start));
Exemple # 2: Synchronisation d'un test avec une application 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("[email protected]");
Exemple # 3: Injection d'un XMLHttpRequest et attente du résultat:
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"));
Les arguments de script doivent être un nombre, un booléen, une chaîne, un élément Web ou une liste de toute combinaison des éléments ci-dessus. Une exception sera levée si les arguments ne répondent pas à ces critères. Les arguments seront mis à disposition du JavaScript via la variable "arguments".
Spécifié par: executeAsyncScript dans l'interface JavascriptExecutor Paramètres: script - Le JavaScript à exécuter. args - Les arguments du script. Peut être vide. Renvoie: un booléen, long, chaîne, liste, WebElement ou null.
La documentation détaillée est ici
(Le garder simple , et correct .)
La différence pertinente entre execteScript
et executeAsyncScript
est la suivante:
La fonction invoquée avec executeAsyncScript
prend un 'rappel terminé' comme dernier argument, qui doit être appelé pour signaler que le script est terminé exécution.
Cela lui permet d'être utilisé avec du code qui ne "se termine" que lorsqu'un rappel est utilisé - par exemple. setTimeout ou XHR asynchrone. Si le "rappel terminé" n'est pas appelé dans les délais, la promesse retournée sera rejetée.
Contrairement à l'exécution de JavaScript synchrone avec #executeScript, les scripts exécutés avec [#executeAsyncScript] doivent explicitement signaler qu'ils sont terminés en invoquant le rappel fourni . Ce rappel sera toujours injecté dans la fonction exécutée comme dernier argument.
Autrement dit, ( les deux fonctions bloquent le flux de contrôle WebDriver jusqu'à ce qu'elles se terminent - soit en exécutant la fin du code pour executeScript
ou lors de l'appel du 'done callback' avec executeAsyncScript
: "async" dans le nom signifie le mécanisme de signal utilisé et ne signifie pas/n'implique pas que le code JavaScript est réellement exécuté de manière asynchrone par rapport au WebDriver .
La principale différence entre ceux-ci est que les scripts exécutés avec async doivent signaler explicitement qu'ils sont terminés en appelant le rappel fourni. Ce rappel est toujours injecté dans la fonction exécutée comme dernier argument.
J'ai utilisé beaucoup de temps pour comprendre cette fonction et j'ai finalement compris. le code suivant aidera beaucoup:
/**
* 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);
});
}
((JavascriptExecutor) driver).executeScript("alert('Hello');");
affichera l'alerte:
(Pilote (JavascriptExecutor)) .executeAsyncScript () est utilisé lorsque le JS met du temps à s'exécuter, par exemple dans un appel de service Web.
window.onload
s'assure que le JS est exécuté lorsque la page est complètement chargée.