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
@@ -0,0 +1,433 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Shoulda::Matchers::ActionController::PermitMatcher, type: :controller do
4
+ shared_examples 'basic tests' do
5
+ it 'accepts a subset of the permitted attributes' do
6
+ define_controller_with_strong_parameters(action: :create) do |ctrl|
7
+ params_with_conditional_require(ctrl.params).permit(:name, :age)
8
+ end
9
+
10
+ expect(controller).to permit_with_conditional_params(
11
+ permit(:name).for(:create)
12
+ )
13
+ end
14
+
15
+ it 'accepts all of the permitted attributes' do
16
+ define_controller_with_strong_parameters(action: :create) do |ctrl|
17
+ params_with_conditional_require(ctrl.params).permit(:name, :age)
18
+ end
19
+
20
+ expect(controller).to permit_with_conditional_params(
21
+ permit(:name, :age).for(:create)
22
+ )
23
+ end
24
+
25
+ it 'rejects attributes that have not been permitted' do
26
+ define_controller_with_strong_parameters(action: :create) do |ctrl|
27
+ params_with_conditional_require(ctrl.params).permit(:name)
28
+ end
29
+
30
+ expect(controller).not_to permit_with_conditional_params(
31
+ permit(:name, :admin).for(:create)
32
+ )
33
+ end
34
+
35
+ it 'rejects when #permit has not been called' do
36
+ define_controller_with_strong_parameters(action: :create)
37
+
38
+ expect(controller).not_to permit_with_conditional_params(
39
+ permit(:name).for(:create)
40
+ )
41
+ end
42
+
43
+ it 'tracks multiple calls to #permit' do
44
+ sets_of_attributes = [
45
+ [:eta, :diner_id],
46
+ [:phone_number, :address_1, :address_2, :city, :state, :zip]
47
+ ]
48
+
49
+ params = {
50
+ order: { some: 'value' },
51
+ diner: { some: 'value' }
52
+ }
53
+
54
+ define_controller_with_strong_parameters(action: :create) do |ctrl|
55
+ params_with_conditional_require(ctrl.params, :order).
56
+ permit(sets_of_attributes[0])
57
+
58
+ params_with_conditional_require(ctrl.params, :diner).
59
+ permit(sets_of_attributes[1])
60
+ end
61
+
62
+ expect(controller).to permit_with_conditional_params(
63
+ permit(*sets_of_attributes[0]).for(:create),
64
+ params
65
+ )
66
+
67
+ expect(controller).to permit_with_conditional_params(
68
+ permit(*sets_of_attributes[1]).for(:create),
69
+ params
70
+ )
71
+ end
72
+ end
73
+
74
+ it 'requires an action' do
75
+ assertion = -> { expect(controller).to permit(:name) }
76
+
77
+ define_controller_with_strong_parameters
78
+
79
+ expect(&assertion).to raise_error(described_class::ActionNotDefinedError)
80
+ end
81
+
82
+ it 'requires a verb for a non-restful action' do
83
+ define_controller_with_strong_parameters
84
+
85
+ assertion = lambda do
86
+ expect(controller).to permit(:name).for(:authorize)
87
+ end
88
+
89
+ expect(&assertion).to raise_error(described_class::VerbNotDefinedError)
90
+ end
91
+
92
+ context 'when operating on the entire params hash' do
93
+ include_context 'basic tests' do
94
+ def permit_with_conditional_params(permit, _params = {})
95
+ permit
96
+ end
97
+
98
+ def params_with_conditional_require(params, *filters)
99
+ params
100
+ end
101
+ end
102
+ end
103
+
104
+ context 'when operating on a slice of the params hash' do
105
+ include_context 'basic tests' do
106
+ def permit_with_conditional_params(permit, params = nil)
107
+ params ||= { user: { some: 'value' } }
108
+ permit.add_params(params)
109
+ end
110
+
111
+ def params_with_conditional_require(params, *filters)
112
+ if filters.none?
113
+ filters = [:user]
114
+ end
115
+
116
+ params.require(*filters)
117
+ end
118
+ end
119
+
120
+ it 'rejects if asserting that parameters were not permitted, but on the wrong slice' do
121
+ define_controller_with_strong_parameters(action: :create) do
122
+ params.require(:order).permit(:eta, :diner_id)
123
+ end
124
+
125
+ expect(controller).
126
+ not_to permit(:eta, :diner_id).
127
+ for(:create, params: { order: { some: 'value' } }).
128
+ on(:something_else)
129
+ end
130
+ end
131
+
132
+ it 'can be used more than once in the same test' do
133
+ define_controller_with_strong_parameters(action: :create) do
134
+ params.permit(:name)
135
+ end
136
+
137
+ expect(controller).to permit(:name).for(:create)
138
+ expect(controller).not_to permit(:admin).for(:create)
139
+ end
140
+
141
+ it 'allows extra parameters to be passed to the action if it requires them' do
142
+ options = {
143
+ controller_name: 'Posts',
144
+ action: :show,
145
+ routes: -> { get '/posts/:slug', to: 'posts#show' }
146
+ }
147
+
148
+ define_controller_with_strong_parameters(options) do
149
+ params.permit(:name)
150
+ end
151
+
152
+ expect(controller).
153
+ to permit(:name).
154
+ for(:show, verb: :get, params: { slug: 'foo' })
155
+ end
156
+
157
+ it 'works with #update specifically' do
158
+ define_controller_with_strong_parameters(action: :update) do
159
+ params.permit(:name)
160
+ end
161
+
162
+ expect(controller).
163
+ to permit(:name).
164
+ for(:update, params: { id: 1 })
165
+ end
166
+
167
+ describe '#matches?' do
168
+ it 'does not raise an error when #fetch was used instead of #require (issue #495)' do
169
+ matcher = permit(:eta, :diner_id).for(:create)
170
+ matching = -> { matcher.matches?(controller) }
171
+
172
+ define_controller_with_strong_parameters(action: :create) do
173
+ params.fetch(:order, {}).permit(:eta, :diner_id)
174
+ end
175
+
176
+ expect(&matching).not_to raise_error
177
+ end
178
+
179
+ context 'stubbing params on the controller' do
180
+ it 'still allows the original params hash to be modified and accessed prior to the call to #require' do
181
+ actual_user_params = nil
182
+ actual_foo_param = nil
183
+ matcher = permit(:name).for(
184
+ :create,
185
+ params: { user: { some: 'params' } }
186
+ )
187
+
188
+ define_controller_with_strong_parameters(action: :create) do
189
+ params[:foo] = 'bar'
190
+ actual_foo_param = params[:foo]
191
+ actual_user_params = params[:user]
192
+
193
+ params.permit(:name)
194
+ end
195
+
196
+ matcher.matches?(controller)
197
+
198
+ expect(actual_user_params).to eq('some' => 'params')
199
+ expect(actual_foo_param).to eq 'bar'
200
+ end
201
+
202
+ it 'still allows #require to return a slice of the params' do
203
+ expected_user_params = { 'foo' => 'bar' }
204
+ actual_user_params = nil
205
+ matcher = permit(:name).for(
206
+ :update,
207
+ params: { id: 1, user: expected_user_params }
208
+ )
209
+
210
+ define_controller_with_strong_parameters(action: :update) do
211
+ actual_user_params = params.require(:user)
212
+ begin
213
+ actual_user_params.permit(:name)
214
+ rescue
215
+ end
216
+ end
217
+
218
+ matcher.matches?(controller)
219
+
220
+ expect(actual_user_params).to eq expected_user_params
221
+ end
222
+
223
+ it 'does not permanently stub the params hash' do
224
+ matcher = permit(:name).for(:create)
225
+ params_access = -> { controller.params.require(:user) }
226
+
227
+ define_controller_with_strong_parameters(action: :create)
228
+
229
+ matcher.matches?(controller)
230
+
231
+ expect(&params_access).
232
+ to raise_error(::ActionController::ParameterMissing)
233
+ end
234
+
235
+ it 'prevents permanently stubbing params on error' do
236
+ matcher = permit(:name).for(:create)
237
+ params_access = -> { controller.params.require(:user) }
238
+
239
+ define_controller_raising_exception
240
+
241
+ begin
242
+ matcher.matches?(controller)
243
+ rescue simulated_error_class
244
+ end
245
+
246
+ expect(&params_access).
247
+ to raise_error(::ActionController::ParameterMissing)
248
+ end
249
+ end
250
+ end
251
+
252
+ describe '#description' do
253
+ it 'returns the correct string' do
254
+ options = { action: :create, method: :post }
255
+
256
+ define_controller_with_strong_parameters(options) do
257
+ params.permit(:name, :age)
258
+ end
259
+
260
+ matcher = described_class.new([:name, :age, :height]).for(:create)
261
+ expect(matcher.description).to eq(
262
+ '(on POST #create) restrict parameters to :name, :age, and :height'
263
+ )
264
+ end
265
+
266
+ context 'when a verb is specified' do
267
+ it 'returns the correct string' do
268
+ options = { action: :some_action }
269
+
270
+ define_controller_with_strong_parameters(options) do
271
+ params.permit(:name, :age)
272
+ end
273
+
274
+ matcher = described_class.
275
+ new([:name]).
276
+ for(:some_action, verb: :put)
277
+ expect(matcher.description).to eq(
278
+ '(on PUT #some_action) restrict parameters to :name'
279
+ )
280
+ end
281
+ end
282
+ end
283
+
284
+ describe 'positive failure message' do
285
+ it 'includes all missing attributes' do
286
+ define_controller_with_strong_parameters(action: :create) do
287
+ params.permit(:name, :age)
288
+ end
289
+
290
+ assertion = lambda do
291
+ expect(@controller).
292
+ to permit(:name, :age, :city, :country).
293
+ for(:create)
294
+ end
295
+
296
+ message =
297
+ "Expected POST #create to restrict parameters to " +
298
+ ":name, :age, :city, and :country,\n" +
299
+ "but the restricted parameters were :name and :age instead."
300
+
301
+ expect(&assertion).to fail_with_message(message)
302
+ end
303
+ end
304
+
305
+ describe 'negative failure message' do
306
+ it 'includes all attributes that should not have been permitted but were' do
307
+ define_controller_with_strong_parameters(action: :create) do
308
+ params.permit(:name, :age)
309
+ end
310
+
311
+ assertion = lambda do
312
+ expect(controller).not_to permit(:name, :age).for(:create)
313
+ end
314
+
315
+ message =
316
+ "Expected POST #create not to restrict parameters to " +
317
+ ":name and :age,\n" +
318
+ "but it did."
319
+
320
+ expect(&assertion).to fail_with_message(message)
321
+ end
322
+ end
323
+
324
+ describe '#for' do
325
+ context 'when given :create' do
326
+ it 'POSTs to the controller' do
327
+ controller = ActionController::Base.new
328
+ context = build_context
329
+ matcher = permit(:name).for(:create).in_context(context)
330
+
331
+ matcher.matches?(controller)
332
+
333
+ expect(context).to have_received(:post).with(:create, {})
334
+ end
335
+ end
336
+
337
+ context 'when given :update' do
338
+ if rails_gte_4_1?
339
+ it 'PATCHes to the controller' do
340
+ controller = ActionController::Base.new
341
+ context = build_context
342
+ matcher = permit(:name).for(:update).in_context(context)
343
+
344
+ matcher.matches?(controller)
345
+
346
+ expect(context).to have_received(:patch).with(:update, {})
347
+ end
348
+ else
349
+ it 'PUTs to the controller' do
350
+ controller = ActionController::Base.new
351
+ context = build_context
352
+ matcher = permit(:name).for(:update).in_context(context)
353
+
354
+ matcher.matches?(controller)
355
+
356
+ expect(context).to have_received(:put).with(:update, {})
357
+ end
358
+ end
359
+ end
360
+
361
+ context 'when given a custom action and verb' do
362
+ it 'calls the action with the verb' do
363
+ controller = ActionController::Base.new
364
+ context = build_context
365
+ matcher = permit(:name).
366
+ for(:hide, verb: :delete).
367
+ in_context(context)
368
+
369
+ matcher.matches?(controller)
370
+
371
+ expect(context).to have_received(:delete).with(:hide, {})
372
+ end
373
+ end
374
+ end
375
+
376
+ let(:simulated_error_class) do
377
+ Class.new(StandardError)
378
+ end
379
+
380
+ def define_controller_with_strong_parameters(options = {}, &action_body)
381
+ model_name = options.fetch(:model_name, 'User')
382
+ controller_name = options.fetch(:controller_name, 'UsersController')
383
+ collection_name = controller_name.
384
+ to_s.sub(/Controller$/, '').underscore.
385
+ to_sym
386
+ action_name = options.fetch(:action, :some_action)
387
+ routes = options.fetch(:routes, -> { resources collection_name })
388
+
389
+ define_model(model_name)
390
+
391
+ controller_class = define_controller(controller_name) do
392
+ define_method action_name do
393
+ if action_body
394
+ if action_body.arity == 0
395
+ instance_eval(&action_body)
396
+ else
397
+ action_body.call(self)
398
+ end
399
+ end
400
+
401
+ render nothing: true
402
+ end
403
+ end
404
+
405
+ setup_rails_controller_test(controller_class)
406
+
407
+ define_routes(&routes)
408
+
409
+ controller_class
410
+ end
411
+
412
+ def define_controller_raising_exception
413
+ _simulated_error_class = simulated_error_class
414
+
415
+ controller_class = define_controller('Examples') do
416
+ define_method :create do
417
+ raise _simulated_error_class
418
+ end
419
+ end
420
+
421
+ setup_rails_controller_test(controller_class)
422
+
423
+ define_routes do
424
+ get 'examples', to: 'examples#create'
425
+ end
426
+
427
+ controller_class
428
+ end
429
+
430
+ def build_context
431
+ double('context', post: nil, put: nil, patch: nil, delete: nil)
432
+ end
433
+ end
@@ -52,11 +52,7 @@ describe Shoulda::Matchers::ActionController::RenderWithLayoutMatcher, type: :co
52
52
  def set_layout_in_context(context, layout)
53
53
  layouts = Hash.new(0)
54
54
  layouts[layout] = 1
55
- context.instance_variable_set(layouts_ivar, layouts)
56
- end
57
-
58
- def layouts_ivar
59
- Shoulda::Matchers::RailsShim.layouts_ivar
55
+ context.instance_variable_set('@_layouts', layouts)
60
56
  end
61
57
 
62
58
  def controller_without_layout
@@ -48,6 +48,26 @@ describe 'Shoulda::Matchers::ActionController::RouteMatcher', type: :controller
48
48
  to(action: 'show', some: 'other', params: 'here')
49
49
  end
50
50
  end
51
+
52
+ context 'when route has a default format' do
53
+ it 'accepts' do
54
+ expect(controller_with_defined_routes).
55
+ to route(:post, "/#{controller_path}").
56
+ to(action: 'create', format: 'json')
57
+ end
58
+
59
+ it 'accepts when format is specified as a symbol' do
60
+ expect(controller_with_defined_routes).
61
+ to route(:post, "/#{controller_path}").
62
+ to(action: 'create', format: :json)
63
+ end
64
+
65
+ it 'rejects when format is unspecified' do
66
+ expect(controller_with_defined_routes).
67
+ not_to route(:post, "/#{controller_path}").
68
+ to(action: 'create')
69
+ end
70
+ end
51
71
  end
52
72
 
53
73
  context 'when controller and action are specified as a joined string' do
@@ -64,6 +84,20 @@ describe 'Shoulda::Matchers::ActionController::RouteMatcher', type: :controller
64
84
  to("#{controller_path}#show", id: 1)
65
85
  end
66
86
  end
87
+
88
+ context 'when route has the format' do
89
+ it 'accepts' do
90
+ expect(controller_with_defined_routes).
91
+ to route(:post, "/#{controller_path}").
92
+ to("#{controller_path}#create", format: 'json')
93
+ end
94
+
95
+ it 'rejects when format is unspecified' do
96
+ expect(controller_with_defined_routes).
97
+ not_to route(:post, "/#{controller_path}").
98
+ to(action: 'create')
99
+ end
100
+ end
67
101
  end
68
102
 
69
103
  def controller_with_defined_routes
@@ -76,6 +110,9 @@ describe 'Shoulda::Matchers::ActionController::RouteMatcher', type: :controller
76
110
  define_routes do
77
111
  get "/#{_controller_path}", to: "#{_controller_path}#index"
78
112
  get "/#{_controller_path}/:id", to: "#{_controller_path}#show"
113
+ post "/#{_controller_path}",
114
+ to: "#{_controller_path}#create",
115
+ defaults: { format: :json }
79
116
  end
80
117
 
81
118
  controller