I'm working on a application which consist of a EmberJS frontend, which talk to a Rails server via REST. In my application goes through a wizard to create a job, so i would like to test if that job is created, this is my test.
feature 'Processing step three', :js => true do
background do
to_step_2
to_step_3
end
scenario 'Creating job', js: true do
within '#login' do
fill_in 'Email', with: @customer.email
fill_in 'Password', with: @customer.password
click_button 'Login'
end
expect { click_link 'Create job' }.to change(Job, :count).by(1)
end
end
So when the user has filled in everything, lastly they click on create job, just like my test describes. This works fine when i do it manually, but when i run my spec i get.
1) Creating a new job Processing step three Creating job
Failure/Error: expect { click_link 'Create job' }.to change(Job, :count).by(1)
count should have been changed by 1, but was changed by 0
# ./spec/features/creating_a_new_job_spec.rb:103:in `block (3 levels) in <top (required)>'
Now if i look at my test log i can see, that capybara runs the count, before my job is inserted
Completed 200 OK in 36ms (Views: 6.0ms | ActiveRecord: 11.2ms)
Started POST "/api/jobs" for 127.0.0.1 at 2013-12-08 14:15:00 +0100
Processing by Api::JobsController#create as JSON
Parameters: {"job"=>{"description"=>"This is a test description of the service i would like to receive.", "zip"=>"2400", "available_from"=>"24 - 12 - 2013", "available_next"=>false, "customer_id"=>"1", "service_id"=>"1", "service_field_id"=>"1"}}
Unpermitted parameters: zip
(11.3ms) SELECT COUNT(*) FROM "jobs"
(1.2ms) BEGIN
SQL (2.5ms) INSERT INTO "jobs" ("available_from", "available_next", "created_at", "customer_id", "description", "service_field_id", "service_id", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["available_from", Tue, 24 Dec 2013 00:00:00 UTC +00:00], ["available_next", false], ["created_at", Sun, 08 Dec 2013 13:15:00 UTC +00:00], ["customer_id", 1], ["description", "This is a test description of the service i would like to receive."], ["service_field_id", 1], ["service_id", 0], ["updated_at", Sun, 08 Dec 2013 13:15:00 UTC +00:00]]
(0.5ms) COMMIT
How do i force Capybara to hold the sails a bit?
The main problem, as you said, it's Capybara didn't wait. But the main reason is the test doesn't use a consistent style.
If using Capybara, the test acts like a real user, and you should expect some UI change instead of database change, for real user can't see what happens in db.
In this test, the db assertion is executed right away, even faster than the browser driver sending data to server, so the data is nil.
To fix,
Remove the within
block at first. This seems unimportant. If I remembered correctly, the expectation should better not in different block of the action. So do it for safety.
Add UI expectation. Then Capybara will wait until the effect appears.
So,
scenario 'Creating job', js: true do
fill_in 'Email', with: @customer.email
fill_in 'Password', with: @customer.password
click_button 'Login'
# Assume your page will show user name after signing in
expect(page).to have_content(@customer.name)
end
If you really want to test db change, you can add that expectation after UI expectation, but I don't recommend that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With