module Clearance module Testing # Provides matchers to be used in your controller specs. # These are typically exposed to your controller specs by # requiring `clearance/rspec` or `clearance/test_unit` as # appropriate in your `rails_helper.rb` or `test_helper.rb` # files. module Matchers # The `deny_access` matcher is used to assert that a # request is denied access by clearance. # @option opts [String] :flash The expected flash notice message. Defaults # to nil, which means the flash will not be checked. # @option opts [String] :redirect The expected redirect url. Defaults to # `'/'` if signed in or the `sign_in_url` if signed out. # # class PostsController < ActionController::Base # before_action :require_login # # def index # @posts = Post.all # end # end # # describe PostsController do # describe "#index" do # it "denies access to users not signed in" do # get :index # # expect(controller).to deny_access # end # end # end def deny_access(opts = {}) DenyAccessMatcher.new(self, opts) end # @api private class DenyAccessMatcher attr_reader :failure_message, :failure_message_when_negated def initialize(context, opts) @context = context @flash = opts[:flash] @url = opts[:redirect] @failure_message = '' @failure_message_when_negated = '' end def description 'deny access' end def matches?(controller) @controller = controller sets_the_flash? && redirects_to_url? end def failure_message_for_should failure_message end def failure_message_for_should_not failure_message_when_negated end private def denied_access_url if clearance_session.signed_in? Clearance.configuration.redirect_url else @controller.sign_in_url end end def clearance_session @controller.request.env[:clearance] end def flash_notice @controller.flash[:notice] end def flash_notice_value if flash_notice.respond_to?(:values) flash_notice.values.first else flash_notice end end def redirects_to_url? @url ||= denied_access_url begin @context.send(:assert_redirected_to, @url) @failure_message_when_negated << "Didn't expect to redirect to #{@url}." true rescue MiniTest::Assertion, ::Test::Unit::AssertionFailedError @failure_message << "Expected to redirect to #{@url} but did not." false end end def sets_the_flash? if @flash.blank? true else if flash_notice_value == @flash @failure_message_when_negated << "Didn't expect to set the flash to #{@flash}" true else @failure_message << "Expected the flash to be set to #{@flash} "\ "but was #{flash_notice_value}" false end end end end end end end