I'm writing a RSpec test suite of our routes for a rather large Rails 3 application. Many of the routes use "MATCH", but none of them should, especially since we'll have to rewrite them as we transition to Rails 4.
Most of my it
blocks look something like this:
it "with /comments/account/100" do
expect(get("comments/account/100")).to route_to("comments#list", :account_id => "100")
expect(post("comments/account/100")).to route_to("comments#list", :account_id => "100")
expect(put("comments/account/100")).to route_to("comments#list", :account_id => "100")
expect(delete("comments/account/100")).to route_to("comments#list", :account_id => "100")
end
It seems a bit, non-DRY, to have to write an endless number of blocks like that. I'd like to have a matcher that looks something like this:
expect(match_all_verbs("/comments/accounts/100")).to route_to("comments#list", :account_id => "100")
EDIT: Final working version, thanks to Steven:
def match_all_verbs(path, method, options = {})
[:get, :post, :put, :delete].each do |verb|
expect(send(verb, path)).to route_to(method, options)
end
end
I added an options
hash so I could pass params to the routes. Everything seems to be working fine.
And for fun, I made a match_no_verbs
to test the .to_not be_routable
matcher combo:
def match_no_verbs(path, method, options = {})
[:get, :post, :put, :delete].each do |verb|
expect(send(verb, path)).to_not route_to(method, options)
end
end
Thanks so much!
RSpec custom matchers take a single value per the documentation, so your formal parameter
values
is not getting defined and your reference to it in the body of your matcher fails.Rather than a custom matcher, whose intent is to specify what equality means and how to display errors for a given type of object, I think you'd want to use some kind of helper which iterates over the verbs and generates the appropriate
expect
calls.For example, you could use (not tested):