Since rspec 3.5 request specs are used to test controller behaviour plus route testing and the correct rendering of the view with the content. The last part troubles me a bit since i do not understand the thin line of what goes in the view specs to what stays in the request specs.
On relishapp i found this piece:
expect(response.body).to include("Widget was successfully created.")
which tempted me of including the following in my request test:
describe "Index page" do
....
it 'includes a link to cars_parts' do
get "/car_overview"
expect(response.body).to include("car_parts_path")
end
....
end
This test fails.
In the view i use the link_to
on the car_parts url_helper
.
The failing test dumps the whole response.body String and i see the car_parts_path
but rspec does not see it. How do i have to change my test to make it pass without the use of capybara since it is only useable with feature specs now.
And am i doing it correct after all or should this kind of test go somewhere else?
I think you might need to change the string to a method.
expect(response.body).to include("car_parts_path")
expect(response.body).to include(car_parts_path) # Remove the quotes
car_parts_path
is a method in Rails, which will evaluate to the actual path. If you're using that URL helper in your view this should work.
But I thought the response body was a string?
Yup, it is. When you call car_parts_path
, you're calling a Ruby method in the Rails framework.
car_parts_path
will return a string. This string will be "/car_parts"
.
Basically, any time you see car_parts_path
, imagine it's "/car_parts"
as a string. Because the two are exactly equivalent.
In the test
So when you have this in the test:
expect(response.body).to include(car_parts_path) # car_parts_path is a method that returns "/car_parts" so it's the same as...
It's evaluates to the same as:
expect(response.body).to include("/car_parts")
In the view
In your ERB view you'll have:
<%= link_to "Car Parts", car_parts_path %>
This is evaluated to:
<%= link_to "Car Parts", "/car_parts" %>
This renders an a
tag in your html:
<a href="/car_parts">Car Parts</a>
You're checking for "/car_parts"
in the response body and the view contains that string, the test now passes and you're all set!
Why did my original code not work?
Rails was looking for "car_parts_path"
as a string - and the view doesn't contain that anywhere.
You were looking for the method name as a string rather than the string the method returns.
Any more questions, just ask!