Как вызвать асинхронную функцию JavaScript из ruby с капибарой?

1

У меня есть несколько тестов E2E для приложения с поперечной платформой Ionic. Тесты написаны на Ruby, и они используют appium_capybara, водосвинку и селен WebDriver.

Приложение Ionic имеет функцию async javascript, которая может использоваться с консоли разработчика для входа в приложение. Я хочу вызвать это из тестов, и мне удалось сделать это из Ruby с помощью функции, называемой valu_async_script.

Однако, хотя у меня есть доказательство того, что функция async фактически выполняется, я получаю эту ошибку от Ruby:

Сроки ожидания асинхронного результата скрипта после 10033 мс (Selenium :: WebDriver :: Error :: ScriptTimeoutError)

Почему это происходит? Любые предложения о том, как заставить его работать?

Функция async выглядит примерно так:

export async function signin(user: string, pass: string,
                             callback: (result: object) => object): 
Promise<object> {
    if (typeof(window.authService) === 'object') {
        const credentials: ICredentials = {
            email: user,
            password: pass,
            rememberMe: false
        };

        await window.authService.authenticate(credentials);

        const result = { message: 'YES!!' };
        callback(result);
        return result;
    }
    return { message: 'EMPTY STRING!!' };
}

Вызов Ruby выглядит следующим образом:

result = Capybara.current_session
    .evaluate_async_script("window.signin('#{user.email}',
        '#{user.password}', (result) => { return result; })
            .then(function(value) { alert(value.message); })")

Появляется предупреждение, показывающее "ДА !!" сообщение, поэтому я знаю, что функция выполнена. Но по какой-то причине Ruby никогда не замечает, что функция закончена.

Теги:
appium
cucumber
capybara

1 ответ

1
Лучший ответ

Из документов для Session#evaluate_async_script - https://www.rubydoc.info/gems/capybara/Capybara/Session#evaluate_async_script-instance_method - важная часть - это "из функции обратного вызова, которая будет передана в качестве последнего аргумента скрипту ". Ваш скрипт не вызывает функцию обратного вызова, которая будет доступна в качестве arguments[0] поэтому у Capybara нет способа узнать, что это сделано.

Чтобы он работал, вам понадобилось бы что-то вроде (непроверенных)

result = Capybara.current_session.evaluate_async_script("
  var cb = arguments[0];
  window.signin('#{user.email}','#{user.password}', cb);")

Вы также можете передать адрес электронной почты и пароль в качестве аргументов

result = Capybara.current_session.evaluate_async_script('
  var cb = arguments[2];
  window.signin(arguments[0], arguments[1], cb);', user.email, user.password)

Обратите внимание, что это перемещает функцию обратного вызова в arguments[2], поскольку сначала вы передаете еще 2 аргумента.

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

  • 0
    Спасибо за ответ. Я проверю это, чтобы увидеть, работает ли это как можно скорее. Однако мне интересно, как выглядит интерфейс для функции, переданной в качестве аргументов [0]. Основываясь на документации, я предполагаю, что это (object) => object, так как Ruby должен получить результат из функции.
  • 0
    @StefanR. На самом деле, согласно спецификации WebDriver это должно быть (object) => undefined

Ещё вопросы

Сообщество Overcoder
Наверх
Меню