Search code examples
ruby-on-rails-4rspec-rails

Proper way to seed routes for view spec


I am testing my views with RSpec. Due to some changes, there is now a call to url_for in the view and all the spec that I wrote for show actions are failing:

No route matches {:controller=>"events", :action=>"show"}

The :id part is missing and because of that the call fails.

(I know that I can just stub that failing method call)

The only thing I found is pretty old and looks like a bad workaround. Also the RSpec documentation does not show something helpful.

Is there a proper way to tell RSpec that it should be on something like events/123?

Some more context:

In the view I call a helper, something like this:

def some_helper_method
  url_for(only_path: false)} + "something_else"
end

The call to that method fails with

 Failure/Error: render
 ActionView::Template::Error:
   No route matches {:controller=>"events", :action=>"show"}

I'm currently fixing it by stubbing the call to that method view.stub(some_helper_method: 'SOME_URL')


Solution

  • Okay, I think I found your answer. I cloned your repo and debug a lot =P until I found that you need to infer the desired parameters in your view spec, since rspec-rails only provides the :controller parameter for the view being rendered. Well, in an attempt to understand better what the issue is, I found this explanation in the rspec-rails documentation:

    View specs infer the controller name and path from the path to the view template. e.g. if the template is "events/index.html.erb" then:

    controller.controller_path == "events" controller.request.path_parameters[:controller] == "events"

    This means that most of the time you don't need to set these values. When spec'ing a partial that is included across different controllers, you may need to override these values before rendering the view

    In other words, the previous link that you posted still works and is still the solution for the parameters "issue" in your view spec. You can follow the discussion about the topic in this PullRequest thread.

    So, the conclusion is that if you really don't want to stub out your call to url_for helper (or the helper that is calling it), you need to supply the desired :id parameter since there's no route for any show action without an :id param (as pointed out by you). Our final result (tested) is indeed:

    controller.request.path_parameters[:id] = event.id

    If this a workaround ? I really don't think so, since rspec-rails itself is internally using this feature to provide the :controller param.

    I'm sorry I couldn't be more helpful before, but I think that this closes all of our main doubts.

    My opinion ? If you really don't need to make any assertions based on the url_for behavior (or any helper behavior for that matter), just stub it, since it is expected to already have been tested in isolation. Otherwise, use the :id param, and don't worry about it. It is not a workaround.

    Cheers friend !