I have this route to the user_friendships
controller's block
action:
block_user_friendship PUT /user_friendships/:id/block(.:format) user_friendships#block
All you need to know is that the block action requires an :id
.
I can test the action's resulting view in an rspec spec like this:
require 'spec_helper'
it "should not display the names of users who have a state of pending or requested" do
visit "/user_friendships/1/block"
page.should have_content("user with id of 1 blocked!")
end
But this is a bit of a brittle spec because the URL is hardcoded. How can I populate the :id
entry of the params hash using the block_user_friendship_path
variable?
This, for example, doesn't work:
require 'spec_helper'
it "should not display the names of users who have a state of pending or requested" do
visit block_user_friendship_path, id: "/23"
page.should have_content("user with id of 23 blocked!")
end
(Results in No route matches {:action=>"block", :controller=>"user_friendships"} missing required keys: [:id]
)
Capybara is intended to be used for full-stack integration tests, so the recommended approach would be to avoid hardcoding URLs and instead drive Capybara to navigate through your app as a user would. This ensures that the links to the block path that are supposed to appear in your app where they're supposed to, and that they work when you click them.
Visiting the URL directly skips that, and if you need to make a PUT
request instead of a GET
request, it won't work correctly since visit
is the equivalent of pasting a URL into your browser address bar: it always issues a GET
request.
If it is working with a fully hardcoded URL, then you might want to check your routes definition. If blocking a user works on a simple GET
request, this could be used in a CSRF attack. Destructive operations should never be triggered by GET
requests.
Alex Lynham's answer describes a Rails/RSpec controller test, not a Capybara integration test, and if you want something lower level that does not exercise the entire stack, a controller test like the one suggested in that answer is a good way to go.