I want to spec my controllers before_filter with rspec. I thought to use ActionController::Testing::ClassMethods#before_filters for it.
I got these results in my rails c:
2.0.0p353 :006 > ActionController::Base.singleton_class.send :include, ActionController::Testing::ClassMethods
2.0.0p353 :003 > EquipmentController.before_filters
=> [:process_action, :process_action]
But in reality this is the filter on my action:
class EquipmentController < ApplicationController
before_filter :authenticate_user!
Any ideas?
This is what I did in my project:
# spec/support/matchers/have_filters.rb
RSpec::Matchers.define :have_filters do |kind, *names|
match do |controller|
filters = controller._process_action_callbacks.select{ |f| f.kind == kind }.map(&:filter)
names.all?{ |name| filters.include?(name) }
end
end
# spec/support/controller_macros.rb
module ControllerMacros
def has_before_filters *names
expect(controller).to have_filters(:before, *names)
end
end
# spec/spec_helper.rb
RSpec.configure do |config|
config.include ControllerMacros, type: :controller
end
and then you can just use it in controller specs like:
# spec/controllers/application_controller_spec.rb
require 'spec_helper'
describe ApplicationController do
describe 'class' do
it { has_before_filters(:authenticate_user) }
end
end
I figured out a way based on the source code from the ActionController::Testing::ClassMethods#before_filter
This will be my spec:
describe EquipmentController do
context 'authentication' do
specify{ expect(EquipmentController).to filter(:before, with: :authenticate_user!, only: :index)}
end
...
This is my 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With