shoulda-matchers 2.8.0 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/.hound_config/ruby.yml +7 -0
  3. data/.travis.yml +11 -54
  4. data/Appraisals +45 -100
  5. data/CONTRIBUTING.md +51 -7
  6. data/Gemfile +7 -19
  7. data/Gemfile.lock +60 -134
  8. data/Guardfile +5 -0
  9. data/NEWS.md +203 -0
  10. data/README.md +95 -50
  11. data/Rakefile +1 -0
  12. data/doc_config/yard/templates/default/layout/html/setup.rb +1 -1
  13. data/gemfiles/4.0.0.gemfile +10 -7
  14. data/gemfiles/4.0.0.gemfile.lock +103 -79
  15. data/gemfiles/4.0.1.gemfile +10 -7
  16. data/gemfiles/4.0.1.gemfile.lock +109 -83
  17. data/gemfiles/4.1.gemfile +10 -7
  18. data/gemfiles/4.1.gemfile.lock +109 -85
  19. data/gemfiles/4.2.gemfile +10 -9
  20. data/gemfiles/4.2.gemfile.lock +86 -78
  21. data/lib/shoulda/matchers.rb +13 -18
  22. data/lib/shoulda/matchers/action_controller.rb +4 -1
  23. data/lib/shoulda/matchers/action_controller/flash_store.rb +95 -0
  24. data/lib/shoulda/matchers/action_controller/{strong_parameters_matcher.rb → permit_matcher.rb} +147 -30
  25. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
  26. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +1 -1
  27. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +1 -1
  28. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +1 -1
  29. data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -1
  30. data/lib/shoulda/matchers/action_controller/route_params.rb +15 -6
  31. data/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
  32. data/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +30 -136
  33. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +28 -109
  34. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +103 -0
  35. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +1 -12
  36. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +79 -10
  37. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +10 -0
  38. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +21 -0
  39. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +24 -0
  40. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +22 -5
  41. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +29 -10
  42. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +27 -10
  43. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +27 -12
  44. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +56 -20
  45. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +3 -11
  46. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +65 -0
  47. data/lib/shoulda/matchers/active_record/association_matcher.rb +40 -6
  48. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +21 -7
  49. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +11 -40
  50. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +1 -1
  51. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +2 -6
  52. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +137 -22
  53. data/lib/shoulda/matchers/configuration.rb +20 -0
  54. data/lib/shoulda/matchers/doublespeak.rb +11 -1
  55. data/lib/shoulda/matchers/doublespeak/double.rb +29 -11
  56. data/lib/shoulda/matchers/doublespeak/double_collection.rb +4 -3
  57. data/lib/shoulda/matchers/doublespeak/method_call.rb +35 -0
  58. data/lib/shoulda/matchers/doublespeak/object_double.rb +7 -2
  59. data/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +4 -3
  60. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +3 -3
  61. data/lib/shoulda/matchers/doublespeak/world.rb +21 -1
  62. data/lib/shoulda/matchers/integrations.rb +43 -0
  63. data/lib/shoulda/matchers/integrations/configuration.rb +68 -0
  64. data/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
  65. data/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
  66. data/lib/shoulda/matchers/integrations/libraries.rb +15 -0
  67. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +31 -0
  68. data/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
  69. data/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
  70. data/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
  71. data/lib/shoulda/matchers/integrations/libraries/rails.rb +30 -0
  72. data/lib/shoulda/matchers/integrations/rails.rb +12 -0
  73. data/lib/shoulda/matchers/integrations/registry.rb +28 -0
  74. data/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
  75. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
  76. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
  77. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
  78. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
  79. data/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
  80. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
  81. data/lib/shoulda/matchers/rails_shim.rb +0 -40
  82. data/lib/shoulda/matchers/version.rb +1 -1
  83. data/script/SUPPORTED_VERSIONS +1 -1
  84. data/script/update_gems_in_all_appraisals +14 -0
  85. data/shoulda-matchers.gemspec +2 -2
  86. data/spec/acceptance/active_model_integration_spec.rb +4 -1
  87. data/spec/acceptance/independent_matchers_spec.rb +6 -6
  88. data/spec/acceptance/multiple_libraries_integration_spec.rb +52 -0
  89. data/spec/acceptance/rails_integration_spec.rb +15 -5
  90. data/spec/acceptance_spec_helper.rb +8 -0
  91. data/spec/doublespeak_spec_helper.rb +14 -0
  92. data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +110 -0
  93. data/spec/support/acceptance/helpers.rb +2 -0
  94. data/spec/support/acceptance/helpers/base_helpers.rb +6 -1
  95. data/spec/support/acceptance/helpers/command_helpers.rb +6 -2
  96. data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -8
  97. data/spec/support/acceptance/helpers/n_unit_helpers.rb +25 -0
  98. data/spec/support/acceptance/helpers/rspec_helpers.rb +2 -0
  99. data/spec/support/acceptance/helpers/step_helpers.rb +13 -19
  100. data/spec/support/acceptance/matchers/have_output.rb +1 -1
  101. data/spec/support/tests/bundle.rb +1 -1
  102. data/spec/support/tests/command_runner.rb +25 -13
  103. data/spec/support/tests/current_bundle.rb +47 -0
  104. data/spec/support/tests/database.rb +28 -0
  105. data/spec/support/tests/database_adapters/postgresql.rb +25 -0
  106. data/spec/support/tests/database_adapters/sqlite3.rb +26 -0
  107. data/spec/support/tests/database_configuration.rb +33 -0
  108. data/spec/support/tests/database_configuration_registry.rb +28 -0
  109. data/spec/support/tests/filesystem.rb +25 -2
  110. data/spec/support/unit/helpers/active_record_versions.rb +12 -0
  111. data/spec/support/unit/helpers/class_builder.rb +6 -2
  112. data/spec/support/unit/helpers/column_type_helpers.rb +26 -0
  113. data/spec/support/unit/helpers/controller_builder.rb +0 -28
  114. data/spec/support/unit/helpers/database_helpers.rb +18 -0
  115. data/spec/support/unit/helpers/model_builder.rb +38 -6
  116. data/spec/support/unit/helpers/rails_versions.rb +2 -2
  117. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +9 -8
  118. data/spec/support/unit/matchers/fail_with_message_matcher.rb +1 -1
  119. data/spec/support/unit/rails_application.rb +29 -13
  120. data/spec/support/unit/record_validating_confirmation_builder.rb +1 -2
  121. data/spec/support/unit/shared_examples/set_session_or_flash.rb +355 -0
  122. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +433 -0
  123. data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +1 -5
  124. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +37 -0
  125. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +23 -147
  126. data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +8 -285
  127. data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +562 -0
  128. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +81 -14
  129. data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +16 -8
  130. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +101 -9
  131. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +39 -1
  132. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +39 -1
  133. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +39 -0
  134. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -17
  135. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -17
  136. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -17
  137. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +838 -271
  138. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -19
  139. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +93 -0
  140. data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +3 -3
  141. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +25 -0
  142. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +905 -0
  143. data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +17 -11
  144. data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +1 -1
  145. data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +144 -43
  146. data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +1 -1
  147. data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +36 -11
  148. data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +29 -16
  149. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +8 -5
  150. data/spec/unit/shoulda/matchers/doublespeak_spec.rb +1 -1
  151. data/spec/unit_spec_helper.rb +15 -14
  152. data/spec/warnings_spy.rb +1 -1
  153. metadata +68 -29
  154. data/docs.watchr +0 -5
  155. data/gemfiles/3.0.gemfile +0 -26
  156. data/gemfiles/3.0.gemfile.lock +0 -173
  157. data/gemfiles/3.1.gemfile +0 -32
  158. data/gemfiles/3.1.gemfile.lock +0 -212
  159. data/gemfiles/3.1_1.9.2.gemfile +0 -32
  160. data/gemfiles/3.1_1.9.2.gemfile.lock +0 -212
  161. data/gemfiles/3.2.gemfile +0 -33
  162. data/gemfiles/3.2.gemfile.lock +0 -212
  163. data/gemfiles/3.2_1.9.2.gemfile +0 -31
  164. data/gemfiles/3.2_1.9.2.gemfile.lock +0 -207
  165. data/lib/shoulda/matchers/assertion_error.rb +0 -27
  166. data/lib/shoulda/matchers/doublespeak/structs.rb +0 -10
  167. data/lib/shoulda/matchers/integrations/nunit_test_case_detection.rb +0 -39
  168. data/lib/shoulda/matchers/integrations/rspec.rb +0 -19
  169. data/lib/shoulda/matchers/integrations/test_unit.rb +0 -34
  170. data/spec/unit/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +0 -331
  171. data/spec/unit/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +0 -564
@@ -1,28 +1,23 @@
1
- require 'shoulda/matchers/assertion_error'
1
+ require 'shoulda/matchers/configuration'
2
2
  require 'shoulda/matchers/doublespeak'
3
3
  require 'shoulda/matchers/error'
4
+ require 'shoulda/matchers/independent'
5
+ require 'shoulda/matchers/integrations'
4
6
  require 'shoulda/matchers/matcher_context'
5
7
  require 'shoulda/matchers/rails_shim'
6
8
  require 'shoulda/matchers/util'
7
9
  require 'shoulda/matchers/version'
8
10
  require 'shoulda/matchers/warn'
9
11
 
10
- require 'shoulda/matchers/independent'
12
+ require 'shoulda/matchers/action_controller'
13
+ require 'shoulda/matchers/active_model'
14
+ require 'shoulda/matchers/active_record'
11
15
 
12
- if defined?(ActiveModel)
13
- require 'shoulda/matchers/active_model'
16
+ module Shoulda
17
+ module Matchers
18
+ class << self
19
+ # @private
20
+ attr_accessor :assertion_exception_class
21
+ end
22
+ end
14
23
  end
15
-
16
- if defined?(ActiveRecord)
17
- require 'shoulda/matchers/active_record'
18
- end
19
-
20
- if defined?(ActionController)
21
- require 'shoulda/matchers/action_controller'
22
- end
23
-
24
- if defined?(RSpec)
25
- require 'shoulda/matchers/integrations/rspec'
26
- end
27
-
28
- require 'shoulda/matchers/integrations/test_unit'
@@ -9,7 +9,10 @@ require 'shoulda/matchers/action_controller/redirect_to_matcher'
9
9
  require 'shoulda/matchers/action_controller/render_template_matcher'
10
10
  require 'shoulda/matchers/action_controller/rescue_from_matcher'
11
11
  require 'shoulda/matchers/action_controller/callback_matcher'
12
- require 'shoulda/matchers/action_controller/strong_parameters_matcher'
12
+ require 'shoulda/matchers/action_controller/permit_matcher'
13
+ require 'shoulda/matchers/action_controller/set_session_or_flash_matcher'
14
+ require 'shoulda/matchers/action_controller/flash_store'
15
+ require 'shoulda/matchers/action_controller/session_store'
13
16
 
14
17
  module Shoulda
15
18
  module Matchers
@@ -0,0 +1,95 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActionController
4
+ # @private
5
+ class FlashStore
6
+ def self.future
7
+ new
8
+ end
9
+
10
+ def self.now
11
+ new.use_now!
12
+ end
13
+
14
+ attr_accessor :controller
15
+
16
+ def initialize
17
+ @use_now = false
18
+ end
19
+
20
+ def name
21
+ if @use_now
22
+ 'flash.now'
23
+ else
24
+ 'flash'
25
+ end
26
+ end
27
+
28
+ def has_key?(key)
29
+ values_to_check.include?(key)
30
+ end
31
+
32
+ def has_value?(expected_value)
33
+ values_to_check.values.any? do |actual_value|
34
+ expected_value === actual_value
35
+ end
36
+ end
37
+
38
+ def empty?
39
+ flash.empty?
40
+ end
41
+
42
+ def use_now!
43
+ @use_now = true
44
+ self
45
+ end
46
+
47
+ private
48
+
49
+ def flash
50
+ @_flash ||= copy_of_flash_from_controller
51
+ end
52
+
53
+ def copy_of_flash_from_controller
54
+ controller.flash.dup.tap do |flash|
55
+ copy_flashes(controller.flash, flash)
56
+ copy_discard_if_necessary(controller.flash, flash)
57
+ # sweep_flash_if_necessary(flash)
58
+ end
59
+ end
60
+
61
+ def copy_flashes(original_flash, new_flash)
62
+ flashes = original_flash.instance_variable_get('@flashes').dup
63
+ new_flash.instance_variable_set('@flashes', flashes)
64
+ end
65
+
66
+ def copy_discard_if_necessary(original_flash, new_flash)
67
+ discard = original_flash.instance_variable_get('@discard').dup
68
+ new_flash.instance_variable_set('@discard', discard)
69
+ end
70
+
71
+ def sweep_flash_if_necessary(flash)
72
+ unless @use_now
73
+ flash.sweep
74
+ end
75
+ end
76
+
77
+ def set_values
78
+ flash.instance_variable_get('@flashes')
79
+ end
80
+
81
+ def keys_to_discard
82
+ flash.instance_variable_get('@discard')
83
+ end
84
+
85
+ def values_to_check
86
+ if @use_now
87
+ set_values.slice(*keys_to_discard.to_a)
88
+ else
89
+ set_values.except(*keys_to_discard.to_a)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -38,14 +38,16 @@ module Shoulda
38
38
  # describe UsersController do
39
39
  # it do
40
40
  # should permit(:first_name, :last_name, :email, :password).
41
- # for(:create)
41
+ # for(:create).
42
+ # on(:user)
42
43
  # end
43
44
  # end
44
45
  #
45
46
  # # Test::Unit
46
47
  # class UsersControllerTest < ActionController::TestCase
47
48
  # should permit(:first_name, :last_name, :email, :password).
48
- # for(:create)
49
+ # for(:create).
50
+ # on(:user)
49
51
  # end
50
52
  #
51
53
  # If your action requires query parameters in order to work, then you'll
@@ -82,7 +84,8 @@ module Shoulda
82
84
  #
83
85
  # it do
84
86
  # should permit(:first_name, :last_name, :email, :password).
85
- # for(:update, params: { id: 1 })
87
+ # for(:update, params: { id: 1 }).
88
+ # on(:user)
86
89
  # end
87
90
  # end
88
91
  #
@@ -93,7 +96,8 @@ module Shoulda
93
96
  # end
94
97
  #
95
98
  # should permit(:first_name, :last_name, :email, :password).
96
- # for(:update, params: { id: 1 })
99
+ # for(:update, params: { id: 1 }).
100
+ # on(:user)
97
101
  # end
98
102
  #
99
103
  # Finally, if you have an action that isn't one of the seven resourceful
@@ -132,10 +136,9 @@ module Shoulda
132
136
  # end
133
137
  #
134
138
  # it do
135
- # should permit(:activated).for(:toggle,
136
- # params: { id: 1 },
137
- # verb: :put
138
- # )
139
+ # should permit(:activated).
140
+ # for(:toggle, params: { id: 1 }, verb: :put).
141
+ # on(:user)
139
142
  # end
140
143
  # end
141
144
  #
@@ -145,28 +148,28 @@ module Shoulda
145
148
  # create(:user, id: 1)
146
149
  # end
147
150
  #
148
- # should permit(:activated).for(:toggle,
149
- # params: { id: 1 },
150
- # verb: :put
151
- # )
151
+ # should permit(:activated).
152
+ # for(:toggle, params: { id: 1 }, verb: :put).
153
+ # on(:user)
152
154
  # end
153
155
  #
154
- # @return [StrongParametersMatcher]
156
+ # @return [PermitMatcher]
155
157
  #
156
158
  def permit(*params)
157
- StrongParametersMatcher.new(params).in_context(self)
159
+ PermitMatcher.new(params).in_context(self)
158
160
  end
159
161
 
160
162
  # @private
161
- class StrongParametersMatcher
163
+ class PermitMatcher
162
164
  attr_writer :stubbed_params
163
165
 
164
166
  def initialize(expected_permitted_params)
167
+ @expected_permitted_params = expected_permitted_params
165
168
  @action = nil
166
169
  @verb = nil
167
170
  @request_params = {}
168
- @expected_permitted_params = expected_permitted_params
169
- set_double_collection
171
+ @subparameter = nil
172
+ @parameters_doubles = ParametersDoubles.new
170
173
  end
171
174
 
172
175
  def for(action, options = {})
@@ -176,19 +179,32 @@ module Shoulda
176
179
  self
177
180
  end
178
181
 
182
+ def add_params(params)
183
+ request_params.merge!(params)
184
+ self
185
+ end
186
+
187
+ def on(subparameter)
188
+ @subparameter = subparameter
189
+ @parameters_doubles = SliceOfParametersDoubles.new(subparameter)
190
+ self
191
+ end
192
+
179
193
  def in_context(context)
180
194
  @context = context
181
195
  self
182
196
  end
183
197
 
184
198
  def description
185
- "permit #{verb.upcase} ##{action} to receive parameters #{param_names_as_sentence}"
199
+ "(on #{verb.upcase} ##{action}) " + expectation
186
200
  end
187
201
 
188
202
  def matches?(controller)
189
203
  @controller = controller
190
204
  ensure_action_and_verb_present!
191
205
 
206
+ parameters_doubles.register
207
+
192
208
  Doublespeak.with_doubles_activated do
193
209
  context.__send__(verb, action, request_params)
194
210
  end
@@ -197,32 +213,49 @@ module Shoulda
197
213
  end
198
214
 
199
215
  def failure_message
200
- "Expected controller to permit #{unpermitted_params.to_sentence}, but it did not."
216
+ "Expected #{verb.upcase} ##{action} to #{expectation},\nbut #{reality}."
201
217
  end
202
218
  alias failure_message_for_should failure_message
203
219
 
204
220
  def failure_message_when_negated
205
- "Expected controller not to permit #{verified_permitted_params.to_sentence}, but it did."
221
+ "Expected #{verb.upcase} ##{action} not to #{expectation},\nbut it did."
206
222
  end
207
223
  alias failure_message_for_should_not failure_message_when_negated
208
224
 
209
225
  protected
210
226
 
211
- attr_reader :controller, :double_collection, :action, :verb,
212
- :request_params, :expected_permitted_params, :context
227
+ attr_reader :controller, :double_collections_by_param, :action, :verb,
228
+ :request_params, :expected_permitted_params, :context, :subparameter,
229
+ :parameters_doubles
230
+
231
+ def expectation
232
+ message = 'restrict parameters '
233
+
234
+ if subparameter
235
+ message << " for #{subparameter.inspect}"
236
+ end
237
+
238
+ message << 'to ' + format_param_names(expected_permitted_params)
213
239
 
214
- def set_double_collection
215
- @double_collection =
216
- Doublespeak.double_collection_for(::ActionController::Parameters)
240
+ message
241
+ end
217
242
 
218
- @double_collection.register_stub(:require).to_return { |params| params }
219
- @double_collection.register_proxy(:permit)
243
+ def reality
244
+ if actual_permitted_params.empty?
245
+ 'it did not restrict any parameters'
246
+ else
247
+ 'the restricted parameters were ' +
248
+ format_param_names(actual_permitted_params) +
249
+ ' instead'
250
+ end
251
+ end
252
+
253
+ def format_param_names(param_names)
254
+ param_names.map(&:inspect).to_sentence
220
255
  end
221
256
 
222
257
  def actual_permitted_params
223
- double_collection.calls_to(:permit).inject([]) do |all_param_names, call|
224
- all_param_names + call.args
225
- end.flatten
258
+ parameters_doubles.permitted_params
226
259
  end
227
260
 
228
261
  def permit_called?
@@ -258,6 +291,90 @@ module Shoulda
258
291
  expected_permitted_params.map(&:inspect).to_sentence
259
292
  end
260
293
 
294
+ # @private
295
+ class ParametersDoubles
296
+ def self.permitted_params_within(double_collection)
297
+ double_collection.calls_to(:permit).map(&:args).flatten
298
+ end
299
+
300
+ def initialize
301
+ klass = ::ActionController::Parameters
302
+ @double_collection = Doublespeak.double_collection_for(klass)
303
+ end
304
+
305
+ def register
306
+ double_collection.register_proxy(:permit)
307
+ end
308
+
309
+ def permitted_params
310
+ ParametersDoubles.permitted_params_within(double_collection)
311
+ end
312
+
313
+ protected
314
+
315
+ attr_reader :double_collection
316
+ end
317
+
318
+ # @private
319
+ class SliceOfParametersDoubles
320
+ TOP_LEVEL = Object.new
321
+
322
+ def initialize(subparameter)
323
+ klass = ::ActionController::Parameters
324
+
325
+ @subparameter = subparameter
326
+ @double_collections_by_param = {
327
+ TOP_LEVEL => Doublespeak.double_collection_for(klass)
328
+ }
329
+ end
330
+
331
+ def register
332
+ top_level_collection = double_collections_by_param[TOP_LEVEL]
333
+ double_permit_on(top_level_collection)
334
+ double_require_on(top_level_collection)
335
+ end
336
+
337
+ def permitted_params
338
+ if double_collections_by_param.key?(subparameter)
339
+ ParametersDoubles.permitted_params_within(
340
+ double_collections_by_param[subparameter]
341
+ )
342
+ else
343
+ []
344
+ end
345
+ end
346
+
347
+ protected
348
+
349
+ attr_reader :subparameter, :double_collections_by_param
350
+
351
+ private
352
+
353
+ def double_permit_on(double_collection)
354
+ double_collection.register_proxy(:permit)
355
+ end
356
+
357
+ def double_require_on(double_collection)
358
+ double_collections_by_param = @double_collections_by_param
359
+ require_double = double_collection.register_proxy(:require)
360
+
361
+ require_double.to_return do |call|
362
+ param_name = call.args.first
363
+ params = call.return_value
364
+ double_collections_by_param[param_name] ||=
365
+ double_permit_against(params)
366
+ end
367
+ end
368
+
369
+ def double_permit_against(params)
370
+ klass = params.singleton_class
371
+
372
+ Doublespeak.double_collection_for(klass).tap do |double_collection|
373
+ double_permit_on(double_collection)
374
+ end
375
+ end
376
+ end
377
+
261
378
  # @private
262
379
  class ActionNotDefinedError < StandardError
263
380
  def message
@@ -82,7 +82,7 @@ module Shoulda
82
82
  @context.__send__(:assert_redirected_to, url)
83
83
  @failure_message_when_negated = "Didn't expect to redirect to #{url}"
84
84
  true
85
- rescue Shoulda::Matchers::AssertionError => error
85
+ rescue Shoulda::Matchers.assertion_exception_class => error
86
86
  @failure_message = error.message
87
87
  false
88
88
  end
@@ -80,7 +80,7 @@ module Shoulda
80
80
  @context.__send__(:assert_template, @options, @message)
81
81
  @failure_message_when_negated = "Didn't expect to render #{@template}"
82
82
  true
83
- rescue Shoulda::Matchers::AssertionError => error
83
+ rescue Shoulda::Matchers.assertion_exception_class => error
84
84
  @failure_message = error.message
85
85
  false
86
86
  end
@@ -125,7 +125,7 @@ module Shoulda
125
125
 
126
126
  def recorded_layouts
127
127
  if @context
128
- @context.instance_variable_get(Shoulda::Matchers::RailsShim.layouts_ivar)
128
+ @context.instance_variable_get('@_layouts')
129
129
  else
130
130
  {}
131
131
  end