Add SetSessionOrFlashMatcher
This commit is contained in:
parent
55c8d09bf2
commit
cc2772324a
|
@ -10,6 +10,7 @@ require 'shoulda/matchers/action_controller/render_template_matcher'
|
|||
require 'shoulda/matchers/action_controller/rescue_from_matcher'
|
||||
require 'shoulda/matchers/action_controller/callback_matcher'
|
||||
require 'shoulda/matchers/action_controller/strong_parameters_matcher'
|
||||
require 'shoulda/matchers/action_controller/set_session_or_flash_matcher'
|
||||
|
||||
module Shoulda
|
||||
module Matchers
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController
|
||||
# @private
|
||||
class SetSessionOrFlashMatcher
|
||||
def initialize(store)
|
||||
@store = store
|
||||
end
|
||||
|
||||
def in_context(context)
|
||||
@context = context
|
||||
self
|
||||
end
|
||||
|
||||
def [](key)
|
||||
@key = key
|
||||
self
|
||||
end
|
||||
|
||||
def to(expected_value = nil, &block)
|
||||
if block
|
||||
unless context_set?
|
||||
message = "When specifying a value as a block, a context must be specified beforehand, e.g., #{store.name}.in_context(context).to { ... }"
|
||||
raise ArgumentError, message
|
||||
end
|
||||
|
||||
@expected_value = context.instance_eval(&block)
|
||||
else
|
||||
@expected_value = expected_value
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
def description
|
||||
"should #{expectation_description}"
|
||||
end
|
||||
|
||||
def matches?(controller)
|
||||
@controller = store.controller = controller
|
||||
!store.empty? && key_matches? && expected_value_matches?
|
||||
end
|
||||
|
||||
def failure_message
|
||||
"Expected #{controller.class} to #{expectation_description}, but it did not"
|
||||
end
|
||||
alias_method :failure_message_for_should, :failure_message
|
||||
|
||||
def failure_message_when_negated
|
||||
"Expected #{controller.class} not to #{expectation_description}, but it did"
|
||||
end
|
||||
alias_method :failure_message_for_should_not,
|
||||
:failure_message_when_negated
|
||||
|
||||
protected
|
||||
|
||||
attr_reader :store, :context, :key, :expected_value, :controller
|
||||
|
||||
private
|
||||
|
||||
def context_set?
|
||||
defined?(@context)
|
||||
end
|
||||
|
||||
def key_set?
|
||||
defined?(@key)
|
||||
end
|
||||
|
||||
def expected_value_set?
|
||||
defined?(@expected_value)
|
||||
end
|
||||
|
||||
def key_matches?
|
||||
!key_set? || store.has_key?(key)
|
||||
end
|
||||
|
||||
def expected_value_matches?
|
||||
!expected_value_set? || store.has_value?(expected_value)
|
||||
end
|
||||
|
||||
def expectation_description
|
||||
string = 'set'
|
||||
|
||||
if key_set?
|
||||
string << " #{store.name}[#{key.inspect}]"
|
||||
else
|
||||
string << " any #{store.name} key"
|
||||
end
|
||||
|
||||
if expected_value_set?
|
||||
if expected_value.is_a?(Regexp)
|
||||
string << " to a value matching #{expected_value.inspect}"
|
||||
else
|
||||
string << " to #{expected_value.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
string
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,562 @@
|
|||
require 'unit_spec_helper'
|
||||
|
||||
describe Shoulda::Matchers::ActionController::SetSessionOrFlashMatcher do
|
||||
context 'without any qualifiers' do
|
||||
it 'produces the right description' do
|
||||
store = build_store(name: 'flash')
|
||||
matcher = described_class.new(store)
|
||||
expected_description = 'should set any key in flash'
|
||||
|
||||
expect(matcher.description).to eq expected_description
|
||||
end
|
||||
|
||||
context 'in the positive' do
|
||||
context 'if the store is not empty' do
|
||||
it 'accepts' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(empty?: false)
|
||||
matcher = described_class.new(store)
|
||||
|
||||
expect(controller).to matcher
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the store is empty' do
|
||||
it 'rejects' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(empty?: true)
|
||||
matcher = described_class.new(store)
|
||||
|
||||
expect(controller).not_to matcher
|
||||
end
|
||||
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash', empty?: true)
|
||||
matcher = described_class.new(store)
|
||||
expected_message = 'Expected MyController to set any key in flash, but it did not'
|
||||
|
||||
expect { expect(controller).to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in the negative' do
|
||||
context 'if the given key is present in the store' do
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash', empty?: false)
|
||||
matcher = described_class.new(store)
|
||||
expected_message = 'Expected MyController not to set any key in flash, but it did'
|
||||
|
||||
expect { expect(controller).not_to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with #[]' do
|
||||
it 'produces the right description' do
|
||||
store = build_store(name: 'flash')
|
||||
matcher = described_class.new(store)['the key']
|
||||
expected_description = 'should set flash["the key"]'
|
||||
|
||||
expect(matcher.description).to eq expected_description
|
||||
end
|
||||
|
||||
context 'in the positive' do
|
||||
context 'if the given key is present in the store' do
|
||||
it 'accepts' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(true)
|
||||
matcher = described_class.new(store)['the key']
|
||||
|
||||
expect(controller).to matcher
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the given key is not present in the store' do
|
||||
it 'rejects' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(false)
|
||||
matcher = described_class.new(store)['the key']
|
||||
|
||||
expect(controller).not_to matcher
|
||||
end
|
||||
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(false)
|
||||
matcher = described_class.new(store)['the key']
|
||||
expected_message = 'Expected MyController to set flash["the key"], but it did not'
|
||||
|
||||
expect { expect(controller).to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in the negative' do
|
||||
context 'if the given key is present in the store' do
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(true)
|
||||
matcher = described_class.new(store)['the key']
|
||||
expected_message = 'Expected MyController not to set flash["the key"], but it did'
|
||||
|
||||
expect { expect(controller).not_to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with #to' do
|
||||
context 'given a static value' do
|
||||
it 'produces the right description' do
|
||||
store = build_store(name: 'flash')
|
||||
matcher = described_class.new(store).to('the value')
|
||||
expected_description = 'should set any key in flash to "the value"'
|
||||
|
||||
expect(matcher.description).to eq expected_description
|
||||
end
|
||||
|
||||
context 'in the positive' do
|
||||
context 'if the given value is present in the store' do
|
||||
it 'accepts' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(true)
|
||||
matcher = described_class.new(store).to('the value')
|
||||
|
||||
expect(controller).to matcher
|
||||
end
|
||||
|
||||
it 'accepts given a value of nil' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_value?).
|
||||
with(nil).
|
||||
and_return(true)
|
||||
matcher = described_class.new(store).to(nil)
|
||||
|
||||
expect(controller).to matcher
|
||||
end
|
||||
|
||||
it 'accepts given a value of false' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_value?).
|
||||
with(false).
|
||||
and_return(true)
|
||||
matcher = described_class.new(store).to(false)
|
||||
|
||||
expect(controller).to matcher
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the given value is not present in the store' do
|
||||
it 'rejects' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(false)
|
||||
matcher = described_class.new(store).to('the value')
|
||||
|
||||
expect(controller).not_to matcher
|
||||
end
|
||||
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(false)
|
||||
matcher = described_class.new(store).to('the value')
|
||||
expected_message = 'Expected MyController to set any key in flash to "the value", but it did not'
|
||||
|
||||
expect { expect(controller).to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in the negative' do
|
||||
context 'if the given value is present in the store' do
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(true)
|
||||
matcher = described_class.new(store).to('the value')
|
||||
expected_message = 'Expected MyController not to set any key in flash to "the value", but it did'
|
||||
|
||||
expect { expect(controller).not_to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'given a regexp' do
|
||||
it 'produces the right description' do
|
||||
store = build_store(name: 'flash')
|
||||
matcher = described_class.new(store).to(/the value/)
|
||||
expected_description = 'should set any key in flash to a value matching /the value/'
|
||||
|
||||
expect(matcher.description).to eq expected_description
|
||||
end
|
||||
|
||||
context 'in the positive' do
|
||||
context 'if the given value is present in the store' do
|
||||
it 'accepts' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_value?).
|
||||
with(/the value/).
|
||||
and_return(true)
|
||||
matcher = described_class.new(store).to(/the value/)
|
||||
|
||||
expect(controller).to matcher
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the given value is not present in the store' do
|
||||
it 'rejects' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_value?).
|
||||
with(/the value/).
|
||||
and_return(false)
|
||||
matcher = described_class.new(store).to(/the value/)
|
||||
|
||||
expect(controller).not_to matcher
|
||||
end
|
||||
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_value?).
|
||||
with(/the value/).
|
||||
and_return(false)
|
||||
matcher = described_class.new(store).to(/the value/)
|
||||
expected_message = 'Expected MyController to set any key in flash to a value matching /the value/, but it did not'
|
||||
|
||||
expect { expect(controller).to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in the negative' do
|
||||
context 'if the given value is present in the store' do
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_value?).
|
||||
with(/the value/).
|
||||
and_return(true)
|
||||
matcher = described_class.new(store).to(/the value/)
|
||||
expected_message = 'Expected MyController not to set any key in flash to a value matching /the value/, but it did'
|
||||
|
||||
expect { expect(controller).not_to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'given a dynamic value' do
|
||||
it 'produces the right description' do
|
||||
store = build_store(name: 'flash')
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store).
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
expected_description = 'should set any key in flash to "the value"'
|
||||
|
||||
expect(matcher.description).to eq expected_description
|
||||
end
|
||||
|
||||
it 'requires in_context to be specified beforehand' do
|
||||
store = build_store(name: 'flash')
|
||||
matcher = described_class.new(store)
|
||||
expected_message = 'When specifying a value as a block, a context must be specified beforehand, e.g., flash.in_context(context).to { ... }'
|
||||
|
||||
expect { matcher.to { whatever } }.
|
||||
to raise_error(ArgumentError, expected_message)
|
||||
end
|
||||
|
||||
context 'in the positive' do
|
||||
context 'if the value evaluated in the context is present in the store' do
|
||||
it 'accepts' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(true)
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store).
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
|
||||
expect(controller).to matcher
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the value evaluated in the context is not present in the store' do
|
||||
it 'rejects' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(false)
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store).
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
|
||||
expect(controller).not_to matcher
|
||||
end
|
||||
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(false)
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store).
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
expected_message = 'Expected MyController to set any key in flash to "the value", but it did not'
|
||||
|
||||
expect { expect(controller).to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in the negative' do
|
||||
context 'if the value evaluated in the context is present in the store' do
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(true)
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store).
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
expected_message = 'Expected MyController not to set any key in flash to "the value", but it did'
|
||||
|
||||
expect { expect(controller).not_to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with #[] + #to' do
|
||||
context 'given a static value' do
|
||||
it 'produces the right description' do
|
||||
store = build_store(name: 'flash')
|
||||
matcher = described_class.new(store)['the key'].to('the value')
|
||||
expected_description = 'should set flash["the key"] to "the value"'
|
||||
|
||||
expect(matcher.description).to eq expected_description
|
||||
end
|
||||
|
||||
context 'in the positive' do
|
||||
context 'if the given value is present in the store' do
|
||||
it 'accepts' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(true)
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(true)
|
||||
matcher = described_class.new(store)['the key'].to('the value')
|
||||
|
||||
expect(controller).to matcher
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the given value is not present in the store' do
|
||||
it 'rejects' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(true)
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(false)
|
||||
matcher = described_class.new(store)['the key'].to('the value')
|
||||
|
||||
expect(controller).not_to matcher
|
||||
end
|
||||
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(true)
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(false)
|
||||
matcher = described_class.new(store)['the key'].to('the value')
|
||||
expected_message = 'Expected MyController to set flash["the key"] to "the value", but it did not'
|
||||
|
||||
expect { expect(controller).to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in the negative' do
|
||||
context 'if the given value is present in the store' do
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(true)
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(true)
|
||||
matcher = described_class.new(store)['the key'].to('the value')
|
||||
expected_message = 'Expected MyController not to set flash["the key"] to "the value", but it did'
|
||||
|
||||
expect { expect(controller).not_to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'given a dynamic value' do
|
||||
it 'produces the right description' do
|
||||
store = build_store(name: 'flash')
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store)['the key'].
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
expected_description = 'should set flash["the key"] to "the value"'
|
||||
|
||||
expect(matcher.description).to eq expected_description
|
||||
end
|
||||
|
||||
context 'in the positive' do
|
||||
context 'if the value evaluated in the context is present in the store' do
|
||||
it 'accepts' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(true)
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(true)
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store)['the key'].
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
|
||||
expect(controller).to matcher
|
||||
end
|
||||
end
|
||||
|
||||
context 'if the value evaluated in the context is not present in the store' do
|
||||
it 'rejects' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(false)
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store)['the key'].
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
|
||||
expect(controller).not_to matcher
|
||||
end
|
||||
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(false)
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store)['the key'].
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
expected_message = 'Expected MyController to set flash["the key"] to "the value", but it did not'
|
||||
|
||||
expect { expect(controller).to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in the negative' do
|
||||
context 'if the value evaluated in the context is present in the store' do
|
||||
it 'produces the correct failure message' do
|
||||
controller = define_class('MyController').new
|
||||
store = build_store(name: 'flash')
|
||||
allow(store).to receive(:has_key?).
|
||||
with('the key').
|
||||
and_return(true)
|
||||
allow(store).to receive(:has_value?).
|
||||
with('the value').
|
||||
and_return(true)
|
||||
context = double('context', method_in_context: 'the value')
|
||||
matcher = described_class.new(store)['the key'].
|
||||
in_context(context).
|
||||
to { method_in_context }
|
||||
expected_message = 'Expected MyController not to set flash["the key"] to "the value", but it did'
|
||||
|
||||
expect { expect(controller).not_to matcher }.
|
||||
to fail_with_message(expected_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_store(overrides = {})
|
||||
defaults = {
|
||||
:name => 'store',
|
||||
:controller= => nil,
|
||||
:has_key? => nil,
|
||||
:has_value? => nil,
|
||||
:empty? => nil,
|
||||
}
|
||||
methods = defaults.merge(overrides)
|
||||
double('store', methods)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue