Подтвердить что ты не робот

WebDriver executeAsyncScript vs executeScript

В чем разница между executeAsyncScript и executeScript? Как я могу использовать событие, такое как window.onload? Я попробовал что-то вроде этого

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

Но, конечно, это не сработало... Поэтому, если кто-нибудь знает, как это работает, напишите пример

4b9b3361

Ответ 1

Я использую executeScript. Пример:

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

В отношении сведений о предупреждениях существует известная проблема. вы можете получить подробности здесь

В соответствии с различием документации:

executeScript

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

Описание, скопированное из интерфейса: JavascriptExecutor Выполняет JavaScript в контексте выбранного кадра или окна. Предоставленный script фрагмент будет выполнен как тело анонимная функция. В script используйте документ для ссылки на текущий документ. Обратите внимание, что локальные переменные не будут доступны один раз script завершил выполнение, хотя глобальные переменные будут сохраняются. Если значение script имеет возвращаемое значение (т.е. Если script содержит оператор return), тогда будут предприняты следующие шаги:

  • Для элемента HTML этот метод возвращает WebElement
  • Для десятичного числа возвращается двойной элемент
  • Для не-десятичного числа возвращается длинный
  • Для boolean возвращается логическое значение
  • Для всех остальных случаев возвращается строка.
  • Для массива верните список с каждым объектом, следуя приведенным выше правилам. Мы поддерживаем вложенные списки.
  • Если значение не равно null или нет возвращаемого значения, в котором возвращается null

Аргументы должны быть числом, логическим, строковым, WebElement или списком любой комбинации вышеуказанного. Исключение будет выбрано, если аргументы не соответствуют этим критериям. Аргументы будут сделаны доступный для JavaScript через магическую переменную "arguments", как будто функция вызывалась через "Function.apply"

Указано: executeScript в интерфейсе JavascriptExecutor Параметры: script - JavaScript для выполнения args - аргументы для script. Может быть пустым Возвраты: один из булевых, длинный, строковый, список или WebElement. Или null.

executeAsyncScript

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

Описание, скопированное из интерфейса: JavascriptExecutor Выполните асинхронную часть JavaScript в контексте выбранного кадра или окна. В отличие от выполнения синхронных JavaScript, скрипты, выполненные с помощью этого метода, должны явно сигнализировать они завершаются вызовом предоставленного обратного вызова. Этот обратный вызов всегда вводится в исполняемую функцию в качестве последнего аргумента. первый аргумент, переданный функции обратного вызова, будет использоваться как script результат. Это значение будет обрабатываться так же, как и синхронный случай.

Пример # 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("[email protected]");

Пример # 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"));

Script аргументы должны быть числом, булевым, строковым, WebElement, или Список любой комбинации вышеуказанного. Исключение будет выбрано если аргументы не соответствуют этим критериям. Аргументы будут доступный для JavaScript через переменную "arguments".

Указано: executeAsyncScript в интерфейсе JavascriptExecutor Параметры: script - JavaScript для выполнения. args - Аргументы к script. Может быть пустым. Возвращает: один из булевых, длинных, строковых, List, WebElement или null.

Подробная документация здесь

Ответ 2

(Сохраняя его простым и правильным.)

Соответствующее различие между execteScript и executeAsyncScript таково:

Функция, вызываемая с помощью executeAsyncScript, принимает "завершенный обратный вызов" в качестве последнего аргумента, который должен вызываться, чтобы сигнализировать, что выполняется script.

Это позволяет использовать его с кодом, который только "заканчивается" при обратном вызове - например. setTimeout или асинхронный XHR. Если "сделанный обратный вызов" не вызывается в пределах тайм-аута, возвращаемое обещание будет отклонено.

В отличие от выполнения синхронного JavaScript С#executeScript, скрипты, выполняемые с помощью [#executeAsyncScript], должны явно сигнализировать, что они завершены вызовом предоставленного обратного вызова. Этот обратный вызов всегда будет введен в исполняемую функцию в качестве последнего аргумента.

То есть обе функции блокируют поток управления WebDriver до тех пор, пока они не закончатся - либо закончите конец кода для executeScript, либо при вызове 'done callback' с executeAsyncScript: "async" в названии означает используемый механизм сигнала и не означает/подразумевает, что код JavaScript фактически выполняется асинхронно в отношении WebDriver.

Ответ 3

Основное различие между ними заключается в том, что скрипты, выполняемые с помощью async, должны явно сигнализировать, что они завершены, вызвав предоставленный обратный вызов. Этот обратный вызов всегда вводится в исполняемую функцию как последний аргумент.

Ответ 4

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

отобразит предупреждение:

((JavascriptExecutor)).executeAsyncScript() используется, когда JS требует времени для выполнения, например, в вызове веб-службы.

window.onload гарантирует, что JS выполняется, когда страница полностью загружена.

Ответ 5

Я использовал много времени, чтобы выполнить эту функцию, и, наконец, я ее получил. Код follwing поможет много:

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

}