等待 Websocket Rails 事件在测试环境中完成
Wait for Websocket Rails event to finish in test environment
我在我的 Rails 应用程序中使用 Websocket Rails gem 来发送触发部分页面刷新的事件。一切正常,但在我的测试中(我使用的是 Rspec + Capybara + Selenium)我似乎找不到等待页面响应 Websocket 事件的方法。我在我的测试中触发事件:
WebsocketRails[@michael.id].trigger "refresh_task", {task: @michaels_task, modified_by: @archer}
活动绑定如下。 ajax 调用 returns 一个实际上是另一个 ajax 调用的脚本。
channel.bind('refresh_task', function(task_user) {
var task = task_user["task"];
var modified_by = task_user["modified_by"];
if ($('span[data-mahi-task-id="' + task.id +'"]').length > 0) {//if the task is currently visible
if ($('span[data-mahi-task-id="' + task.id +'"] div.modal').length > 0 ) { //the edit is open, so prompt the user
refresh_task = confirm(modified_by.name + " has modified this task, do you want to re-load? (if you don't re-load you risk overwriting their changes)");
} else {
refresh_task = true;
}
if (refresh_task == true) {
//hide the modal if it exists
$('span[data-mahi-task-id="' + task.id +'"] div.modal').modal('hide');
//grey out the task while we load => this will get removed in ready.js
$('span[data-mahi-task-id="' + task.id +'"]').addClass('ajax-disabled');
// fake a "cancel" button on the update user task which will trigger a re-load of the task
$.ajax({
url: "/users/" + task.created_by_id + "/tasks/" + task.id,
data: {task: task, update_details_cancel_button: "", _method:'put'}, //need to teel rails this is a put - not all browsers support put
dataType: 'script', //what format we expect the response to be - i.e. we want to execupte the resulting script
complete : ajaxComplete(task,modified_by),
method: 'POST' //not all browsers support put so send a POST with the data _method:'put' as above
});
}
}
});
一旦 ajax 开始,我可以告诉它 运行 并等待它完成,但我需要我的测试在触发事件和以某种方式启动 ajax 之间等待?
我通过编写一个接受代码块的辅助方法解决了这个问题。辅助方法记录当前时间,然后向 ajax 启动事件添加一个函数,该函数记录 ajax 在 sessionStorage 变量中启动的时间。然后我可以 运行 将代码块传递给方法并等待 ajax 开始,如下所示:
def wait_for_ajax_to_start
start_time = Time.now.to_f * 1000 #number of milliseconds
#attach a hander on ajaxstart to store the time ajax started in a sessionStorage variable called 'ajaxStarted'
page.evaluate_script('$(document).ajaxStart(function() {sessionStorage.ajaxStarted = $.now()})')
#run the code block passed to this method
yield
#wait until the ajax has started or timeout
Timeout.timeout(Capybara.default_wait_time) do #timeout after the default wait time
loop until (page.evaluate_script('sessionStorage.ajaxStarted') != nil) && (page.evaluate_script('sessionStorage.ajaxStarted').to_i >= start_time)
end
end
我这样调用辅助方法:
wait_for_ajax_to_start {
WebsocketRails[@michael.id].trigger "refresh_task", {task: @michaels_task, modified_by: @archer}
}
到目前为止,这似乎对我有用....
您的测试应该等待页面上由刷新引起的可见变化
我在我的 Rails 应用程序中使用 Websocket Rails gem 来发送触发部分页面刷新的事件。一切正常,但在我的测试中(我使用的是 Rspec + Capybara + Selenium)我似乎找不到等待页面响应 Websocket 事件的方法。我在我的测试中触发事件:
WebsocketRails[@michael.id].trigger "refresh_task", {task: @michaels_task, modified_by: @archer}
活动绑定如下。 ajax 调用 returns 一个实际上是另一个 ajax 调用的脚本。
channel.bind('refresh_task', function(task_user) {
var task = task_user["task"];
var modified_by = task_user["modified_by"];
if ($('span[data-mahi-task-id="' + task.id +'"]').length > 0) {//if the task is currently visible
if ($('span[data-mahi-task-id="' + task.id +'"] div.modal').length > 0 ) { //the edit is open, so prompt the user
refresh_task = confirm(modified_by.name + " has modified this task, do you want to re-load? (if you don't re-load you risk overwriting their changes)");
} else {
refresh_task = true;
}
if (refresh_task == true) {
//hide the modal if it exists
$('span[data-mahi-task-id="' + task.id +'"] div.modal').modal('hide');
//grey out the task while we load => this will get removed in ready.js
$('span[data-mahi-task-id="' + task.id +'"]').addClass('ajax-disabled');
// fake a "cancel" button on the update user task which will trigger a re-load of the task
$.ajax({
url: "/users/" + task.created_by_id + "/tasks/" + task.id,
data: {task: task, update_details_cancel_button: "", _method:'put'}, //need to teel rails this is a put - not all browsers support put
dataType: 'script', //what format we expect the response to be - i.e. we want to execupte the resulting script
complete : ajaxComplete(task,modified_by),
method: 'POST' //not all browsers support put so send a POST with the data _method:'put' as above
});
}
}
});
一旦 ajax 开始,我可以告诉它 运行 并等待它完成,但我需要我的测试在触发事件和以某种方式启动 ajax 之间等待?
我通过编写一个接受代码块的辅助方法解决了这个问题。辅助方法记录当前时间,然后向 ajax 启动事件添加一个函数,该函数记录 ajax 在 sessionStorage 变量中启动的时间。然后我可以 运行 将代码块传递给方法并等待 ajax 开始,如下所示:
def wait_for_ajax_to_start
start_time = Time.now.to_f * 1000 #number of milliseconds
#attach a hander on ajaxstart to store the time ajax started in a sessionStorage variable called 'ajaxStarted'
page.evaluate_script('$(document).ajaxStart(function() {sessionStorage.ajaxStarted = $.now()})')
#run the code block passed to this method
yield
#wait until the ajax has started or timeout
Timeout.timeout(Capybara.default_wait_time) do #timeout after the default wait time
loop until (page.evaluate_script('sessionStorage.ajaxStarted') != nil) && (page.evaluate_script('sessionStorage.ajaxStarted').to_i >= start_time)
end
end
我这样调用辅助方法:
wait_for_ajax_to_start {
WebsocketRails[@michael.id].trigger "refresh_task", {task: @michaels_task, modified_by: @archer}
}
到目前为止,这似乎对我有用....
您的测试应该等待页面上由刷新引起的可见变化