1
0
Fork 0
mirror of https://github.com/thoughtbot/shoulda-matchers.git synced 2022-11-09 12:01:38 -05:00
thoughtbot--shoulda-matchers/lib/shoulda/matchers/action_controller/set_flash_matcher.rb
2015-02-09 10:52:51 -07:00

297 lines
7.8 KiB
Ruby

module Shoulda
module Matchers
module ActionController
# The `set_flash` matcher is used to make assertions about the
# `flash` hash.
#
# class PostsController < ApplicationController
# def index
# flash[:foo] = 'A candy bar'
# end
#
# def destroy
# end
# end
#
# # RSpec
# describe PostsController do
# describe 'GET #index' do
# before { get :index }
#
# it { should set_flash }
# end
#
# describe 'DELETE #destroy' do
# before { delete :destroy }
#
# it { should_not set_flash }
# end
# end
#
# # Test::Unit
# class PostsControllerTest < ActionController::TestCase
# context 'GET #index' do
# setup { get :index }
#
# should set_flash
# end
#
# context 'DELETE #destroy' do
# setup { delete :destroy }
#
# should_not set_flash
# end
# end
#
# #### Qualifiers
#
# ##### []
#
# Use `[]` to narrow the scope of the matcher to a particular key.
#
# class PostsController < ApplicationController
# def index
# flash[:foo] = 'A candy bar'
# end
# end
#
# # RSpec
# describe PostsController do
# describe 'GET #index' do
# before { get :index }
#
# it { should set_flash[:foo] }
# it { should_not set_flash[:bar] }
# end
# end
#
# # Test::Unit
# class PostsControllerTest < ActionController::TestCase
# context 'GET #index' do
# setup { get :show }
#
# should set_flash[:foo]
# should_not set_flash[:bar]
# end
# end
#
# ##### to
#
# Use `to` to assert that some key was set to a particular value, or that
# some key matches a particular regex.
#
# class PostsController < ApplicationController
# def index
# flash[:foo] = 'A candy bar'
# end
# end
#
# # RSpec
# describe PostsController do
# describe 'GET #index' do
# before { get :index }
#
# it { should set_flash.to('A candy bar') }
# it { should set_flash.to(/bar/) }
# it { should set_flash[:foo].to('bar') }
# it { should_not set_flash[:foo].to('something else') }
# end
# end
#
# # Test::Unit
# class PostsControllerTest < ActionController::TestCase
# context 'GET #index' do
# setup { get :show }
#
# should set_flash.to('A candy bar')
# should set_flash.to(/bar/)
# should set_flash[:foo].to('bar')
# should_not set_flash[:foo].to('something else')
# end
# end
#
# ##### now
#
# Use `now` to change the scope of the matcher to use the "now" hash
# instead of the usual "future" hash.
#
# class PostsController < ApplicationController
# def show
# flash.now[:foo] = 'bar'
# end
# end
#
# # RSpec
# describe PostsController do
# describe 'GET #show' do
# before { get :show }
#
# it { should set_flash.now }
# it { should set_flash[:foo].now }
# it { should set_flash[:foo].to('bar').now }
# end
# end
#
# # Test::Unit
# class PostsControllerTest < ActionController::TestCase
# context 'GET #index' do
# setup { get :show }
#
# should set_flash.now
# should set_flash[:foo].now
# should set_flash[:foo].to('bar').now
# end
# end
#
# @return [SetFlashMatcher]
#
def set_flash
SetFlashMatcher.new
end
# @private
class SetFlashMatcher
def initialize
@options = {}
@value = nil
end
def to(value)
if !value.is_a?(String) && !value.is_a?(Regexp)
raise "cannot match against #{value.inspect}"
end
@value = value
self
end
def now
@options[:now] = true
self
end
def [](key)
@options[:key] = key
self
end
def matches?(controller)
@controller = controller
sets_the_flash? && string_value_matches? && regexp_value_matches?
end
def description
description = "set the #{expected_flash_invocation}"
description << " to #{@value.inspect}" unless @value.nil?
description
end
def failure_message
"Expected #{expectation}"
end
alias failure_message_for_should failure_message
def failure_message_when_negated
"Did not expect #{expectation}"
end
alias failure_message_for_should_not failure_message_when_negated
private
def sets_the_flash?
flash_values.any?
end
def string_value_matches?
if @value.is_a?(String)
flash_values.any? {|value| value == @value }
else
true
end
end
def regexp_value_matches?
if @value.is_a?(Regexp)
flash_values.any? {|value| value =~ @value }
else
true
end
end
def flash_values
if @options.key?(:key)
flash_hash = HashWithIndifferentAccess.new(flash.to_hash)
[flash_hash[@options[:key]]]
else
flash.to_hash.values
end
end
def flash
@flash ||= copy_of_flash_from_controller
end
def copy_of_flash_from_controller
@controller.flash.dup.tap do |flash|
copy_flashes(@controller.flash, flash)
copy_discard_if_necessary(@controller.flash, flash)
sweep_flash_if_necessary(flash)
end
end
def copy_flashes(original_flash, new_flash)
flashes = original_flash.instance_variable_get('@flashes').dup
new_flash.instance_variable_set('@flashes', flashes)
end
def copy_discard_if_necessary(original_flash, new_flash)
discard_ivar = :@discard
if original_flash.instance_variable_defined?(discard_ivar)
discard = original_flash.instance_variable_get(discard_ivar).dup
new_flash.instance_variable_set(discard_ivar, discard)
end
end
def sweep_flash_if_necessary(flash)
unless @options[:now]
flash.sweep
end
end
def expectation
expectation = "the #{expected_flash_invocation} to be set"
expectation << " to #{@value.inspect}" unless @value.nil?
expectation << ", but #{flash_description}"
expectation
end
def flash_description
if flash.blank?
'no flash was set'
else
"was #{flash.inspect}"
end
end
def expected_flash_invocation
"flash#{pretty_now}#{pretty_key}"
end
def pretty_now
if @options[:now]
'.now'
else
''
end
end
def pretty_key
if @options[:key]
"[:#{@options[:key]}]"
else
''
end
end
end
end
end
end