mcmire-shoulda-matchers 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +32 -0
  4. data/.yardopts +7 -0
  5. data/Appraisals +45 -0
  6. data/CONTRIBUTING.md +41 -0
  7. data/Gemfile +31 -0
  8. data/Gemfile.lock +166 -0
  9. data/MIT-LICENSE +22 -0
  10. data/NEWS.md +299 -0
  11. data/README.md +163 -0
  12. data/Rakefile +116 -0
  13. data/doc_config/gh-pages/index.html.erb +9 -0
  14. data/doc_config/yard/setup.rb +22 -0
  15. data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +5967 -0
  16. data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +12 -0
  17. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +45 -0
  18. data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +69 -0
  19. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +283 -0
  20. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +32 -0
  21. data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +1 -0
  22. data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +8 -0
  23. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +300 -0
  24. data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +1 -0
  25. data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +289 -0
  26. data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +6 -0
  27. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +8 -0
  28. data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +14 -0
  29. data/doc_config/yard/templates/default/layout/html/fonts.erb +1 -0
  30. data/doc_config/yard/templates/default/layout/html/layout.erb +23 -0
  31. data/doc_config/yard/templates/default/layout/html/search.erb +13 -0
  32. data/doc_config/yard/templates/default/layout/html/setup.rb +8 -0
  33. data/doc_config/yard/templates/default/method_details/html/source.erb +10 -0
  34. data/doc_config/yard/templates/default/module/html/box_info.erb +31 -0
  35. data/features/rails_integration.feature +113 -0
  36. data/features/step_definitions/rails_steps.rb +162 -0
  37. data/features/support/env.rb +5 -0
  38. data/gemfiles/3.0.gemfile +24 -0
  39. data/gemfiles/3.0.gemfile.lock +150 -0
  40. data/gemfiles/3.1.gemfile +27 -0
  41. data/gemfiles/3.1.gemfile.lock +173 -0
  42. data/gemfiles/3.2.gemfile +27 -0
  43. data/gemfiles/3.2.gemfile.lock +171 -0
  44. data/gemfiles/4.0.0.gemfile +28 -0
  45. data/gemfiles/4.0.0.gemfile.lock +172 -0
  46. data/gemfiles/4.0.1.gemfile +28 -0
  47. data/gemfiles/4.0.1.gemfile.lock +172 -0
  48. data/lib/shoulda-matchers.rb +1 -0
  49. data/lib/shoulda/matchers.rb +11 -0
  50. data/lib/shoulda/matchers/action_controller.rb +17 -0
  51. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +64 -0
  52. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +97 -0
  53. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +81 -0
  54. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +117 -0
  55. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +114 -0
  56. data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +154 -0
  57. data/lib/shoulda/matchers/action_controller/route_matcher.rb +116 -0
  58. data/lib/shoulda/matchers/action_controller/route_params.rb +48 -0
  59. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +164 -0
  60. data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +296 -0
  61. data/lib/shoulda/matchers/active_model.rb +30 -0
  62. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +167 -0
  63. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +314 -0
  64. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +46 -0
  65. data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +160 -0
  66. data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +417 -0
  67. data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +337 -0
  68. data/lib/shoulda/matchers/active_model/errors.rb +10 -0
  69. data/lib/shoulda/matchers/active_model/exception_message_finder.rb +58 -0
  70. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +92 -0
  71. data/lib/shoulda/matchers/active_model/helpers.rb +46 -0
  72. data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
  73. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +75 -0
  74. data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +27 -0
  75. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +41 -0
  76. data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +27 -0
  77. data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +26 -0
  78. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +112 -0
  79. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +77 -0
  80. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +121 -0
  81. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +380 -0
  82. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +89 -0
  83. data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +372 -0
  84. data/lib/shoulda/matchers/active_model/validation_matcher.rb +97 -0
  85. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +69 -0
  86. data/lib/shoulda/matchers/active_record.rb +22 -0
  87. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +204 -0
  88. data/lib/shoulda/matchers/active_record/association_matcher.rb +901 -0
  89. data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
  90. data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +41 -0
  91. data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +41 -0
  92. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +81 -0
  93. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +65 -0
  94. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +94 -0
  95. data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
  96. data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +41 -0
  97. data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +63 -0
  98. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +261 -0
  99. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +149 -0
  100. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +72 -0
  101. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +181 -0
  102. data/lib/shoulda/matchers/assertion_error.rb +19 -0
  103. data/lib/shoulda/matchers/error.rb +6 -0
  104. data/lib/shoulda/matchers/integrations/rspec.rb +20 -0
  105. data/lib/shoulda/matchers/integrations/test_unit.rb +30 -0
  106. data/lib/shoulda/matchers/rails_shim.rb +50 -0
  107. data/lib/shoulda/matchers/version.rb +6 -0
  108. data/lib/shoulda/matchers/warn.rb +8 -0
  109. data/shoulda-matchers.gemspec +23 -0
  110. data/spec/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +22 -0
  111. data/spec/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +42 -0
  112. data/spec/shoulda/matchers/action_controller/render_template_matcher_spec.rb +78 -0
  113. data/spec/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +63 -0
  114. data/spec/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +63 -0
  115. data/spec/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +31 -0
  116. data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +70 -0
  117. data/spec/shoulda/matchers/action_controller/route_params_spec.rb +30 -0
  118. data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +51 -0
  119. data/spec/shoulda/matchers/action_controller/set_the_flash_matcher_spec.rb +153 -0
  120. data/spec/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +111 -0
  121. data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +170 -0
  122. data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +81 -0
  123. data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +95 -0
  124. data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +320 -0
  125. data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +166 -0
  126. data/spec/shoulda/matchers/active_model/exception_message_finder_spec.rb +111 -0
  127. data/spec/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +20 -0
  128. data/spec/shoulda/matchers/active_model/helpers_spec.rb +158 -0
  129. data/spec/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +169 -0
  130. data/spec/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +59 -0
  131. data/spec/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +59 -0
  132. data/spec/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +57 -0
  133. data/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +139 -0
  134. data/spec/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +41 -0
  135. data/spec/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +47 -0
  136. data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +331 -0
  137. data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +180 -0
  138. data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +398 -0
  139. data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +127 -0
  140. data/spec/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +107 -0
  141. data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +860 -0
  142. data/spec/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +247 -0
  143. data/spec/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +111 -0
  144. data/spec/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +78 -0
  145. data/spec/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +41 -0
  146. data/spec/shoulda/matchers/active_record/serialize_matcher_spec.rb +86 -0
  147. data/spec/spec_helper.rb +26 -0
  148. data/spec/support/active_model_versions.rb +13 -0
  149. data/spec/support/active_resource_builder.rb +29 -0
  150. data/spec/support/activemodel_helpers.rb +19 -0
  151. data/spec/support/capture_helpers.rb +19 -0
  152. data/spec/support/class_builder.rb +42 -0
  153. data/spec/support/controller_builder.rb +74 -0
  154. data/spec/support/fail_with_message_including_matcher.rb +33 -0
  155. data/spec/support/fail_with_message_matcher.rb +32 -0
  156. data/spec/support/i18n_faker.rb +10 -0
  157. data/spec/support/mailer_builder.rb +10 -0
  158. data/spec/support/model_builder.rb +81 -0
  159. data/spec/support/rails_versions.rb +18 -0
  160. data/spec/support/shared_examples/numerical_submatcher.rb +19 -0
  161. data/spec/support/shared_examples/numerical_type_submatcher.rb +17 -0
  162. data/spec/support/test_application.rb +120 -0
  163. data/yard.watchr +5 -0
  164. metadata +281 -0
@@ -0,0 +1,48 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActionController
4
+ # @private
5
+ class RouteParams
6
+ def initialize(args)
7
+ @args = args
8
+ end
9
+
10
+ def normalize
11
+ if controller_and_action_given_as_string?
12
+ extract_params_from_string
13
+ else
14
+ stringify_params
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :args
21
+
22
+ def controller_and_action_given_as_string?
23
+ args[0].is_a?(String)
24
+ end
25
+
26
+ def extract_params_from_string
27
+ params = args[1] || {}
28
+ controller, action = args[0].split('#')
29
+ params.merge!(controller: controller, action: action)
30
+ end
31
+
32
+ def stringify_params
33
+ args[0].each do |key, value|
34
+ args[0][key] = stringify(value)
35
+ end
36
+ end
37
+
38
+ def stringify(value)
39
+ if value.is_a?(Array)
40
+ value.map(&:to_param)
41
+ else
42
+ value.to_param
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,164 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActionController
4
+ # The `set_session` matcher is used to make assertions about the
5
+ # `session` hash.
6
+ #
7
+ # class PostsController < ApplicationController
8
+ # def show
9
+ # session[:foo] = 'bar'
10
+ # end
11
+ # end
12
+ #
13
+ # # RSpec
14
+ # describe PostsController do
15
+ # describe 'GET #show' do
16
+ # before { get :show }
17
+ #
18
+ # it { should set_session(:foo) }
19
+ # it { should_not set_session(:baz) }
20
+ # end
21
+ # end
22
+ #
23
+ # # Test::Unit
24
+ # class PostsControllerTest < ActionController::TestCase
25
+ # context 'GET #show' do
26
+ # setup { get :show }
27
+ #
28
+ # should set_session(:foo)
29
+ # should_not set_session(:baz)
30
+ # end
31
+ # end
32
+ #
33
+ # #### Qualifiers
34
+ #
35
+ # ##### to
36
+ #
37
+ # Use `to` to assert that the key in the session hash was set to a
38
+ # particular value.
39
+ #
40
+ # class PostsController < ApplicationController
41
+ # def show
42
+ # session[:foo] = 'bar'
43
+ # end
44
+ # end
45
+ #
46
+ # # RSpec
47
+ # describe PostsController do
48
+ # describe 'GET #show' do
49
+ # before { get :show }
50
+ #
51
+ # it { should set_session(:foo).to('bar') }
52
+ # it { should_not set_session(:foo).to('something else') }
53
+ # end
54
+ # end
55
+ #
56
+ # # Test::Unit
57
+ # class PostsControllerTest < ActionController::TestCase
58
+ # context 'GET #show' do
59
+ # setup { get :show }
60
+ #
61
+ # should set_session(:foo).to('bar')
62
+ # should_not set_session(:foo).to('something else')
63
+ # end
64
+ # end
65
+ #
66
+ # @return [SetSessionMatcher]
67
+ #
68
+ def set_session(key)
69
+ SetSessionMatcher.new(key)
70
+ end
71
+
72
+ # @private
73
+ class SetSessionMatcher
74
+ def initialize(key)
75
+ @key = key.to_s
76
+ end
77
+
78
+ def to(value = nil, &block)
79
+ @value = value
80
+ @value_block = block
81
+ self
82
+ end
83
+
84
+ def matches?(controller)
85
+ @controller = controller
86
+ if @value_block
87
+ @value = @context.instance_eval(&@value_block)
88
+ end
89
+ assigned_correct_value? || cleared_value?
90
+ end
91
+
92
+ def failure_message
93
+ "Expected #{expectation}, but #{result}"
94
+ end
95
+ alias failure_message_for_should failure_message
96
+
97
+ def failure_message_when_negated
98
+ "Didn't expect #{expectation}, but #{result}"
99
+ end
100
+ alias failure_message_for_should_not failure_message_when_negated
101
+
102
+ def description
103
+ description = "set session variable #{@key.inspect}"
104
+ if @value
105
+ description << " to #{@value.inspect}"
106
+ end
107
+ description
108
+ end
109
+
110
+ def in_context(context)
111
+ @context = context
112
+ self
113
+ end
114
+
115
+ private
116
+
117
+ def assigned_value?
118
+ !assigned_value.nil?
119
+ end
120
+
121
+ def cleared_value?
122
+ defined?(@value) && @value.nil? && assigned_value.nil?
123
+ end
124
+
125
+ def assigned_correct_value?
126
+ if assigned_value?
127
+ if @value.nil?
128
+ true
129
+ else
130
+ assigned_value == @value
131
+ end
132
+ end
133
+ end
134
+
135
+ def assigned_value
136
+ session[@key]
137
+ end
138
+
139
+ def expectation
140
+ expectation = "session variable #{@key} to be set"
141
+ if @value
142
+ expectation << " to #{@value.inspect}"
143
+ end
144
+ end
145
+
146
+ def result
147
+ if session.empty?
148
+ 'no session variables were set'
149
+ else
150
+ "the session was #{session.inspect}"
151
+ end
152
+ end
153
+
154
+ def session
155
+ if @controller.request.respond_to?(:session)
156
+ @controller.request.session.to_hash
157
+ else
158
+ @controller.response.session.data
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,296 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActionController
4
+ # The `set_the_flash` matcher is used to make assertions about the
5
+ # `flash` hash.
6
+ #
7
+ # class PostsController < ApplicationController
8
+ # def index
9
+ # flash[:foo] = 'A candy bar'
10
+ # end
11
+ #
12
+ # def destroy
13
+ # end
14
+ # end
15
+ #
16
+ # # RSpec
17
+ # describe PostsController do
18
+ # describe 'GET #index' do
19
+ # before { get :index }
20
+ #
21
+ # it { should set_the_flash }
22
+ # end
23
+ #
24
+ # describe 'DELETE #destroy' do
25
+ # before { delete :destroy }
26
+ #
27
+ # it { should_not set_the_flash }
28
+ # end
29
+ # end
30
+ #
31
+ # # Test::Unit
32
+ # class PostsControllerTest < ActionController::TestCase
33
+ # context 'GET #index' do
34
+ # setup { get :index }
35
+ #
36
+ # should set_the_flash
37
+ # end
38
+ #
39
+ # context 'DELETE #destroy' do
40
+ # setup { delete :destroy }
41
+ #
42
+ # should_not set_the_flash
43
+ # end
44
+ # end
45
+ #
46
+ # #### Qualifiers
47
+ #
48
+ # ##### []
49
+ #
50
+ # Use `[]` to narrow the scope of the matcher to a particular key.
51
+ #
52
+ # class PostsController < ApplicationController
53
+ # def index
54
+ # flash[:foo] = 'A candy bar'
55
+ # end
56
+ # end
57
+ #
58
+ # # RSpec
59
+ # describe PostsController do
60
+ # describe 'GET #index' do
61
+ # before { get :index }
62
+ #
63
+ # it { should set_the_flash[:foo] }
64
+ # it { should_not set_the_flash[:bar] }
65
+ # end
66
+ # end
67
+ #
68
+ # # Test::Unit
69
+ # class PostsControllerTest < ActionController::TestCase
70
+ # context 'GET #index' do
71
+ # setup { get :show }
72
+ #
73
+ # should set_the_flash[:foo]
74
+ # should_not set_the_flash[:bar]
75
+ # end
76
+ # end
77
+ #
78
+ # ##### to
79
+ #
80
+ # Use `to` to assert that some key was set to a particular value, or that
81
+ # some key matches a particular regex.
82
+ #
83
+ # class PostsController < ApplicationController
84
+ # def index
85
+ # flash[:foo] = 'A candy bar'
86
+ # end
87
+ # end
88
+ #
89
+ # # RSpec
90
+ # describe PostsController do
91
+ # describe 'GET #index' do
92
+ # before { get :index }
93
+ #
94
+ # it { should set_the_flash.to('A candy bar') }
95
+ # it { should set_the_flash.to(/bar/) }
96
+ # it { should set_the_flash[:foo].to('bar') }
97
+ # it { should_not set_the_flash[:foo].to('something else') }
98
+ # end
99
+ # end
100
+ #
101
+ # # Test::Unit
102
+ # class PostsControllerTest < ActionController::TestCase
103
+ # context 'GET #index' do
104
+ # setup { get :show }
105
+ #
106
+ # should set_the_flash.to('A candy bar')
107
+ # should set_the_flash.to(/bar/)
108
+ # should set_the_flash[:foo].to('bar')
109
+ # should_not set_the_flash[:foo].to('something else')
110
+ # end
111
+ # end
112
+ #
113
+ # ##### now
114
+ #
115
+ # Use `now` to change the scope of the matcher to use the "now" hash
116
+ # instead of the usual "future" hash.
117
+ #
118
+ # class PostsController < ApplicationController
119
+ # def show
120
+ # flash.now[:foo] = 'bar'
121
+ # end
122
+ # end
123
+ #
124
+ # # RSpec
125
+ # describe PostsController do
126
+ # describe 'GET #show' do
127
+ # before { get :show }
128
+ #
129
+ # it { should set_the_flash.now }
130
+ # it { should set_the_flash[:foo].now }
131
+ # it { should set_the_flash[:foo].to('bar').now }
132
+ # end
133
+ # end
134
+ #
135
+ # # Test::Unit
136
+ # class PostsControllerTest < ActionController::TestCase
137
+ # context 'GET #index' do
138
+ # setup { get :show }
139
+ #
140
+ # should set_the_flash.now
141
+ # should set_the_flash[:foo].now
142
+ # should set_the_flash[:foo].to('bar').now
143
+ # end
144
+ # end
145
+ #
146
+ # @return [SetTheFlashMatcher]
147
+ #
148
+ def set_the_flash
149
+ SetTheFlashMatcher.new
150
+ end
151
+
152
+ # @private
153
+ class SetTheFlashMatcher
154
+ def initialize
155
+ @options = {}
156
+ end
157
+
158
+ def to(value)
159
+ if !value.is_a?(String) && !value.is_a?(Regexp)
160
+ raise "cannot match against #{value.inspect}"
161
+ end
162
+ @value = value
163
+ self
164
+ end
165
+
166
+ def now
167
+ @options[:now] = true
168
+ self
169
+ end
170
+
171
+ def [](key)
172
+ @options[:key] = key
173
+ self
174
+ end
175
+
176
+ def matches?(controller)
177
+ @controller = controller
178
+ sets_the_flash? && string_value_matches? && regexp_value_matches?
179
+ end
180
+
181
+ def description
182
+ description = "set the #{expected_flash_invocation}"
183
+ description << " to #{@value.inspect}" unless @value.nil?
184
+ description
185
+ end
186
+
187
+ def failure_message
188
+ "Expected #{expectation}"
189
+ end
190
+ alias failure_message_for_should failure_message
191
+
192
+ def failure_message_when_negated
193
+ "Did not expect #{expectation}"
194
+ end
195
+ alias failure_message_for_should_not failure_message_when_negated
196
+
197
+ private
198
+
199
+ def sets_the_flash?
200
+ flash_values.any?
201
+ end
202
+
203
+ def string_value_matches?
204
+ if @value.is_a?(String)
205
+ flash_values.any? {|value| value == @value }
206
+ else
207
+ true
208
+ end
209
+ end
210
+
211
+ def regexp_value_matches?
212
+ if @value.is_a?(Regexp)
213
+ flash_values.any? {|value| value =~ @value }
214
+ else
215
+ true
216
+ end
217
+ end
218
+
219
+ def flash_values
220
+ if @options.key?(:key)
221
+ [flash.to_hash[@options[:key]]]
222
+ else
223
+ flash.to_hash.values
224
+ end
225
+ end
226
+
227
+ def flash
228
+ @flash ||= copy_of_flash_from_controller
229
+ end
230
+
231
+ def copy_of_flash_from_controller
232
+ @controller.flash.dup.tap do |flash|
233
+ copy_flashes(@controller.flash, flash)
234
+ copy_discard_if_necessary(@controller.flash, flash)
235
+ sweep_flash_if_necessary(flash)
236
+ end
237
+ end
238
+
239
+ def copy_flashes(original_flash, new_flash)
240
+ flashes_ivar = Shoulda::Matchers::RailsShim.flashes_ivar
241
+ flashes = original_flash.instance_variable_get(flashes_ivar).dup
242
+ new_flash.instance_variable_set(flashes_ivar, flashes)
243
+ end
244
+
245
+ def copy_discard_if_necessary(original_flash, new_flash)
246
+ discard_ivar = :@discard
247
+ if original_flash.instance_variable_defined?(discard_ivar)
248
+ discard = original_flash.instance_variable_get(discard_ivar).dup
249
+ new_flash.instance_variable_set(discard_ivar, discard)
250
+ end
251
+ end
252
+
253
+ def sweep_flash_if_necessary(flash)
254
+ unless @options[:now]
255
+ flash.sweep
256
+ end
257
+ end
258
+
259
+ def expectation
260
+ expectation = "the #{expected_flash_invocation} to be set"
261
+ expectation << " to #{@value.inspect}" unless @value.nil?
262
+ expectation << ", but #{flash_description}"
263
+ expectation
264
+ end
265
+
266
+ def flash_description
267
+ if flash.blank?
268
+ 'no flash was set'
269
+ else
270
+ "was #{flash.inspect}"
271
+ end
272
+ end
273
+
274
+ def expected_flash_invocation
275
+ "flash#{pretty_now}#{pretty_key}"
276
+ end
277
+
278
+ def pretty_now
279
+ if @options[:now]
280
+ '.now'
281
+ else
282
+ ''
283
+ end
284
+ end
285
+
286
+ def pretty_key
287
+ if @options[:key]
288
+ "[:#{@options[:key]}]"
289
+ else
290
+ ''
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end
296
+ end