Cucumber: Wait for ajax:success
I have the following typical cucumber steps in a Rails 3.1 project:
...
When I follow "Remove from cart"
Then I should see "Test Product removed from cart"
The difficulty is that "Remove from cart" button is an ajax :remote call, which returns "Test Product removed from cart" to the #cart_notice element via:
$('#cart_notice').append("<%= @product.name %> removed from cart");开发者_Go百科
The function works fine in the browser, but doesn't find the "Test Product removed from cart" text in cucumber. I'm guessing this is because Cucumber is searching for the text before the AJAX returns it?
So, in short...how do I ensure cucumber waits for the ajax to return a result before searching for the desired content?
To add to what dexter said, you may want to write a step that executes JS in the browser which waits for ajax requests to finish. With jQuery, I use this step:
When /^I wait for the ajax request to finish$/ do
start_time = Time.now
page.evaluate_script('jQuery.isReady&&jQuery.active==0').class.should_not eql(String) until page.evaluate_script('jQuery.isReady&&jQuery.active==0') or (start_time + 5.seconds) < Time.now do
sleep 1
end
end
You can then include the step as needed, or after every javascript step:
AfterStep('@javascript') do
begin
When 'I wait for the ajax request to finish'
rescue
end
end
I was having issues with the automatic synchronization, and this cleared it up.
I guess you are using cucumber with capybara. In that case, capybara comes with a resynchronize
feature. "Capybara can block and wait for Ajax requests to finish after you’ve interacted with the page." - from capybara documentation
You can enable it in features/support/env.rb
Capybara.register_driver :selenium do |app|
Capybara::Driver::Selenium.new(app, :browser => browser.to_sym, :resynchronize => true)
end
But, I have seen this causing timeout issues. So, if that isn't working for you, I would recommend introducing a manual wait step before asserting the results of the ajax request.
...
When I follow "Remove from cart"
And I wait for 5 seconds
Then I should see "Test Product removed from cart"
You can define the wait step in step_definitions/web_steps.rb
as
When /^I wait for (\d+) seconds?$/ do |secs|
sleep secs.to_i
end
I suppose wait_until
should do the job. It will command to capybara
to check something until its true for some time.
Old question, but the Spreewald gem should help https://github.com/makandra/spreewald
You can use the patiently method from the Spreewald gem like so:
Then /^I should see "([^\"]*)" in the HTML$/ do |text|
patiently do
page.body.should include(text)
end
end
The step will maintain a loop for a period of time until the desired text appears in the test dom, else the step will fail.
(taken from https://makandracards.com/makandra/12139-waiting-for-page-loads-and-ajax-requests-to-finish-with-capybara)
精彩评论