如何使用水豚从 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
调用它并等待可见页面正常更改。
我有一些针对跨平台 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
调用它并等待可见页面正常更改。