giga-safe-box 0.0.1

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 (140) hide show
  1. checksums.yaml +7 -0
  2. data/giga-safe-box.gemspec +11 -0
  3. data/shoulda-matchers-8.0.1/LICENSE +22 -0
  4. data/shoulda-matchers-8.0.1/README.md +567 -0
  5. data/shoulda-matchers-8.0.1/docs/errors/NonCaseSwappableValueError.md +111 -0
  6. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/callback_matcher.rb +121 -0
  7. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +70 -0
  8. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/flash_store.rb +86 -0
  9. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/permit_matcher.rb +445 -0
  10. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +96 -0
  11. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_template_matcher.rb +84 -0
  12. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +145 -0
  13. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +115 -0
  14. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +148 -0
  15. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_matcher.rb +207 -0
  16. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_params.rb +62 -0
  17. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
  18. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +228 -0
  19. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_matcher.rb +163 -0
  20. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +107 -0
  21. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller.rb +24 -0
  22. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
  23. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
  24. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +232 -0
  25. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
  26. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
  27. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
  28. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
  29. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
  30. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher.rb +695 -0
  31. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/comparison_matcher.rb +157 -0
  32. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +78 -0
  33. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/errors.rb +52 -0
  34. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +125 -0
  35. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/helpers.rb +37 -0
  36. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +45 -0
  37. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +67 -0
  38. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +45 -0
  39. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +44 -0
  40. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +71 -0
  41. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +53 -0
  42. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
  43. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
  44. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
  45. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
  46. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
  47. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers.rb +14 -0
  48. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +180 -0
  49. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +128 -0
  50. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +567 -0
  51. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +185 -0
  52. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +272 -0
  53. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +664 -0
  54. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +575 -0
  55. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +711 -0
  56. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +428 -0
  57. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +62 -0
  58. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher.rb +195 -0
  59. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_message_finder.rb +63 -0
  60. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validator.rb +127 -0
  61. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model.rb +96 -0
  62. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +217 -0
  63. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matcher.rb +2134 -0
  64. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +74 -0
  65. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +62 -0
  66. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +41 -0
  67. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +105 -0
  68. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +101 -0
  69. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +89 -0
  70. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +142 -0
  71. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +71 -0
  72. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
  73. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +76 -0
  74. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +42 -0
  75. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +65 -0
  76. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
  77. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +784 -0
  78. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/encrypt_matcher.rb +174 -0
  79. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_attached_matcher.rb +343 -0
  80. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +366 -0
  81. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +287 -0
  82. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +104 -0
  83. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +95 -0
  84. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
  85. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
  86. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/normalize_matcher.rb +151 -0
  87. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/serialize_matcher.rb +203 -0
  88. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/model.rb +58 -0
  89. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/namespace.rb +39 -0
  90. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +49 -0
  91. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +55 -0
  92. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness.rb +14 -0
  93. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1197 -0
  94. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record.rb +37 -0
  95. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/configuration.rb +31 -0
  96. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double.rb +103 -0
  97. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_collection.rb +60 -0
  98. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +31 -0
  99. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/method_call.rb +44 -0
  100. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/object_double.rb +43 -0
  101. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +32 -0
  102. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/stub_implementation.rb +31 -0
  103. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/world.rb +63 -0
  104. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak.rb +38 -0
  105. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/error.rb +29 -0
  106. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error.rb +15 -0
  107. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher.rb +540 -0
  108. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent.rb +11 -0
  109. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration.rb +70 -0
  110. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
  111. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
  112. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/action_controller.rb +33 -0
  113. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
  114. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
  115. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
  116. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/rails.rb +31 -0
  117. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/routing.rb +29 -0
  118. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries.rb +16 -0
  119. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/rails.rb +12 -0
  120. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/registry.rb +28 -0
  121. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
  122. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
  123. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
  124. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
  125. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
  126. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
  127. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
  128. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations.rb +43 -0
  129. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_collection.rb +99 -0
  130. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_context.rb +36 -0
  131. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/rails_shim.rb +190 -0
  132. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/routing.rb +10 -0
  133. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util/word_wrap.rb +211 -0
  134. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util.rb +110 -0
  135. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/version.rb +6 -0
  136. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/warn.rb +28 -0
  137. data/shoulda-matchers-8.0.1/lib/shoulda/matchers.rb +25 -0
  138. data/shoulda-matchers-8.0.1/lib/shoulda-matchers.rb +1 -0
  139. data/shoulda-matchers-8.0.1/shoulda-matchers.gemspec +43 -0
  140. metadata +178 -0
@@ -0,0 +1,445 @@
1
+ require 'delegate'
2
+
3
+ begin
4
+ require 'strong_parameters'
5
+ rescue LoadError
6
+ end
7
+
8
+ require 'active_support/hash_with_indifferent_access'
9
+
10
+ module Shoulda
11
+ module Matchers
12
+ module ActionController
13
+ # The `permit` matcher tests that an action in your controller receives a
14
+ # allowlist of parameters using Rails' Strong Parameters feature
15
+ # (specifically that `permit` was called with the correct arguments).
16
+ #
17
+ # Here's an example:
18
+ #
19
+ # class UsersController < ApplicationController
20
+ # def create
21
+ # user = User.create(user_params)
22
+ # # ...
23
+ # end
24
+ #
25
+ # private
26
+ #
27
+ # def user_params
28
+ # params.require(:user).permit(
29
+ # :first_name,
30
+ # :last_name,
31
+ # :email,
32
+ # :password
33
+ # )
34
+ # end
35
+ # end
36
+ #
37
+ # # RSpec
38
+ # RSpec.describe UsersController, type: :controller do
39
+ # it do
40
+ # params = {
41
+ # user: {
42
+ # first_name: 'John',
43
+ # last_name: 'Doe',
44
+ # email: 'johndoe@example.com',
45
+ # password: 'password'
46
+ # }
47
+ # }
48
+ # should permit(:first_name, :last_name, :email, :password).
49
+ # for(:create, params: params).
50
+ # on(:user)
51
+ # end
52
+ # end
53
+ #
54
+ # # Minitest (Shoulda)
55
+ # class UsersControllerTest < ActionController::TestCase
56
+ # should "(for POST #create) restrict parameters on :user to first_name, last_name, email, and password" do
57
+ # params = {
58
+ # user: {
59
+ # first_name: 'John',
60
+ # last_name: 'Doe',
61
+ # email: 'johndoe@example.com',
62
+ # password: 'password'
63
+ # }
64
+ # }
65
+ # matcher = permit(:first_name, :last_name, :email, :password).
66
+ # for(:create, params: params).
67
+ # on(:user)
68
+ # assert_accepts matcher, subject
69
+ # end
70
+ # end
71
+ #
72
+ # If your action requires query parameters in order to work, then you'll
73
+ # need to supply them:
74
+ #
75
+ # class UsersController < ApplicationController
76
+ # def update
77
+ # user = User.find(params[:id])
78
+ #
79
+ # if user.update_attributes(user_params)
80
+ # # ...
81
+ # else
82
+ # # ...
83
+ # end
84
+ # end
85
+ #
86
+ # private
87
+ #
88
+ # def user_params
89
+ # params.require(:user).permit(
90
+ # :first_name,
91
+ # :last_name,
92
+ # :email,
93
+ # :password
94
+ # )
95
+ # end
96
+ # end
97
+ #
98
+ # # RSpec
99
+ # RSpec.describe UsersController, type: :controller do
100
+ # before do
101
+ # create(:user, id: 1)
102
+ # end
103
+ #
104
+ # it do
105
+ # params = {
106
+ # id: 1,
107
+ # user: {
108
+ # first_name: 'Jon',
109
+ # last_name: 'Doe',
110
+ # email: 'jondoe@example.com',
111
+ # password: 'password'
112
+ # }
113
+ # }
114
+ # should permit(:first_name, :last_name, :email, :password).
115
+ # for(:update, params: params).
116
+ # on(:user)
117
+ # end
118
+ # end
119
+ #
120
+ # # Minitest (Shoulda)
121
+ # class UsersControllerTest < ActionController::TestCase
122
+ # setup do
123
+ # create(:user, id: 1)
124
+ # end
125
+ #
126
+ # should "(for PATCH #update) restrict parameters on :user to :first_name, :last_name, :email, and :password" do
127
+ # params = {
128
+ # id: 1,
129
+ # user: {
130
+ # first_name: 'Jon',
131
+ # last_name: 'Doe',
132
+ # email: 'jondoe@example.com',
133
+ # password: 'password'
134
+ # }
135
+ # }
136
+ # matcher = permit(:first_name, :last_name, :email, :password).
137
+ # for(:update, params: params).
138
+ # on(:user)
139
+ # assert_accepts matcher, subject
140
+ # end
141
+ # end
142
+ #
143
+ # Finally, if you have an action that isn't one of the seven resourceful
144
+ # actions, then you'll need to provide the HTTP verb that it responds to:
145
+ #
146
+ # Rails.application.routes.draw do
147
+ # resources :users do
148
+ # member do
149
+ # put :toggle
150
+ # end
151
+ # end
152
+ # end
153
+ #
154
+ # class UsersController < ApplicationController
155
+ # def toggle
156
+ # user = User.find(params[:id])
157
+ #
158
+ # if user.update_attributes(user_params)
159
+ # # ...
160
+ # else
161
+ # # ...
162
+ # end
163
+ # end
164
+ #
165
+ # private
166
+ #
167
+ # def user_params
168
+ # params.require(:user).permit(:activated)
169
+ # end
170
+ # end
171
+ #
172
+ # # RSpec
173
+ # RSpec.describe UsersController, type: :controller do
174
+ # before do
175
+ # create(:user, id: 1)
176
+ # end
177
+ #
178
+ # it do
179
+ # params = { id: 1, user: { activated: true } }
180
+ # should permit(:activated).
181
+ # for(:toggle, params: params, verb: :put).
182
+ # on(:user)
183
+ # end
184
+ # end
185
+ #
186
+ # # Minitest (Shoulda)
187
+ # class UsersControllerTest < ActionController::TestCase
188
+ # setup do
189
+ # create(:user, id: 1)
190
+ # end
191
+ #
192
+ # should "(for PUT #toggle) restrict parameters on :user to :activated" do
193
+ # params = { id: 1, user: { activated: true } }
194
+ # matcher = permit(:activated).
195
+ # for(:toggle, params: params, verb: :put).
196
+ # on(:user)
197
+ # assert_accepts matcher, subject
198
+ # end
199
+ # end
200
+ #
201
+ # @return [PermitMatcher]
202
+ #
203
+ def permit(*params)
204
+ PermitMatcher.new(params).in_context(self)
205
+ end
206
+
207
+ # @private
208
+ class PermitMatcher
209
+ attr_writer :stubbed_params
210
+
211
+ def initialize(expected_permitted_parameter_names)
212
+ @expected_permitted_parameter_names =
213
+ expected_permitted_parameter_names
214
+ @action = nil
215
+ @verb = nil
216
+ @request_params = {}
217
+ @subparameter_name = nil
218
+ @parameters_double_registry = CompositeParametersDoubleRegistry.new
219
+ end
220
+
221
+ def for(action, options = {})
222
+ @action = action
223
+ @verb = options.fetch(:verb, default_verb)
224
+ @request_params = options.fetch(:params, {})
225
+ self
226
+ end
227
+
228
+ def add_params(params)
229
+ request_params.merge!(params)
230
+ self
231
+ end
232
+
233
+ def on(subparameter_name)
234
+ @subparameter_name = subparameter_name
235
+ self
236
+ end
237
+
238
+ def in_context(context)
239
+ @context = context
240
+ self
241
+ end
242
+
243
+ def description
244
+ "(for #{verb.upcase} ##{action}) " + expectation
245
+ end
246
+
247
+ def matches?(controller)
248
+ @controller = controller
249
+ ensure_action_and_verb_present!
250
+
251
+ parameters_double_registry.register
252
+
253
+ Doublespeak.with_doubles_activated do
254
+ params = { params: request_params }
255
+
256
+ context.__send__(verb, action, **params)
257
+ end
258
+
259
+ unpermitted_parameter_names.empty?
260
+ end
261
+
262
+ def failure_message
263
+ "Expected #{verb.upcase} ##{action} to #{expectation},"\
264
+ "\nbut #{reality}."
265
+ end
266
+
267
+ def failure_message_when_negated
268
+ "Expected #{verb.upcase} ##{action} not to #{expectation},"\
269
+ "\nbut it did."
270
+ end
271
+
272
+ protected
273
+
274
+ attr_reader :controller, :double_collections_by_parameter_name, :action,
275
+ :verb, :request_params, :expected_permitted_parameter_names,
276
+ :context, :subparameter_name, :parameters_double_registry
277
+
278
+ def expectation
279
+ String.new('restrict parameters ').tap do |message|
280
+ if subparameter_name
281
+ message << "on #{subparameter_name.inspect} "
282
+ end
283
+
284
+ message << 'to '\
285
+ "#{format_parameter_names(expected_permitted_parameter_names)}"
286
+ end
287
+ end
288
+
289
+ def reality
290
+ if actual_permitted_parameter_names.empty?
291
+ 'it did not restrict any parameters'
292
+ else
293
+ 'the restricted parameters were '\
294
+ "#{format_parameter_names(actual_permitted_parameter_names)}"\
295
+ ' instead'
296
+ end
297
+ end
298
+
299
+ def format_parameter_names(parameter_names)
300
+ parameter_names.map(&:inspect).to_sentence
301
+ end
302
+
303
+ def actual_permitted_parameter_names
304
+ @_actual_permitted_parameter_names ||= begin
305
+ options =
306
+ if subparameter_name
307
+ { for: subparameter_name }
308
+ else
309
+ {}
310
+ end
311
+ parameters_double_registry.permitted_parameter_names(options)
312
+ end
313
+ end
314
+
315
+ def unpermitted_parameter_names
316
+ expected_permitted_parameter_names - actual_permitted_parameter_names
317
+ end
318
+
319
+ def ensure_action_and_verb_present!
320
+ if action.blank?
321
+ raise ActionNotDefinedError
322
+ end
323
+
324
+ if verb.blank?
325
+ raise VerbNotDefinedError
326
+ end
327
+ end
328
+
329
+ def default_verb
330
+ case action
331
+ when :create then :post
332
+ when :update then RailsShim.verb_for_update
333
+ end
334
+ end
335
+
336
+ def parameter_names_as_sentence
337
+ expected_permitted_parameter_names.map(&:inspect).to_sentence
338
+ end
339
+
340
+ # @private
341
+ class CompositeParametersDoubleRegistry
342
+ def initialize
343
+ @parameters_double_registries = []
344
+ end
345
+
346
+ def register
347
+ double_collection = Doublespeak.double_collection_for(
348
+ ::ActionController::Parameters.singleton_class,
349
+ )
350
+ double_collection.register_proxy(:new).to_return do |call|
351
+ params = call.return_value
352
+ parameters_double_registry = ParametersDoubleRegistry.new(params)
353
+ parameters_double_registry.register
354
+ parameters_double_registries << parameters_double_registry
355
+ end
356
+ end
357
+
358
+ def permitted_parameter_names(options = {})
359
+ parameters_double_registries.flat_map do |double_registry|
360
+ double_registry.permitted_parameter_names(options)
361
+ end
362
+ end
363
+
364
+ protected
365
+
366
+ attr_reader :parameters_double_registries
367
+ end
368
+
369
+ # @private
370
+ class ParametersDoubleRegistry
371
+ TOP_LEVEL = Object.new
372
+
373
+ def self.permitted_parameter_names_within(double_collection)
374
+ double_collection.calls_to(:permit).map(&:args).flatten
375
+ end
376
+
377
+ def initialize(params)
378
+ @params = params
379
+ @double_collections_by_parameter_name = {}
380
+ end
381
+
382
+ def register
383
+ register_double_for_permit_against(params, TOP_LEVEL)
384
+ end
385
+
386
+ def permitted_parameter_names(args = {})
387
+ subparameter_name = args.fetch(:for, TOP_LEVEL)
388
+
389
+ if double_collections_by_parameter_name.key?(subparameter_name)
390
+ self.class.permitted_parameter_names_within(
391
+ double_collections_by_parameter_name[subparameter_name],
392
+ )
393
+ else
394
+ []
395
+ end
396
+ end
397
+
398
+ protected
399
+
400
+ attr_reader :params, :double_collections_by_parameter_name
401
+
402
+ private
403
+
404
+ def register_double_for_permit_against(params, subparameter_name)
405
+ klass = params.singleton_class
406
+
407
+ double_collection = Doublespeak.double_collection_for(klass)
408
+ register_double_for_permit_on(double_collection)
409
+ register_double_for_require_on(double_collection)
410
+
411
+ double_collections_by_parameter_name[subparameter_name] =
412
+ double_collection
413
+ end
414
+
415
+ def register_double_for_permit_on(double_collection)
416
+ double_collection.register_proxy(:permit)
417
+ end
418
+
419
+ def register_double_for_require_on(double_collection)
420
+ double_collection.register_proxy(:require).to_return do |call|
421
+ params = call.return_value
422
+ subparameter_name = call.args.first
423
+ register_double_for_permit_against(params, subparameter_name)
424
+ end
425
+ end
426
+ end
427
+
428
+ # @private
429
+ class ActionNotDefinedError < StandardError
430
+ def message
431
+ 'You must specify the controller action using the #for method.'
432
+ end
433
+ end
434
+
435
+ # @private
436
+ class VerbNotDefinedError < StandardError
437
+ def message
438
+ 'You must specify an HTTP verb when using a non-RESTful action.'\
439
+ ' For example: for(:authorize, verb: :post)'
440
+ end
441
+ end
442
+ end
443
+ end
444
+ end
445
+ end
@@ -0,0 +1,96 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActionController
4
+ # The `redirect_to` matcher tests that an action redirects to a certain
5
+ # location. In a test suite using RSpec, it is very similar to
6
+ # rspec-rails's `redirect_to` matcher. In a test suite using Minitest +
7
+ # Shoulda, it provides a more expressive syntax over
8
+ # `assert_redirected_to`.
9
+ #
10
+ # class PostsController < ApplicationController
11
+ # def show
12
+ # redirect_to :index
13
+ # end
14
+ # end
15
+ #
16
+ # # RSpec
17
+ # RSpec.describe PostsController, type: :controller do
18
+ # describe 'GET #show' do
19
+ # before { get :show }
20
+ #
21
+ # it { should redirect_to(posts_path) }
22
+ # it { should redirect_to(action: :index) }
23
+ # end
24
+ # end
25
+ #
26
+ # # Minitest (Shoulda)
27
+ # class PostsControllerTest < ActionController::TestCase
28
+ # context 'GET #show' do
29
+ # setup { get :show }
30
+ #
31
+ # should redirect_to('/posts') { posts_path }
32
+ # should redirect_to(action: :index)
33
+ # end
34
+ # end
35
+ #
36
+ # @return [RedirectToMatcher]
37
+ #
38
+ def redirect_to(url_or_description, &block)
39
+ RedirectToMatcher.new(url_or_description, self, &block)
40
+ end
41
+
42
+ # @private
43
+ class RedirectToMatcher
44
+ attr_reader :failure_message, :failure_message_when_negated
45
+
46
+ def initialize(url_or_description, context, &block)
47
+ @url_block = nil
48
+ @url = nil
49
+ @context = context
50
+ @failure_message = nil
51
+ @failure_message_when_negated = nil
52
+
53
+ if block
54
+ @url_block = block
55
+ @location = url_or_description
56
+ else
57
+ @location = @url = url_or_description
58
+ end
59
+ end
60
+
61
+ def in_context(context)
62
+ @context = context
63
+ self
64
+ end
65
+
66
+ def matches?(controller)
67
+ @controller = controller
68
+ redirects_to_url?
69
+ end
70
+
71
+ def description
72
+ "redirect to #{@location.inspect}"
73
+ end
74
+
75
+ private
76
+
77
+ def redirects_to_url?
78
+ @context.__send__(:assert_redirected_to, url)
79
+ @failure_message_when_negated = "Didn't expect to redirect to #{url}"
80
+ true
81
+ rescue Shoulda::Matchers.assertion_exception_class => e
82
+ @failure_message = e.message
83
+ false
84
+ end
85
+
86
+ def url
87
+ if @url_block
88
+ @context.instance_eval(&@url_block)
89
+ else
90
+ @url
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,84 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActionController
4
+ # The `render_template` matcher tests that an action renders a template
5
+ # or partial. In RSpec, it is very similar to rspec-rails's
6
+ # `render_template` matcher. In a test suite using Minitest + Shoulda, it
7
+ # provides a more expressive syntax over `assert_template`.
8
+ #
9
+ # class PostsController < ApplicationController
10
+ # def show
11
+ # end
12
+ # end
13
+ #
14
+ # # app/views/posts/show.html.erb
15
+ # <%= render 'sidebar' %>
16
+ #
17
+ # # RSpec
18
+ # RSpec.describe PostsController, type: :controller do
19
+ # describe 'GET #show' do
20
+ # before { get :show }
21
+ #
22
+ # it { should render_template('show') }
23
+ # it { should render_template(partial: '_sidebar') }
24
+ # end
25
+ # end
26
+ #
27
+ # # Minitest (Shoulda)
28
+ # class PostsControllerTest < ActionController::TestCase
29
+ # context 'GET #show' do
30
+ # setup { get :show }
31
+ #
32
+ # should render_template('show')
33
+ # should render_template(partial: '_sidebar')
34
+ # end
35
+ # end
36
+ #
37
+ # @return [RenderTemplateMatcher]
38
+ #
39
+ def render_template(options = {}, message = nil)
40
+ RenderTemplateMatcher.new(options, message, self)
41
+ end
42
+
43
+ # @private
44
+ class RenderTemplateMatcher
45
+ attr_reader :failure_message, :failure_message_when_negated
46
+
47
+ def initialize(options, message, context)
48
+ @options = options
49
+ @message = message
50
+ @template = options.is_a?(Hash) ? options[:partial] : options
51
+ @context = context
52
+ @controller = nil
53
+ @failure_message = nil
54
+ @failure_message_when_negated = nil
55
+ end
56
+
57
+ def matches?(controller)
58
+ @controller = controller
59
+ renders_template?
60
+ end
61
+
62
+ def description
63
+ "render template #{@template}"
64
+ end
65
+
66
+ def in_context(context)
67
+ @context = context
68
+ self
69
+ end
70
+
71
+ private
72
+
73
+ def renders_template?
74
+ @context.__send__(:assert_template, @options, @message)
75
+ @failure_message_when_negated = "Didn't expect to render #{@template}"
76
+ true
77
+ rescue Shoulda::Matchers.assertion_exception_class => e
78
+ @failure_message = e.message
79
+ false
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end