Reputation: 1236
I have the following rspec fragment:
describe "Save should create a ClassificationScheme" do
subject { lambda { click_button "Save"; sleep 1 } }
it { should change(ClassificationScheme, :count).by(1)
end
Without the "sleep 1" capybara doesn't wait for the action fired by the save button and the spec fails. With the sleep 1 is OK, but is there any better solution?
Note, that this test is running in Firefox using selenium webdriver.
My versions:
Upvotes: 1
Views: 2377
Reputation: 49870
When you click something using Capybara there is no guarantee any actions triggered by that click have completed when the method returns. This is because Capybara knows nothing about what the browser is doing other than that it clicked an element on the screen. Instead of sleeping you need to check for something that visually changes on the page to indicate the action triggered by clicking the button has completed. That may be a message stating the save happened successfully or an element disappearing, etc. Something along the lines of
describe "Save should create a ClassificationScheme" do
subject { lambda { click_button "Save"; page.should have_text('Classification Saved' } }
it { should change(ClassificationScheme, :count).by(1)
end
Note: you should also update Capybara - 2.4.4 was released in October of 2014, there have been a lot of improvements since then.
Upvotes: 2
Reputation: 17323
You didn't include code for your submit action, but if there's anything asynchronous going on, like an Ajax request, the submit action itself will finish quickly, while the async task is still processing the request. If that's the case, you can use a helper like this:
# spec/support/wait_for_ajax.rb
module WaitForAjax
def wait_for_ajax
Timeout.timeout(Capybara.default_max_wait_time) do
loop until finished_all_ajax_requests?
end
end
def finished_all_ajax_requests?
page.evaluate_script('jQuery.active').zero?
end
end
RSpec.configure do |config|
config.include WaitForAjax, type: :feature
end
Code courtesy Thoughtbot.
Note that this only includes the helper in feature specs; so either tag your specs with type: :feature
, or change the config.include
line above to include it in whatever spec type you're using.
To use it:
describe "Save should create a ClassificationScheme" do
subject { lambda { click_button "Save"; wait_for_ajax } }
it { should change(ClassificationScheme, :count).by(1)
end
Upvotes: 0