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

Bring set_session in line with set_flash

* Deprecate `set_session(:foo)` in favor of `set_session[:foo]`
* Make both #[] and #to optional (`should set_session` simply checks
  that the session is non-empty, `should set_session.to('value')` checks
  that *any* value is 'value')
* Add support for regexps to #to
* Deprecate `should set_session(...).to(nil)` in favor of using
  `should_not set_session`
* Improve failure message
This commit is contained in:
Elliot Winkler 2014-11-21 11:30:02 -07:00
parent 5cfe0403e6
commit b84ec8cc16
4 changed files with 391 additions and 98 deletions

17
NEWS.md
View file

@ -8,6 +8,14 @@
* `set_the_flash` has been renamed to `set_flash`. `set_the_flash` is
deprecated and will be removed in 3.0.0.
* `set_session(:foo)` is deprecated in favor of `set_session[:foo]`.
`set_session(:foo)` will be invalid syntax in 3.0.0.
* Using `should set_session[:key].to(nil)` to assert that that a value has not
been set is deprecated. Please use `should_not set_session[:key]` instead.
In 3.0.0, `should set_session[:key].to(nil)` will only pass if the value is
truly nil.
### Bug fixes
* Fix `delegate_method` so that it works again with shoulda-context. ([#591])
@ -44,9 +52,18 @@
### Features
* Add ability to test `:primary_key` option on associations. ([#597])
* Add `allow_blank` qualifier to `validate_uniqueness_of` to complement
the `allow_blank` option. ([#543])
* Change `set_session` so that #[] and #to qualifiers are optional, similar to
`set_flash`. That is, you can now say `should set_session` to assert that any
flash value has been set, or `should set_session.to('value')` to assert that
any value in the session is 'value'.
* Change `set_session` so that its #to qualifier supports regexps, similar to
`set_flash`.
### Improvements
* Tweak `allow_value` failure message so that it reads a bit nicer when listing

View file

@ -5,45 +5,11 @@ module Shoulda
# `session` hash.
#
# class PostsController < ApplicationController
# def show
# session[:foo] = 'bar'
# end
# end
#
# # RSpec
# describe PostsController do
# describe 'GET #show' do
# before { get :show }
#
# it { should set_session(:foo) }
# it { should_not set_session(:baz) }
# end
# end
#
# # Test::Unit
# class PostsControllerTest < ActionController::TestCase
# context 'GET #show' do
# setup { get :show }
#
# should set_session(:foo)
# should_not set_session(:baz)
# end
# end
#
# #### Qualifiers
#
# ##### to
#
# Use `to` to assert that the key in the session hash was set to a
# particular value.
#
# class PostsController < ApplicationController
# def index
# session[:foo] = 'bar'
# session[:foo] = 'A candy bar'
# end
#
# def show
# session[:foo] = nil
# def destroy
# end
# end
#
@ -52,15 +18,13 @@ module Shoulda
# describe 'GET #index' do
# before { get :index }
#
# it { should set_session(:foo).to('bar') }
# it { should_not set_session(:foo).to('something else') }
# it { should_not set_session(:foo).to(nil) }
# it { should set_session }
# end
#
# describe 'GET #show' do
# before { get :show }
# describe 'DELETE #destroy' do
# before { delete :destroy }
#
# it { should set_session(:foo).to(nil) }
# it { should_not set_session }
# end
# end
#
@ -69,31 +33,108 @@ module Shoulda
# context 'GET #index' do
# setup { get :index }
#
# should set_session(:foo).to('bar')
# should_not set_session(:foo).to('something else')
# should_not set_session(:foo).to(nil)
# should set_session
# end
#
# context 'GET #show' do
# context 'DELETE #destroy' do
# setup { delete :destroy }
#
# should_not set_session
# end
# end
#
# #### Qualifiers
#
# ##### []
#
# Use `[]` to narrow the scope of the matcher to a particular key.
#
# class PostsController < ApplicationController
# def index
# session[:foo] = 'A candy bar'
# end
# end
#
# # RSpec
# describe PostsController do
# describe 'GET #index' do
# before { get :index }
#
# it { should set_session[:foo] }
# it { should_not set_session[:bar] }
# end
# end
#
# # Test::Unit
# class PostsControllerTest < ActionController::TestCase
# context 'GET #index' do
# setup { get :show }
#
# should set_session(:foo).to(nil)
# should set_session[:foo]
# should_not set_session[: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
# session[:foo] = 'A candy bar'
# end
# end
#
# # RSpec
# describe PostsController do
# describe 'GET #index' do
# before { get :index }
#
# it { should set_session.to('A candy bar') }
# it { should set_session.to(/bar/) }
# it { should set_session[:foo].to('bar') }
# it { should_not set_session[:foo].to('something else') }
# end
# end
#
# # Test::Unit
# class PostsControllerTest < ActionController::TestCase
# context 'GET #index' do
# setup { get :show }
#
# should set_session.to('A candy bar')
# should set_session.to(/bar/)
# should set_session[:foo].to('bar')
# should_not set_session[:foo].to('something else')
# end
# end
#
# @return [SetSessionMatcher]
#
def set_session(key)
def set_session(key = nil)
SetSessionMatcher.new(key)
end
# @private
class SetSessionMatcher
def initialize(key)
@key = key.to_s
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
@value_block = nil
end
def [](key)
@key = key.to_s
self
end
def to(value = nil, &block)
@value = value
@value_block = block
@ -102,10 +143,27 @@ module Shoulda
def matches?(controller)
@controller = controller
if @value_block
@value = @context.instance_eval(&@value_block)
end
assigned_correct_value? || cleared_value?
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
@ -114,16 +172,12 @@ module Shoulda
alias failure_message_for_should failure_message
def failure_message_when_negated
"Didn't expect #{expectation}, but #{result}"
"Didn't expect #{expectation}, but it was"
end
alias failure_message_for_should_not failure_message_when_negated
def description
description = "set session variable #{@key.inspect}"
if @value
description << " to #{@value.inspect}"
end
description
"should #{expectation}"
end
def in_context(context)
@ -133,54 +187,56 @@ module Shoulda
private
def key_specified?
defined?(@key)
end
def value_specified?
defined?(@value)
end
def value_or_default_value
defined?(@value) && @value
end
def assigned_value?
!assigned_value.nil?
def nil_value_expected_but_actual_value_unset?
value_specified? && @value.nil? && !session.key?(@key)
end
def cleared_value?
defined?(@value) && @value.nil? && assigned_value.nil?
end
def assigned_correct_value?
if assigned_value?
if !defined?(@value)
true
else
assigned_value == value_or_default_value
end
end
end
def assigned_value
session[@key]
def session_present?
!session.empty?
end
def expectation
expectation = "session variable #{@key} to be set"
expectation = ""
if value_or_default_value
expectation << " to #{value_or_default_value.inspect}"
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.empty?
'no session variables were set'
else
if session_present?
"the session was #{session.inspect}"
else
'no session variables were set'
end
end
def session
if @controller.request.respond_to?(:session)
@controller.request.session.to_hash
else
@controller.response.session.data
end
@controller.session
end
end
end

View file

@ -0,0 +1,59 @@
module UnitTests
module Matchers
def print_warning_including(expected_warning)
PrintWarningIncludingMatcher.new(expected_warning)
end
class PrintWarningIncludingMatcher
def initialize(expected_warning)
@expected_warning = collapse_whitespace(expected_warning)
end
def matches?(block)
@captured_stderr = collapse_whitespace(capture(:stderr, &block))
captured_stderr.include?(expected_warning)
end
def failure_message
"Expected block to #{expectation}\nbut actually printed#{actual_warning}"
end
alias_method :failure_message_for_should, :failure_message
def failure_message_when_negated
"Expected block not to #{expectation}, but it did."
end
alias_method :failure_message_for_should_not,
:failure_message_when_negated
def description
"should #{expectation}"
end
def supports_block_expectations?
true
end
protected
attr_reader :expected_warning, :captured_stderr
private
def expectation
"print a warning including:\n #{expected_warning}"
end
def actual_warning
if captured_stderr.empty?
" nothing."
else
":\n #{captured_stderr}"
end
end
def collapse_whitespace(string)
string.gsub(/\n+/, ' ').squeeze(' ')
end
end
end
end

View file

@ -1,7 +1,107 @@
require 'unit_spec_helper'
describe Shoulda::Matchers::ActionController, '#set_session' 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'
)
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
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
@ -24,35 +124,46 @@ describe Shoulda::Matchers::ActionController, '#set_session' 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')
expect(controller_with_session(var: 'hi')).
to set_session[:var].to('hi')
end
it 'accepts given nil' do
expect(controller_with_session(var: nil)).to set_session[:var].to(nil)
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)
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')
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)
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
expect(controller_with_session(var: 'hi')).to set_session[:other].to(nil)
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)
expect(controller_with_session(var: false)).
not_to set_session[:other].to(false)
end
end
end
@ -67,10 +178,12 @@ describe Shoulda::Matchers::ActionController, '#set_session' do
end
it 'accepts given nil' do
context = double(expected: nil)
silence_warnings do
context = double(expected: nil)
expect(controller_with_session(var: nil)).
to set_session[:var].in_context(context).to { expected }
expect(controller_with_session(var: nil)).
to set_session[:var].in_context(context).to { expected }
end
end
it 'accepts given false' do
@ -106,10 +219,12 @@ describe Shoulda::Matchers::ActionController, '#set_session' do
end
it 'accepts given nil' do
context = double(expected: nil)
silence_warnings do
context = double(expected: nil)
expect(controller_with_session(var: 'hi')).
to set_session[:other].in_context(context).to { expected }
expect(controller_with_session(var: 'hi')).
to set_session[:other].in_context(context).to { expected }
end
end
it 'rejects given false' do
@ -123,6 +238,52 @@ describe Shoulda::Matchers::ActionController, '#set_session' do
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|