single test failing after changing to capybara-webkit - ruby-on-rails-3

I have written some RSpec test for my rails 3.2 application and because I was annyoed by the Browser popping up ich tried to change from firefox to capybara-webkit.
After this all tests still run, except one. The line that is failing is:
expect { click_button "Create" }.to change(Answer, :count).by(count)
If I remove the expect and add a method to take a screenshot before and after, I can see that the test is run correctly. But if I step trough with the Debugger the log shows me that the records get created after the second screenshot line. I can wait forever the click_button and corresponding Controller action is run after the line next line is executed.
The "create" button is a standard html button, no JS is involved in the create action. Does sb have a explaination for this strange behaviour?

There is a race condition here between Capybara sending the click action to the server and your test checking the database.
The simplest way to resolve this is to wait before checking:
expect { click_button "Create"; sleep 2 }.to change(Answer, :count).by(count)
I don't like this. A better way to test this would be to check from the end user's perspective.
For example, after clicking 'Create', does the user see the answer on the answers page?
fill_in :title, :with => "My answer"
click_button 'Create'
page.should have_text "My answer"

Related

Capybara skipping over a click_button

I have a test that fills out some fields and then is supposed to click a button. This is all done after loading up a modal window. However, it seems that it just skips over it and doesn't click the button. I have tried debugging it manually and calling it myself and it'll work fine but when I run the test by itself it doesn't click it.
Given /^I login with "(.*?)" and "(.*?)"$/ do |email, password|
within "#signin_fields" do
fill_in("custom_fields_email", :with => email)
fill_in("custom_fields_password", :with => password)
end
click_button("Sign In") if page.should have_selector(".btn-signin")
end
I even added a check to make sure it was on the page but since the removal of wait_until, I'm not sure how I'm supposed to let the page load and then make sure it clicks the button properly. Any ideas would heavily appreciated.
This post may help: How do you get rspec to output what it encountered rather than it "didn't find what it expected"? Basically, for debugging, you can add the line save and open page and inspect what the spec is finding and whether it differs from the results of your own debugging.
The following row from your code is incorrect as have_selector is a RSpec matcher:
click_button("Sign In") if page.should have_selector(".btn-signin")
Instead you should use any of Capybara::Node::Matchers like:
click_button("Sign In") if page.has_selector?(".btn-signin")
page.should have_selector(".btn-signin") isn't going to return true or false and therefor the button will never be clicked. Just do this:
click_button(".btn-signin")
If it should be there then the test will fail if it doesn't appear on the page.

Capybara can't find link on the page

I'm trying to get my first capybara tests going. I following Ryan Bate's philosophy and putting some functional tests into my controller spec files.
describe UsersController do
render_views
it "can get the home page" do
get 'home'
response.body.should include("Login")
end
it "should log in" do
get 'home'
puts response.body
click_link('Login')
response.body.should include("Email")
response.body.should include("Password")
end
end
In it should login I ran into problems so began with just trying to make sure I can find and click the link. No luck. In the test as above I'm just trying to make sure the link exists
The puts response.body produces the following output
...
<div id="user_nav">
Register or Login
</div>
...
and I also see the element on the actual page. It seems only my test can't find it. The first test does pass.
1) UsersController should log in
Failure/Error: click_link('Login')
Capybara::ElementNotFound:
no link with title, id or text 'Login' found
# (eval):2:in `click_link'
# ./spec/controllers/users_controller_spec.rb:14:in `block (2 levels) in <top (required)>'
I'm using Rails 3.2, Rpsec 2.11 and Capybara 1.1.2.
(I've already checked the other questions on stackoverflow as well as a few tutorials and screencasts. I can't see any reason it can't find an element given an id tag, but I'm probably missing something obvious.
I think the reason it's not working is that you're using get for what is essentially an integration test. See this post: http://blog.plataformatec.com.br/2012/06/improving-the-integration-between-capybara-and-rspec/
If my understanding is correct, you need to use visit in order to use click_link on the page:
it "should log in" do
visit home_path
click_link('Login')
page.should ...
end
See also this answer on SO: Rspec and capybara, difference between visit and get methods, with regards to the current_path object

Rspec Request Spec, fails on form submit

I've got a simple scheduling application. I've got a request spec set up to run through the flow of adding a new workout to the schedule, and the form appears to hang on submit and the script bails after a few seconds. Running through it manually works fine, and my controller and model specs are all passing without complaint.
The only funky thing is I'm using execute_script to interact with the jquery datepicker, which seems to be working okay. Watching the execution shows that no error is happening, it's just hangs waiting for 127.0.0.1 to respond which doesn't seem to happen.
describe "Workouts" do
describe 'Create Workouts', js: true do
it 'Creates a new workout and displays the workout\'s page' do
visit workouts_path
expect {
click_link "New Workout"
fill_in 'workout_name', with: 'Workout!'
fill_in '', with: '05/01/2012'
page.execute_script %Q{ $('#workout_show_date').trigger("focus") }
page.execute_script %Q{ $("a.ui-state-default:contains('15')").trigger("click") }
select('6', from: 'workout_time_4i')
select('15', from: 'workout_time_5i')
click_button 'Create Workout'
}.to change(Workout,:count).by(1)
end
end
end
So after putting a sleep in the spec the error started returning that the database was locked, which google revealed to be a problem related to transactional fixtures being turned on. Turned that off and now all my specs are passing

Rails 3 RSpec and assert_select

I've thought to try to use Rspec. But I get a next problem with the assert_select.
1) UserController login page open login page contains all expected controls
Failure/Error: assert_select "form[action=?]", "/user/login" do MiniTest::Assertion:
Expected at least 1 element matching "form[action='/user/login']", found 0.
# (eval):2:in `assert'
# ./spec/controllers/user_controller_spec.rb:20:in `block (3 levels) in <top (required)>'
This is my code snippet
describe UserController do
describe "login page open" do
it "login page contains all expected controls" do
get :login
assert_select "form[action=?]", "/user/login" do
assert_select "input[name=?]", "username"
assert_select "input[name=?]", "password"
assert_select "input[type=?]", "submit"
end
end
end
When I open a login page in a browser this page opens without problem.
By default, RSpec (at least in newer versions) prevents Rails from rendering views when you run controller specs specs. They want you to test your views in view specs, not controller specs. Since the views don't render, assert_select always fails.
But for people who (like me) want to test the occasional snippet of a view in their controller specs, they provide a render_views method. You have to call it in your describe or context block, though, not inside the it block.
describe UserController do
render_views # <== ADD THIS
describe "login page open" do
it "login page contains all expected controls" do
get :login
assert_select "form[action=?]", "/user/login" do
assert_select "input[name=?]", "username"
assert_select "input[name=?]", "password"
assert_select "input[type=?]", "submit"
end
end
end
Controller tests are for testing controllers.
assert_select matches something that is in your view code.
It is a good idea keep your controllers separated from your views, and this includes tests done on controllers and on views. You should use assert_select in your views test (the ones that are usually on spec/views), not on your controller tests.

Rails 3 assert_select undefined method matches?

Trying to get started on view testing in Rails 3. I want to validate that I have a form getting kicked out in the view that has the right URL for the action. So I am using assert_select. I actually got a failing test first, using this syntax in the spec (using Rspec):
response.should assert_select "form[action=#{my_model_path}]"
Looking at the rendered HTML, sure enough, the view was rendering the 'edit' url, not the 'new' url due to the wrong model being passed down. Groovy, start red.
I make the model a 'new' one, and I look at my rendered output, and it's what I'd expect, BUT the test fails, and the error message says:
NoMethodError:
undefined method `matches?' for #<Array:0x0000012a1a5d58>
I've looked all over the web for this, found one guy that mentioned the error, but got no resolution. Any ideas?
Figured out that I could get this to work by nesting my assert_select calls, like so:
response.should assert_select "form" do
assert_select "[action=?]", my_model_path
end