如何使用水豚从 ruby 调用异步 javascript 函数?

How to call async javascript function from ruby with capybara?

我有一些针对跨平台 Ionic 应用程序的 E2E 测试。测试用 Ruby 编写,并使用 appium_capybara, capybara and selenium-webdriver.

Ionic 应用程序有一个异步 javascript 功能,可以从开发者控制台使用它来登录应用程序。我想从测试中调用它,我设法从 Ruby 中使用一个名为 evaluate_async_script.

的函数来做到这一点

然而,虽然我有证据证明异步函数确实被执行了,但我从 Ruby 得到了这个错误:

Timed out waiting for asyncrhonous script result after 10033 ms (Selenium::WebDriver::Error::ScriptTimeoutError)

为什么会这样?关于如何让它发挥作用有什么建议吗?

异步函数看起来像这样:

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

弹出警报显示 'YES!!' 消息,所以我知道函数已执行。但是由于某种原因 Ruby 从未注意到函数已经完成。

来自 Session#evaluate_async_script 的文档 - https://www.rubydoc.info/gems/capybara/Capybara/Session#evaluate_async_script-instance_method - 重要部分是 "from a callback function which will be passed as the last argument to the script"。您的脚本没有调用可作为 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。仅当您确实需要异步函数的响应时才需要它,否则您可以使用 execute_script 调用它并等待可见页面正常更改。