1
0
Fork 0
mirror of https://github.com/thoughtbot/shoulda-matchers.git synced 2022-11-09 12:01:38 -05:00

Consolidate set_session and set_flash APIs

* Refactor so they both use SetSessionOrFlashMatcher internally
* Remove `set_session['key']` in favor of `set_session('key')`
* `set_flash['key'].to(nil)` no longer works if set_flash has never been
  set
This commit is contained in:
Elliot Winkler 2014-11-19 16:13:59 -07:00
parent 801f2c7c1e
commit 535fe05be8
10 changed files with 582 additions and 653 deletions

View file

@ -13,7 +13,13 @@
* `ensure_inclusion_of`, `ensure_exclusion_of`, and `ensure_length_of` have been
removed in favor of their `validate_*` counterparts.
* `set_the_flash` has been removed in favor of `set_flash`.
* `set_the_flash` and `set_session` have been changed to more closely align with
each other:
* `set_the_flash` has been removed in favor of `set_flash`.
* `set_session('foo')` is no longer valid syntax, please use
`set_session['foo']` instead.
* `set_session['key'].to(nil)` will no longer pass when the key in question
has not been set yet.
# 2.8.0

View file

@ -11,6 +11,8 @@ 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'
require 'shoulda/matchers/action_controller/flash_store'
require 'shoulda/matchers/action_controller/session_store'
module Shoulda
module Matchers

View file

@ -0,0 +1,95 @@
module Shoulda
module Matchers
module ActionController
# @private
class FlashStore
def self.future
new
end
def self.now
new.use_now!
end
attr_accessor :controller
def initialize
@use_now = false
end
def name
if @use_now
'flash.now'
else
'flash'
end
end
def has_key?(key)
values_to_check.include?(key)
end
def has_value?(expected_value)
values_to_check.values.any? do |actual_value|
expected_value === actual_value
end
end
def empty?
flash.empty?
end
def use_now!
@use_now = true
self
end
private
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 = original_flash.instance_variable_get('@discard').dup
new_flash.instance_variable_set('@discard', discard)
end
def sweep_flash_if_necessary(flash)
unless @use_now
flash.sweep
end
end
def set_values
flash.instance_variable_get('@flashes')
end
def keys_to_discard
flash.instance_variable_get('@discard')
end
def values_to_check
if @use_now
set_values.slice(*keys_to_discard.to_a)
else
set_values.except(*keys_to_discard.to_a)
end
end
end
end
end
end

View file

@ -0,0 +1,34 @@
module Shoulda
module Matchers
module ActionController
# @private
class SessionStore
attr_accessor :controller
def name
'session'
end
def has_key?(key)
session.key?(key)
end
def has_value?(expected_value)
session.values.any? do |actual_value|
expected_value === actual_value
end
end
def empty?
session.empty?
end
private
def session
controller.session
end
end
end
end
end

View file

@ -1,3 +1,5 @@
require 'forwardable'
module Shoulda
module Matchers
module ActionController
@ -146,151 +148,54 @@ module Shoulda
# @return [SetFlashMatcher]
#
def set_flash
SetFlashMatcher.new
SetFlashMatcher.new.in_context(self)
end
# @private
class SetFlashMatcher
def initialize
@options = {}
@value = nil
end
extend Forwardable
def to(value)
if !value.is_a?(String) && !value.is_a?(Regexp)
raise "cannot match against #{value.inspect}"
end
@value = value
self
def_delegators :underlying_matcher,
:description,
:matches?,
:failure_message,
:failure_message_when_negated
alias_method \
:failure_message_for_should,
:failure_message
alias_method \
:failure_message_for_should_not,
:failure_message_when_negated
def initialize
store = FlashStore.future
@underlying_matcher = SetSessionOrFlashMatcher.new(store)
end
def now
@options[:now] = true
store = FlashStore.now
@underlying_matcher = SetSessionOrFlashMatcher.new(store)
self
end
def in_context(context)
underlying_matcher.in_context(context)
self
end
def [](key)
@options[:key] = key
underlying_matcher[key]
self
end
def matches?(controller)
@controller = controller
sets_the_flash? && string_value_matches? && regexp_value_matches?
def to(expected_value = nil, &block)
underlying_matcher.to(expected_value, &block)
self
end
def description
description = "set the #{expected_flash_invocation}"
description << " to #{@value.inspect}" unless @value.nil?
description
end
protected
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
attr_reader :underlying_matcher
end
end
end

View file

@ -1,3 +1,5 @@
require 'forwardable'
module Shoulda
module Matchers
module ActionController
@ -112,132 +114,49 @@ module Shoulda
#
# @return [SetSessionMatcher]
#
def set_session(key = nil)
SetSessionMatcher.new(key)
def set_session
SetSessionMatcher.new.in_context(self)
end
# @private
class SetSessionMatcher
def initialize(key)
if key
Shoulda::Matchers.warn <<EOT
Passing a key to set_session is deprecated.
Please use the hash syntax instead (e.g., `set_session[:foo]`, not `set_session(:foo)`).
EOT
self[key]
end
extend Forwardable
@value_block = nil
end
def_delegators :underlying_matcher,
:description,
:matches?,
:failure_message,
:failure_message_when_negated
alias_method \
:failure_message_for_should,
:failure_message
alias_method \
:failure_message_for_should_not,
:failure_message_when_negated
def [](key)
@key = key.to_s
self
end
def to(value = nil, &block)
@value = value
@value_block = block
self
end
def matches?(controller)
@controller = controller
if @value_block
@value = @context.instance_eval(&@value_block)
end
if nil_value_expected_but_actual_value_unset?
Shoulda::Matchers.warn <<EOT
Using `should set_session[...].to(nil)` to assert that a variable is unset is deprecated.
Please use `should_not set_session[...]` instead.
EOT
end
if key_specified? && value_specified?
@value === session[@key]
elsif key_specified?
session.key?(@key)
elsif value_specified?
session.values.any? { |value| @value === value }
else
session_present?
end
end
def failure_message
"Expected #{expectation}, but #{result}"
end
alias failure_message_for_should failure_message
def failure_message_when_negated
"Didn't expect #{expectation}, but it was"
end
alias failure_message_for_should_not failure_message_when_negated
def description
"should #{expectation}"
def initialize
store = SessionStore.new
@underlying_matcher = SetSessionOrFlashMatcher.new(store)
end
def in_context(context)
@context = context
underlying_matcher.in_context(context)
self
end
private
def key_specified?
defined?(@key)
def [](key)
underlying_matcher[key]
self
end
def value_specified?
defined?(@value)
def to(expected_value = nil, &block)
underlying_matcher.to(expected_value, &block)
self
end
def value_or_default_value
defined?(@value) && @value
end
protected
def nil_value_expected_but_actual_value_unset?
value_specified? && @value.nil? && !session.key?(@key)
end
def session_present?
!session.empty?
end
def expectation
expectation = ""
if key_specified?
expectation << "session variable #{@key.inspect}"
else
expectation << "any session variable"
end
expectation << " to be"
if value_specified? && !@value.nil?
expectation << " #{@value.inspect}"
else
expectation << " set"
end
expectation
end
def result
if session_present?
"the session was #{session.inspect}"
else
'no session variables were set'
end
end
def session
@controller.session
end
attr_reader :underlying_matcher
end
end
end

View file

@ -84,7 +84,7 @@ module Shoulda
if key_set?
string << " #{store.name}[#{key.inspect}]"
else
string << " any #{store.name} key"
string << " any key in #{store.name}"
end
if expected_value_set?

View file

@ -0,0 +1,355 @@
shared_examples_for 'set session or flash matcher' do
context 'without any qualifiers' do
it 'produces the right description' do
expected_description = "should set any key in #{store_name}"
matcher = set_store
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 = controller_with_store('any key' => 'any value')
expect(controller).to set_store
end
end
context 'if the store is empty' do
it 'rejects' do
controller = controller_with_empty_store
expect(controller).not_to set_store
end
it 'produces the correct failure message' do
controller = controller_with_empty_store
expected_message = %<Expected #{controller.class} to set any key in #{store_name}, but it did not>
expect { expect(controller).to set_store }.
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 = controller_with_store('any key' => 'any value')
expected_message = %<Expected #{controller.class} not to set any key in #{store_name}, but it did>
assertion = proc do
expect(controller).not_to set_store
end
expect(&assertion).to fail_with_message(expected_message)
end
end
end
end
context 'with #[]' do
it 'produces the right description' do
matcher = set_store['the key']
expected_description = %<should set #{store_name}["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 = controller_with_store('the key' => 'any value')
expect(controller).to set_store['the key']
end
end
context 'if the given key is not present in the store' do
it 'rejects' do
controller = controller_with_empty_store
expect(controller).not_to set_store['the key']
end
it 'produces the correct failure message' do
controller = controller_with_empty_store
expected_message = %<Expected #{controller.class} to set #{store_name}["the key"], but it did not>
assertion = proc do
expect(controller).to set_store['the key']
end
expect(&assertion).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 = controller_with_store('the key' => 'any value')
expected_message = %<Expected #{controller.class} not to set #{store_name}["the key"], but it did>
assertion = proc do
expect(controller).not_to set_store['the key']
end
expect(&assertion).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
matcher = set_store.to('the value')
expected_description = %<should set any key in #{store_name} 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 = controller_with_store('any key' => 'the value')
expect(controller).to set_store.to('the value')
end
it 'accepts given a value of nil' do
controller = controller_with_store('any key' => nil)
expect(controller).to set_store.to(nil)
end
it 'accepts given a value of false' do
controller = controller_with_store('any key' => false)
expect(controller).to set_store.to(false)
end
end
context 'if the given value is not present in the store' do
it 'rejects' do
controller = controller_with_empty_store
expect(controller).not_to set_store.to('the value')
end
it 'rejects checking for nil' do
controller = controller_with_empty_store
expect(controller).not_to set_store.to(nil)
end
it 'produces the correct failure message' do
controller = controller_with_empty_store
expected_message = %<Expected #{controller.class} to set any key in #{store_name} to "the value", but it did not>
assertion = proc do
expect(controller).to set_store.to('the value')
end
expect(&assertion).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 = controller_with_store('any key' => 'the value')
expected_message = %<Expected #{controller.class} not to set any key in #{store_name} to "the value", but it did>
assertion = proc do
expect(controller).not_to set_store.to('the value')
end
expect(&assertion).to fail_with_message(expected_message)
end
end
end
end
context 'given a regexp' do
it 'produces the right description' do
matcher = set_store.to(/value/)
expected_description = %<should set any key in #{store_name} to a value matching /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 = controller_with_store('any key' => 'the value')
expect(controller).to set_store.to(/value/)
end
it 'accepts given a value of nil' do
controller = controller_with_store('any key' => nil)
expect(controller).to set_store.to(nil)
end
it 'accepts given a value of false' do
controller = controller_with_store('any key' => false)
expect(controller).to set_store.to(false)
end
end
context 'if the given value is not present in the store' do
it 'rejects' do
controller = controller_with_empty_store
expect(controller).not_to set_store.to(/value/)
end
it 'produces the correct failure message' do
controller = controller_with_empty_store
expected_message = %<Expected #{controller.class} to set any key in #{store_name} to a value matching /value/, but it did not>
assertion = proc do
expect(controller).to set_store.to(/value/)
end
expect(&assertion).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 = controller_with_store('any key' => 'the value')
expected_message = %<Expected #{controller.class} not to set any key in #{store_name} to a value matching /value/, but it did>
assertion = proc do
expect(controller).not_to set_store.to(/value/)
end
expect(&assertion).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
expected_description = %<should set #{store_name}["the key"] to "the value">
matcher = set_store['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 = controller_with_store('the key' => 'the value')
expect(controller).to set_store['the key'].to('the value')
end
end
context 'if the given value is not present in the store' do
it 'rejects' do
controller = controller_with_empty_store
expect(controller).not_to set_store['the key'].to('the value')
end
it 'produces the correct failure message' do
controller = controller_with_empty_store
expected_message = %<Expected #{controller.class} to set #{store_name}["the key"] to "the value", but it did not>
assertion = proc do
expect(controller).to set_store['the key'].to('the value')
end
expect(&assertion).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 = controller_with_store('the key' => 'the value')
expected_message = %<Expected #{controller.class} not to set #{store_name}["the key"] to "the value", but it did>
assertion = proc do
expect(controller).not_to set_store['the key'].to('the value')
end
expect(&assertion).to fail_with_message(expected_message)
end
end
end
end
context 'given a dynamic value' do
it 'produces the right description' do
context = double('context', method_in_context: 'the value')
matcher = set_store['the key'].
in_context(context).
to { method_in_context }
expected_description = %<should set #{store_name}["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 = controller_with_store('the key' => 'the value')
context = double('context', method_in_context: 'the value')
expect(controller).to set_store['the key'].
in_context(context).
to { method_in_context }
end
end
context 'if the value evaluated in the context is not present in the store' do
it 'rejects' do
controller = controller_with_empty_store
context = double('context', method_in_context: 'the value')
expect(controller).not_to set_store['the key'].
in_context(context).
to { method_in_context }
end
it 'produces the correct failure message' do
controller = controller_with_empty_store
context = double('context', method_in_context: 'the value')
expected_message = %<Expected #{controller.class} to set #{store_name}["the key"] to "the value", but it did not>
assertion = proc do
expect(controller).to set_store['the key'].
in_context(context).
to { method_in_context }
end
expect(&assertion).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
context = double('context', method_in_context: 'the value')
controller = controller_with_store('the key' => 'the value')
expected_message = %<Expected #{controller.class} not to set #{store_name}["the key"] to "the value", but it did>
assertion = proc do
expect(controller).not_to set_store['the key'].
in_context(context).
to { method_in_context }
end
expect(&assertion).to fail_with_message(expected_message)
end
end
end
end
end
def controller_with_empty_store
build_fake_response
end
def controller_with_store(store_contents)
context = self
build_fake_response do
store = context.store_within(self)
store_contents.each do |key, value|
store[key] = value
end
end
end
end

View file

@ -1,153 +1,43 @@
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController::SetFlashMatcher, type: :controller do
it 'fails with unmatchable #to' do
expect { set_flash.to(1) }.to raise_error('cannot match against 1')
end
context 'a controller that sets a flash message' do
it 'accepts setting any flash message' do
expect(controller_with_flash(notice: 'hi')).to set_flash
it_behaves_like 'set session or flash matcher' do
def store_name
'flash'
end
it 'accepts setting the exact flash message' do
expect(controller_with_flash(notice: 'hi')).to set_flash.to('hi')
def set_store
set_flash
end
it 'accepts setting a matched flash message' do
expect(controller_with_flash(notice: 'hello')).to set_flash.to(/he/)
end
it 'rejects setting a different flash message' do
expect(controller_with_flash(notice: 'hi')).
not_to set_flash.to('other')
end
it 'rejects setting a different pattern' do
expect(controller_with_flash(notice: 'hi')).
not_to set_flash.to(/other/)
def store_within(controller)
controller.flash
end
end
context 'a controller that sets a flash.now message' do
it 'rejects setting any flash message' do
expect(controller_with_flash_now).not_to set_flash
it_behaves_like 'set session or flash matcher' do
def store_name
'flash.now'
end
it 'accepts setting any flash.now message' do
expect(controller_with_flash_now).to set_flash.now
def set_store
set_flash.now
end
it 'accepts setting the exact flash.now message' do
expect(controller_with_flash_now(notice: 'hi')).
to set_flash.now.to('hi')
end
it 'accepts setting a matched flash.now message' do
expect(controller_with_flash_now(notice: 'flasher')).
to set_flash.now.to(/lash/)
end
it 'rejects setting a different flash.now message' do
expect(controller_with_flash_now(notice: 'hi')).
not_to set_flash.now.to('other')
end
it 'rejects setting a different flash.now pattern' do
expect(controller_with_flash_now(notice: 'hi')).
not_to set_flash.now.to(/other/)
def store_within(controller)
controller.flash.now
end
end
context 'a controller that sets flash messages for multiple keys' do
it 'accepts flash message for either key' do
controller = controller_with_flash(notice: 'one', alert: 'two')
expect(controller).to set_flash[:notice]
expect(controller).to set_flash[:alert]
end
it 'rejects a flash message that is not one of the set keys' do
expect(controller_with_flash(notice: 'one', alert: 'two')).
not_to set_flash[:warning]
end
it 'accepts exact flash message of notice' do
expect(controller_with_flash(notice: 'one', alert: 'two')).
to set_flash[:notice].to('one')
end
it 'accepts setting a matched flash message of notice' do
expect(controller_with_flash(notice: 'one', alert: 'two')).
to set_flash[:notice].to(/on/)
end
it 'rejects setting a different flash message of notice' do
expect(controller_with_flash(notice: 'one', alert: 'two')).
not_to set_flash[:notice].to('other')
end
it 'rejects setting a different pattern' do
expect(controller_with_flash(notice: 'one', alert: 'two')).
not_to set_flash[:notice].to(/other/)
end
end
context 'a controller that sets flash and flash.now' do
it 'accepts setting any flash.now message' do
context 'when the controller sets both flash and flash.now' do
it 'does not mix flash and flash.now' do
controller = build_fake_response do
flash.now[:notice] = 'value'
flash[:success] = 'great job'
flash['key for flash'] = 'value for flash'
flash.now['key for flash.now'] = 'value for flash.now'
end
expect(controller).to set_flash.now
expect(controller).to set_flash
end
it 'accepts setting a matched flash.now message' do
controller = build_fake_response do
flash.now[:notice] = 'value'
flash[:success] = 'great job'
end
expect(controller).to set_flash.now.to(/value/)
expect(controller).to set_flash.to(/great/)
end
it 'rejects setting a different flash.now message' do
controller = build_fake_response do
flash.now[:notice] = 'value'
flash[:success] = 'great job'
end
expect(controller).not_to set_flash.now.to('other')
expect(controller).not_to set_flash.to('other')
end
end
context 'a controller that does not set a flash message' do
it 'rejects setting any flash message' do
expect(controller_with_no_flashes).not_to set_flash
end
end
def controller_with_no_flashes
build_fake_response
end
def controller_with_flash(flash_hash)
build_fake_response do
flash_hash.each do |key, value|
flash[key] = value
end
end
end
def controller_with_flash_now(flash_hash = { notice: 'hi' })
build_fake_response do
flash_hash.each do |key, value|
flash.now[key] = value
end
expect(controller).not_to set_flash['key for flash.now']
expect(controller).not_to set_flash.now['key for flash']
end
end
end

View file

@ -1,294 +1,17 @@
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController, '#set_session', type: :controller do
context 'passing an argument to the initializer' do
it 'is deprecated in favor of using #[]' do
expectation = proc { set_session(:foo) }
expect(&expectation).to print_warning_including(
'Passing a key to set_session is deprecated'
)
describe Shoulda::Matchers::ActionController::SetSessionMatcher, type: :controller do
it_behaves_like 'set session or flash matcher' do
def store_name
'session'
end
it 'still works regardless' do
silence_warnings do
expect(controller_with_session(var: 'hi')).to set_session(:var)
end
end
end
context 'a controller that sets a session variable' do
context 'without any qualifiers' do
it 'accepts' do
expect(controller_with_session(var: 'hi')).to set_session
end
def set_store
set_session
end
context 'with #to' do
context 'given a static value' do
context 'when any key in session has the given value' do
it 'accepts' do
expect(controller_with_session(var: 'hi')).
to set_session.to('hi')
end
it 'accepts given nil' do
silence_warnings do
expect(controller_with_session(var: nil)).
to set_session.to(nil)
end
end
it 'accepts given false' do
expect(controller_with_session(var: false)).
to set_session.to(false)
end
end
context 'when no key in session has the given value' do
it 'rejects' do
expect(controller_with_session(var: 'hi')).
not_to set_session.to('different')
end
end
end
context 'given a dynamic value' do
context 'when any key in session has the given value' do
it 'accepts' do
context = double(expected: 'hi')
expect(controller_with_session(var: 'hi')).
to set_session.in_context(context).to { expected }
end
it 'accepts given nil' do
silence_warnings do
context = double(expected: nil)
expect(controller_with_session(var: nil)).
to set_session.in_context(context).to { expected }
end
end
it 'accepts given false' do
context = double(expected: false)
expect(controller_with_session(var: false)).
to set_session.in_context(context).to { expected }
end
end
context 'when no key in session has the given value' do
it 'rejects' do
context = double(expected: 'different')
expect(controller_with_session(var: 'hi')).
not_to set_session.in_context(context).to { expected }
end
end
end
context 'given a regexp' do
context 'when any value in session matches the regexp' do
it 'accepts' do
expect(controller_with_session(var: 'hello')).
to set_session.to(/ello/)
end
end
context 'when no value in session matches the regexp' do
it 'rejects' do
expect(controller_with_session(var: 'hello')).
not_to set_session.to(/different/)
end
end
end
end
context 'with #[]' do
context 'when the given key is present in session' do
it 'accepts' do
expect(controller_with_session(var: 'hi')).to set_session[:var]
end
it 'accepts when expected key is a string' do
expect(controller_with_session(var: 'hi')).to set_session['var']
end
end
context 'when the given key is not present in session' do
it 'rejects' do
expect(controller_with_session(var: 'hi')).not_to set_session[:other]
end
end
end
context 'with #[] + #to' do
context 'given a static value' do
context 'when the given key and value are present in session' do
it 'accepts' do
expect(controller_with_session(var: 'hi')).
to set_session[:var].to('hi')
end
it 'accepts given nil' do
silence_warnings do
expect(controller_with_session(var: nil)).
to set_session[:var].to(nil)
end
end
it 'accepts given false' do
expect(controller_with_session(var: false)).
to set_session[:var].to(false)
end
end
context 'when the given key is present in session but not the given value' do
it 'rejects' do
expect(controller_with_session(var: 'hi')).
not_to set_session[:var].to('other')
end
it 'rejects given nil' do
expect(controller_with_session(var: 'hi')).
not_to set_session[:var].to(nil)
end
end
context 'when the given key is not present in session' do
it 'accepts given nil' do
silence_warnings do
expect(controller_with_session(var: 'hi')).
to set_session[:other].to(nil)
end
end
it 'rejects given false' do
expect(controller_with_session(var: false)).
not_to set_session[:other].to(false)
end
end
end
context 'given a dynamic value' do
context 'when the given key and value are present in session' do
it 'accepts' do
context = double(expected: 'value')
expect(controller_with_session(var: 'value')).
to set_session[:var].in_context(context).to { expected }
end
it 'accepts given nil' do
silence_warnings do
context = double(expected: nil)
expect(controller_with_session(var: nil)).
to set_session[:var].in_context(context).to { expected }
end
end
it 'accepts given false' do
context = double(expected: false)
expect(controller_with_session(var: false)).
to set_session[:var].in_context(context).to { expected }
end
end
context 'when the given key is present in session but not the given value' do
it 'rejects given nil' do
context = double(expected: nil)
expect(controller_with_session(var: 'hi')).
not_to set_session[:var].in_context(context).to { expected }
end
it 'rejects given false' do
context = double(expected: false)
expect(controller_with_session(var: 'hi')).
not_to set_session[:var].in_context(context).to { expected }
end
end
context 'when the given key is not present in session' do
it 'rejects' do
context = double(expected: 'other')
expect(controller_with_session(var: 'unexpected')).
not_to set_session[:var].in_context(context).to { expected }
end
it 'accepts given nil' do
silence_warnings do
context = double(expected: nil)
expect(controller_with_session(var: 'hi')).
to set_session[:other].in_context(context).to { expected }
end
end
it 'rejects given false' do
context = double(expected: false)
expect(controller_with_session(var: false)).
not_to set_session[:other].in_context(context).to { expected }
end
end
end
end
end
context 'a controller that does not set any session variables' do
context 'without any qualifiers' do
it 'rejects' do
expect(controller_without_session).not_to set_session
end
end
context 'with #[]' do
it 'rejects' do
expect(controller_without_session).
not_to set_session['any key']
end
end
context 'with #to' do
it 'rejects' do
expect(controller_without_session).
not_to set_session.to('any value')
end
end
context 'with #[] + #to' do
it 'rejects' do
expect(controller_without_session).
not_to set_session['any key'].to('any value')
end
it 'prints a warning when using .to(nil) to assert that a variable is unset' do
expectation = proc do
expect(controller_without_session).to set_session['any key'].to(nil)
end
expected_warning = <<EOT
Using `should set_session[...].to(nil)` to assert that a variable is unset is deprecated.
Please use `should_not set_session[...]` instead.
EOT
expect(&expectation).to print_warning_including(expected_warning)
end
end
end
def controller_without_session
build_fake_response
end
def controller_with_session(session_hash)
build_fake_response do
session_hash.each do |key, value|
session[key] = value
end
def store_within(controller)
controller.session
end
end
end