Kainan Zhang
Kainan Zhang

Reputation: 33

fail to rspec before_filters

I am new to Rails and I am using Boti's evolved way to test my project, however I got the following error:

> Failures:

  1) ApplicationController UploadsController admin_only should filter :before and {:with=>:admin_only, :except=>:show}
     Failure/Error: extra = -> (x) { x.options[:unless].include?( "action_name == '#{filter[:except]}'") }

     NoMethodError:
       undefined method `options' for #<ActiveSupport::Callbacks::Callback:0x000006060f6598>
     # ./spec/support/matchers/filter.rb:5:in `block (3 levels) in <top (required)>'
     # ./spec/support/matchers/filter.rb:9:in `call'
     # ./spec/support/matchers/filter.rb:9:in `block (3 levels) in <top (required)>'
     # ./spec/support/matchers/filter.rb:9:in `find'
     # ./spec/support/matchers/filter.rb:9:in `block (2 levels) in <top (required)>'
     # ./spec/controllers/application_controller_spec.rb:37:in `block (4 levels) in <top (required)>'

Could anyone help me out of this, thanks.

This is my spec:

RSpec.describe ApplicationController, type: :controller do
  include Devise::Test::ControllerHelpers
       describe UploadsController do
        context 'authentication' do
         specify{ expect(UploadsController).to filter(:before, with: :authenticate_user!)}
        end
        context 'admin_only' do
         specify{ expect(UploadsController).to filter(:before, with: :admin_only, except: :index)}
        end
      end
   end

This is controller

class UploadsController < ApplicationController
   before_action :authenticate_user!
   before_action :admin_only, :except => :index
   def index
    begin
      @uploads = Upload.all
    rescue
      redirect_to uploads_alert_uploads_path(:error_path => request.url, :error_time => DateTime.now)
    end
  end
end

This is matcher in spec/support/matchers/filter.rb

RSpec::Matchers.define :filter do |kind, filter|
  match do |controller|
    extra = -> (x) {true}
    if filter[:except].present?
      extra = -> (x) { x.options[:unless].include?( "action_name == '#{filter[:except]}'") }
    elsif filter[:only].present?
      extra = -> (x) { x.options[:if].include?( "action_name == '#{filter[:only]}'") }
    end
    controller._process_action_callbacks.find{|x|x.kind == kind && x.filter == filter[:with] && extra.call(x)}
  end
end

Upvotes: 0

Views: 154

Answers (1)

Joey
Joey

Reputation: 762

A better test would be to assert that a user cannot access the UploadsController (requests returns 404) and that an admin can (request returns 200).

Asserting that the filter is called ties your test to the implementation of the admin_only method and not the end result of limiting what a user can access.

Upvotes: 1

Related Questions