jhund / filterrific

Filterrific is a Rails Engine plugin that makes it easy to filter, search, and sort your ActiveRecord lists.
http://filterrific.clearcove.ca
MIT License
910 stars 124 forks source link

Filterrific form fails in rspec test #159

Open stevefolly opened 6 years ago

stevefolly commented 6 years ago

Testing a view with a Filteriffic form in rspec fails with the following error:

1) members/index renders a list of members
 Failure/Error: <%= form_for_filterrific @filterrific do |f| %>

 ActionView::Template::Error:
   No route matches {:action=>"index", :controller=>"test"}
 # /home/spfolly/.rvm/gems/ruby-2.3.0/gems/filterrific-5.0.1/lib/filterrific/action_view_extension.rb:19:in `form_for_filterrific'
 # ./app/views/members/index.html.erb:20:in `_app_views_members_index_html_erb__4554187109976153340_52575240'
 # ./spec/views/members/index.html.erb_spec.rb:42:in `block (2 levels) in <top (required)>'
 # ------------------
 # --- Caused by: ---
 # ActionController::UrlGenerationError:
 #   No route matches {:action=>"index", :controller=>"test"}
 #   /home/spfolly/.rvm/gems/ruby-2.3.0/gems/filterrific-5.0.1/lib/filterrific/action_view_extension.rb:19:in `form_for_filterrific'

Is the controller name 'test' a quirk of rspec? Do I need a 'test' route just for Filterrific rspec tests?

dan-jensen commented 6 years ago

After running into this same problem, just found it can be solved by stubbing the controller_name method on ActionView::TestCase::TestController.

Why: Rspec uses ActionView::TestCase::TestController as a generic controller for all view tests, hence the :controller=>"test" reported above. (Note: Rspec does consider namespaces. For example, if your view is located under a namespace of "admin", then the error will say no route matches :controller=>"admin/test".) Filterrific simply uses the controller's name by calling controller.controller_name (see https://github.com/jhund/filterrific/blob/master/lib/filterrific/action_view_extension.rb#L20). So in Rspec view tests, it's setting the controller name to "test". To get your test to pass you can stub controller_name to return a different value.

Example: This is a complete example of how I set up my Rspec view test. Only the first line is necessary to fix the problem described in this Issue, but I thought I'd include the rest because there doesn't seem to be much information online about testing code where Filterrific is in use.

  before(:each) do
    allow_any_instance_of(ActionView::TestCase::TestController).to receive(:controller_name).and_return('members') # CUSTOMIZE THIS; Fixes the "No route matches" problem
    @filterrific = Filterrific::ParamSet.new(User, {})
    @filterrific.select_options = {
      filter_role: User.filter_role_options,
      filter_status: User.filter_status_options,
    }
    @users = [ build_stubbed(:user) ]
  end
stevefolly commented 6 years ago

@dan-jensen this works a treat! Thank you :-)