问题
I have a form where when a user submits an ajax form with a single name field, a record is created that belongs to a Template object. This all works fine manually, but for some reason when I test this via rspec its telling me that the association was not created. Why isn't the template object updated here?
describe "edit page" do
before(:each) do
visit edit_admin_template_path(template)
end
context "form sections", js: true do
it "allows admin to create one" do
find("#btn-add-section").click
within('#new_form_section') do
fill_in 'Name', with: "Personal Info"
click_button "Create Section"
end
expect(template.form_sections.length).to eq(1)
end
end
end
This is the failure that I am getting
Failure/Error: expect(template.form_sections.length).to eq(1)
expected: 1
got: 0
(compared using ==)
UPDATE: just noticed this in the rspec output
An error occurred in an after hook
ActionView::Template::Error: undefined method `form_sections' for nil:NilClass
so its telling me that the template object does not exist, then its able to compare it afterwards?
UPDATE 2: So it appears that the issue is waiting for the ajax call to complete in capybara, before expecting. I added this to the spec and it now works, obviously I need to refacotr this to something better like a helper
it "allows admin to create one" do
find("#btn-add-section").click
within('#new_form_section') do
fill_in 'Name', with: "Personal Info"
click_button "Create Section"
end
sleep(10) #this waits for the request to complete
expect(template.form_sections.length).to eq(1)
end
回答1:
The key is telling rspec to wait for the ajax call to complete before doing any expectations. This is a great post on the solution that I used.
Thoughtbot - automatically wait for ajax wioth capybara
http://robots.thoughtbot.com/automatically-wait-for-ajax-with-capybara ""
回答2:
Just in case others stumble upon this, rather than using sleep you could test based on the UI itself. Capybara will wait for that element to reload, if you use have_css or find matchers, like this:
expect(page).to have_css("#form-page-two", visible: :visible) #this will force test to wait for ajax call
Capybara.automatic_reload must not be set to false. (defaults to true)
This strategy will reduce the run time of your test suite; if the test only took 2 or 3 seconds to load it will only wait that long (not 10).
However, it can be frustrating to write because of intermittent failures. To avoid this you may need to bump up the wait time setting.
Capybara.default_max_wait_time = 10
https://github.com/teamcapybara/capybara#asynchronous-javascript-ajax-and-friends
来源:https://stackoverflow.com/questions/27967849/rspec-capybara-test-with-ajax-call-not-updating-record