mini-quick-sys 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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/mini-quick-sys.gemspec +12 -0
  3. data/rspec-rails-8.0.4/Capybara.md +28 -0
  4. data/rspec-rails-8.0.4/Changelog.md +1408 -0
  5. data/rspec-rails-8.0.4/LICENSE.md +25 -0
  6. data/rspec-rails-8.0.4/README.md +386 -0
  7. data/rspec-rails-8.0.4/lib/generators/rspec/authentication/authentication_generator.rb +25 -0
  8. data/rspec-rails-8.0.4/lib/generators/rspec/authentication/templates/user_spec.rb +5 -0
  9. data/rspec-rails-8.0.4/lib/generators/rspec/authentication/templates/users.yml +11 -0
  10. data/rspec-rails-8.0.4/lib/generators/rspec/channel/channel_generator.rb +12 -0
  11. data/rspec-rails-8.0.4/lib/generators/rspec/channel/templates/channel_spec.rb.erb +7 -0
  12. data/rspec-rails-8.0.4/lib/generators/rspec/controller/controller_generator.rb +51 -0
  13. data/rspec-rails-8.0.4/lib/generators/rspec/controller/templates/controller_spec.rb +16 -0
  14. data/rspec-rails-8.0.4/lib/generators/rspec/controller/templates/request_spec.rb +19 -0
  15. data/rspec-rails-8.0.4/lib/generators/rspec/controller/templates/routing_spec.rb +13 -0
  16. data/rspec-rails-8.0.4/lib/generators/rspec/controller/templates/view_spec.rb +5 -0
  17. data/rspec-rails-8.0.4/lib/generators/rspec/feature/feature_generator.rb +29 -0
  18. data/rspec-rails-8.0.4/lib/generators/rspec/feature/templates/feature_singular_spec.rb +5 -0
  19. data/rspec-rails-8.0.4/lib/generators/rspec/feature/templates/feature_spec.rb +5 -0
  20. data/rspec-rails-8.0.4/lib/generators/rspec/generator/generator_generator.rb +24 -0
  21. data/rspec-rails-8.0.4/lib/generators/rspec/generator/templates/generator_spec.rb +5 -0
  22. data/rspec-rails-8.0.4/lib/generators/rspec/helper/helper_generator.rb +16 -0
  23. data/rspec-rails-8.0.4/lib/generators/rspec/helper/templates/helper_spec.rb +17 -0
  24. data/rspec-rails-8.0.4/lib/generators/rspec/install/install_generator.rb +80 -0
  25. data/rspec-rails-8.0.4/lib/generators/rspec/install/templates/spec/rails_helper.rb +91 -0
  26. data/rspec-rails-8.0.4/lib/generators/rspec/job/job_generator.rb +13 -0
  27. data/rspec-rails-8.0.4/lib/generators/rspec/job/templates/job_spec.rb.erb +7 -0
  28. data/rspec-rails-8.0.4/lib/generators/rspec/mailbox/mailbox_generator.rb +14 -0
  29. data/rspec-rails-8.0.4/lib/generators/rspec/mailbox/templates/mailbox_spec.rb.erb +7 -0
  30. data/rspec-rails-8.0.4/lib/generators/rspec/mailer/mailer_generator.rb +30 -0
  31. data/rspec-rails-8.0.4/lib/generators/rspec/mailer/templates/fixture +3 -0
  32. data/rspec-rails-8.0.4/lib/generators/rspec/mailer/templates/mailer_spec.rb +25 -0
  33. data/rspec-rails-8.0.4/lib/generators/rspec/mailer/templates/preview.rb +13 -0
  34. data/rspec-rails-8.0.4/lib/generators/rspec/model/model_generator.rb +37 -0
  35. data/rspec-rails-8.0.4/lib/generators/rspec/model/templates/fixtures.yml +19 -0
  36. data/rspec-rails-8.0.4/lib/generators/rspec/model/templates/model_spec.rb +7 -0
  37. data/rspec-rails-8.0.4/lib/generators/rspec/request/request_generator.rb +17 -0
  38. data/rspec-rails-8.0.4/lib/generators/rspec/request/templates/request_spec.rb +10 -0
  39. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/scaffold_generator.rb +136 -0
  40. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +129 -0
  41. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/templates/api_request_spec.rb +131 -0
  42. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/templates/controller_spec.rb +145 -0
  43. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/templates/edit_spec.rb +27 -0
  44. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/templates/index_spec.rb +26 -0
  45. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/templates/new_spec.rb +22 -0
  46. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/templates/request_spec.rb +138 -0
  47. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/templates/routing_spec.rb +46 -0
  48. data/rspec-rails-8.0.4/lib/generators/rspec/scaffold/templates/show_spec.rb +21 -0
  49. data/rspec-rails-8.0.4/lib/generators/rspec/system/system_generator.rb +24 -0
  50. data/rspec-rails-8.0.4/lib/generators/rspec/system/templates/system_spec.rb +9 -0
  51. data/rspec-rails-8.0.4/lib/generators/rspec/view/templates/view_spec.rb +5 -0
  52. data/rspec-rails-8.0.4/lib/generators/rspec/view/view_generator.rb +22 -0
  53. data/rspec-rails-8.0.4/lib/generators/rspec.rb +56 -0
  54. data/rspec-rails-8.0.4/lib/rspec/rails/active_record.rb +25 -0
  55. data/rspec-rails-8.0.4/lib/rspec/rails/adapters.rb +196 -0
  56. data/rspec-rails-8.0.4/lib/rspec/rails/configuration.rb +158 -0
  57. data/rspec-rails-8.0.4/lib/rspec/rails/example/channel_example_group.rb +93 -0
  58. data/rspec-rails-8.0.4/lib/rspec/rails/example/controller_example_group.rb +217 -0
  59. data/rspec-rails-8.0.4/lib/rspec/rails/example/feature_example_group.rb +53 -0
  60. data/rspec-rails-8.0.4/lib/rspec/rails/example/helper_example_group.rb +42 -0
  61. data/rspec-rails-8.0.4/lib/rspec/rails/example/job_example_group.rb +23 -0
  62. data/rspec-rails-8.0.4/lib/rspec/rails/example/mailbox_example_group.rb +80 -0
  63. data/rspec-rails-8.0.4/lib/rspec/rails/example/mailer_example_group.rb +38 -0
  64. data/rspec-rails-8.0.4/lib/rspec/rails/example/model_example_group.rb +11 -0
  65. data/rspec-rails-8.0.4/lib/rspec/rails/example/rails_example_group.rb +23 -0
  66. data/rspec-rails-8.0.4/lib/rspec/rails/example/request_example_group.rb +27 -0
  67. data/rspec-rails-8.0.4/lib/rspec/rails/example/routing_example_group.rb +61 -0
  68. data/rspec-rails-8.0.4/lib/rspec/rails/example/system_example_group.rb +177 -0
  69. data/rspec-rails-8.0.4/lib/rspec/rails/example/view_example_group.rb +214 -0
  70. data/rspec-rails-8.0.4/lib/rspec/rails/example.rb +13 -0
  71. data/rspec-rails-8.0.4/lib/rspec/rails/extensions/active_record/proxy.rb +11 -0
  72. data/rspec-rails-8.0.4/lib/rspec/rails/extensions.rb +1 -0
  73. data/rspec-rails-8.0.4/lib/rspec/rails/feature_check.rb +51 -0
  74. data/rspec-rails-8.0.4/lib/rspec/rails/file_fixture_support.rb +18 -0
  75. data/rspec-rails-8.0.4/lib/rspec/rails/fixture_file_upload_support.rb +39 -0
  76. data/rspec-rails-8.0.4/lib/rspec/rails/fixture_support.rb +58 -0
  77. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +180 -0
  78. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
  79. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/action_cable.rb +70 -0
  80. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/action_mailbox.rb +73 -0
  81. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/active_job.rb +534 -0
  82. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/base_matcher.rb +179 -0
  83. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/be_a_new.rb +83 -0
  84. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/be_new_record.rb +30 -0
  85. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/be_valid.rb +49 -0
  86. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/have_enqueued_mail.rb +259 -0
  87. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/have_http_status.rb +381 -0
  88. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/have_rendered.rb +64 -0
  89. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/redirect_to.rb +38 -0
  90. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/relation_match_array.rb +3 -0
  91. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/routing_matchers.rb +125 -0
  92. data/rspec-rails-8.0.4/lib/rspec/rails/matchers/send_email.rb +122 -0
  93. data/rspec-rails-8.0.4/lib/rspec/rails/matchers.rb +36 -0
  94. data/rspec-rails-8.0.4/lib/rspec/rails/tasks/rspec.rake +49 -0
  95. data/rspec-rails-8.0.4/lib/rspec/rails/vendor/capybara.rb +32 -0
  96. data/rspec-rails-8.0.4/lib/rspec/rails/version.rb +9 -0
  97. data/rspec-rails-8.0.4/lib/rspec/rails/view_assigns.rb +27 -0
  98. data/rspec-rails-8.0.4/lib/rspec/rails/view_path_builder.rb +29 -0
  99. data/rspec-rails-8.0.4/lib/rspec/rails/view_rendering.rb +166 -0
  100. data/rspec-rails-8.0.4/lib/rspec/rails/view_spec_methods.rb +56 -0
  101. data/rspec-rails-8.0.4/lib/rspec/rails.rb +18 -0
  102. data/rspec-rails-8.0.4/lib/rspec-rails.rb +91 -0
  103. metadata +142 -0
@@ -0,0 +1,381 @@
1
+ # The following code inspired and modified from Rails' `assert_response`:
2
+ #
3
+ # https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/testing/assertions/response.rb#L22-L38
4
+ #
5
+ # Thank you to all the Rails devs who did the heavy lifting on this!
6
+
7
+ module RSpec
8
+ module Rails
9
+ module Matchers
10
+ # Namespace for various implementations of `have_http_status`.
11
+ #
12
+ # @api private
13
+ module HaveHttpStatus
14
+ # Instantiates an instance of the proper matcher based on the provided
15
+ # `target`.
16
+ #
17
+ # @param target [Object] expected http status or code
18
+ # @return response matcher instance
19
+ def self.matcher_for_status(target)
20
+ if GenericStatus.valid_statuses.include?(target)
21
+ GenericStatus.new(target)
22
+ elsif Symbol === target
23
+ SymbolicStatus.new(target)
24
+ else
25
+ NumericCode.new(target)
26
+ end
27
+ end
28
+
29
+ # @api private
30
+ # Conversion function to coerce the provided object into an
31
+ # `ActionDispatch::TestResponse`.
32
+ #
33
+ # @param obj [Object] object to convert to a response
34
+ # @return [ActionDispatch::TestResponse]
35
+ def as_test_response(obj)
36
+ if ::ActionDispatch::Response === obj || ::Rack::MockResponse === obj
37
+ ::ActionDispatch::TestResponse.from_response(obj)
38
+ elsif ::ActionDispatch::TestResponse === obj
39
+ obj
40
+ elsif obj.respond_to?(:status_code) && obj.respond_to?(:response_headers)
41
+ # Acts As Capybara Session
42
+ # Hack to support `Capybara::Session` without having to load
43
+ # Capybara or catch `NameError`s for the undefined constants
44
+ obj = ActionDispatch::Response.new.tap do |resp|
45
+ resp.status = obj.status_code
46
+ resp.headers.clear
47
+ resp.headers.merge!(obj.response_headers)
48
+ resp.body = obj.body
49
+ resp.request = ActionDispatch::Request.new({})
50
+ end
51
+ ::ActionDispatch::TestResponse.from_response(obj)
52
+ else
53
+ raise TypeError, "Invalid response type: #{obj}"
54
+ end
55
+ end
56
+ module_function :as_test_response
57
+
58
+ # @return [String, nil] a formatted failure message if
59
+ # `@invalid_response` is present, `nil` otherwise
60
+ def invalid_response_type_message
61
+ return unless @invalid_response
62
+
63
+ "expected a response object, but an instance of " \
64
+ "#{@invalid_response.class} was received"
65
+ end
66
+
67
+ # @api private
68
+ # Provides an implementation for `have_http_status` matching against
69
+ # numeric http status codes.
70
+ #
71
+ # Not intended to be instantiated directly.
72
+ #
73
+ # @example
74
+ # expect(response).to have_http_status(404)
75
+ #
76
+ # @see RSpec::Rails::Matchers#have_http_status
77
+ class NumericCode < RSpec::Rails::Matchers::BaseMatcher
78
+ include HaveHttpStatus
79
+
80
+ def initialize(code)
81
+ @expected = code.to_i
82
+ @actual = nil
83
+ @invalid_response = nil
84
+ end
85
+
86
+ # @param [Object] response object providing an http code to match
87
+ # @return [Boolean] `true` if the numeric code matched the `response` code
88
+ def matches?(response)
89
+ test_response = as_test_response(response)
90
+ @actual = test_response.response_code.to_i
91
+ expected == @actual
92
+ rescue TypeError => _ignored
93
+ @invalid_response = response
94
+ false
95
+ end
96
+
97
+ # @return [String]
98
+ def description
99
+ "respond with numeric status code #{expected}"
100
+ end
101
+
102
+ # @return [String] explaining why the match failed
103
+ def failure_message
104
+ invalid_response_type_message ||
105
+ "expected the response to have status code #{expected.inspect}" \
106
+ " but it was #{actual.inspect}"
107
+ end
108
+
109
+ # @return [String] explaining why the match failed
110
+ def failure_message_when_negated
111
+ invalid_response_type_message ||
112
+ "expected the response not to have status code " \
113
+ "#{expected.inspect} but it did"
114
+ end
115
+ end
116
+
117
+ # @api private
118
+ # Provides an implementation for `have_http_status` matching against
119
+ # Rack symbol http status codes.
120
+ #
121
+ # Not intended to be instantiated directly.
122
+ #
123
+ # @example
124
+ # expect(response).to have_http_status(:created)
125
+ #
126
+ # @see RSpec::Rails::Matchers#have_http_status
127
+ # @see https://github.com/rack/rack/blob/master/lib/rack/utils.rb `Rack::Utils::SYMBOL_TO_STATUS_CODE`
128
+ class SymbolicStatus < RSpec::Rails::Matchers::BaseMatcher
129
+ include HaveHttpStatus
130
+
131
+ def initialize(status)
132
+ @expected_status = status
133
+ @actual = nil
134
+ @invalid_response = nil
135
+ set_expected_code!
136
+ end
137
+
138
+ # @param [Object] response object providing an http code to match
139
+ # @return [Boolean] `true` if Rack's associated numeric HTTP code matched
140
+ # the `response` code
141
+ def matches?(response)
142
+ test_response = as_test_response(response)
143
+ @actual = test_response.response_code
144
+ expected == @actual
145
+ rescue TypeError => _ignored
146
+ @invalid_response = response
147
+ false
148
+ end
149
+
150
+ # @return [String]
151
+ def description
152
+ "respond with status code #{pp_expected}"
153
+ end
154
+
155
+ # @return [String] explaining why the match failed
156
+ def failure_message
157
+ invalid_response_type_message ||
158
+ "expected the response to have status code #{pp_expected} but it" \
159
+ " was #{pp_actual}"
160
+ end
161
+
162
+ # @return [String] explaining why the match failed
163
+ def failure_message_when_negated
164
+ invalid_response_type_message ||
165
+ "expected the response not to have status code #{pp_expected} " \
166
+ "but it did"
167
+ end
168
+
169
+ # The initialized expected status symbol
170
+ attr_reader :expected_status
171
+ private :expected_status
172
+
173
+ private
174
+
175
+ # @return [Symbol] representing the actual http numeric code
176
+ def actual_status
177
+ return unless actual
178
+
179
+ @actual_status ||= compute_status_from(actual)
180
+ end
181
+
182
+ # Reverse lookup of the Rack status code symbol based on the numeric
183
+ # http code
184
+ #
185
+ # @param code [Fixnum] http status code to look up
186
+ # @return [Symbol] representing the http numeric code
187
+ def compute_status_from(code)
188
+ status, _ = Rack::Utils::SYMBOL_TO_STATUS_CODE.find do |_, c|
189
+ c == code
190
+ end
191
+ status
192
+ end
193
+
194
+ # @return [String] pretty format the actual response status
195
+ def pp_actual
196
+ pp_status(actual_status, actual)
197
+ end
198
+
199
+ # @return [String] pretty format the expected status and associated code
200
+ def pp_expected
201
+ pp_status(expected_status, expected)
202
+ end
203
+
204
+ # @return [String] pretty format the actual response status
205
+ def pp_status(status, code)
206
+ if status
207
+ "#{status.inspect} (#{code})"
208
+ else
209
+ code.to_s
210
+ end
211
+ end
212
+
213
+ # Sets `expected` to the numeric http code based on the Rack
214
+ # `expected_status` status
215
+ #
216
+ # @see Rack::Utils::SYMBOL_TO_STATUS_CODE
217
+ # @raise [ArgumentError] if an associated code could not be found
218
+ def set_expected_code!
219
+ @expected ||= Rack::Utils.status_code(expected_status)
220
+ end
221
+ end
222
+
223
+ # @api private
224
+ # Provides an implementation for `have_http_status` matching against
225
+ # `ActionDispatch::TestResponse` http status category queries.
226
+ #
227
+ # Not intended to be instantiated directly.
228
+ #
229
+ # @example
230
+ # expect(response).to have_http_status(:success)
231
+ # expect(response).to have_http_status(:error)
232
+ # expect(response).to have_http_status(:missing)
233
+ # expect(response).to have_http_status(:redirect)
234
+ #
235
+ # @see RSpec::Rails::Matchers#have_http_status
236
+ # @see https://github.com/rails/rails/blob/7-2-stable/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
237
+ class GenericStatus < RSpec::Rails::Matchers::BaseMatcher
238
+ include HaveHttpStatus
239
+
240
+ # @return [Array<Symbol>] of status codes which represent a HTTP status
241
+ # code "group"
242
+ # @see https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
243
+ def self.valid_statuses
244
+ [
245
+ :error, :success, :missing,
246
+ :server_error, :successful, :not_found,
247
+ :redirect
248
+ ]
249
+ end
250
+
251
+ def initialize(type)
252
+ unless self.class.valid_statuses.include?(type)
253
+ raise ArgumentError, "Invalid generic HTTP status: #{type.inspect}"
254
+ end
255
+
256
+ @expected = type
257
+ @actual = nil
258
+ @invalid_response = nil
259
+ end
260
+
261
+ # @return [Boolean] `true` if Rack's associated numeric HTTP code matched
262
+ # the `response` code or the named response status
263
+ def matches?(response)
264
+ test_response = as_test_response(response)
265
+ @actual = test_response.response_code
266
+ check_expected_status(test_response, expected)
267
+ rescue TypeError => _ignored
268
+ @invalid_response = response
269
+ false
270
+ end
271
+
272
+ # @return [String]
273
+ def description
274
+ "respond with #{type_message}"
275
+ end
276
+
277
+ # @return [String] explaining why the match failed
278
+ def failure_message
279
+ invalid_response_type_message ||
280
+ "expected the response to have #{type_message} but it was #{actual}"
281
+ end
282
+
283
+ # @return [String] explaining why the match failed
284
+ def failure_message_when_negated
285
+ invalid_response_type_message ||
286
+ "expected the response not to have #{type_message} but it was #{actual}"
287
+ end
288
+
289
+ protected
290
+
291
+ RESPONSE_METHODS = {
292
+ success: 'successful',
293
+ error: 'server_error',
294
+ missing: 'not_found'
295
+ }.freeze
296
+
297
+ def check_expected_status(test_response, expected)
298
+ test_response.send(
299
+ "#{RESPONSE_METHODS.fetch(expected, expected)}?")
300
+ end
301
+
302
+ private
303
+
304
+ # @return [String] formatting the expected status and associated code(s)
305
+ def type_message
306
+ @type_message ||= (expected == :error ? "an error" : "a #{expected}") +
307
+ " status code (#{type_codes})"
308
+ end
309
+
310
+ # @return [String] formatting the associated code(s) for the various
311
+ # status code "groups"
312
+ # @see https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
313
+ # @see https://github.com/rack/rack/blob/master/lib/rack/response.rb `Rack::Response`
314
+ def type_codes
315
+ # At the time of this commit the most recent version of
316
+ # `ActionDispatch::TestResponse` defines the following aliases:
317
+ #
318
+ # alias_method :success?, :successful?
319
+ # alias_method :missing?, :not_found?
320
+ # alias_method :redirect?, :redirection?
321
+ # alias_method :error?, :server_error?
322
+ #
323
+ # It's parent `ActionDispatch::Response` includes
324
+ # `Rack::Response::Helpers` which defines the aliased methods as:
325
+ #
326
+ # def successful?; status >= 200 && status < 300; end
327
+ # def redirection?; status >= 300 && status < 400; end
328
+ # def server_error?; status >= 500 && status < 600; end
329
+ # def not_found?; status == 404; end
330
+ #
331
+ # @see https://github.com/rails/rails/blob/ca200378/actionpack/lib/action_dispatch/testing/test_response.rb#L17-L27
332
+ # @see https://github.com/rails/rails/blob/ca200378/actionpack/lib/action_dispatch/http/response.rb#L74
333
+ # @see https://github.com/rack/rack/blob/ce4a3959/lib/rack/response.rb#L119-L122
334
+ @type_codes ||= case expected
335
+ when :error, :server_error
336
+ "5xx"
337
+ when :success, :successful
338
+ "2xx"
339
+ when :missing, :not_found
340
+ "404"
341
+ when :redirect
342
+ "3xx"
343
+ end
344
+ end
345
+ end
346
+ end
347
+
348
+ # @api public
349
+ # Passes if `response` has a matching HTTP status code.
350
+ #
351
+ # The following symbolic status codes are allowed:
352
+ #
353
+ # - `Rack::Utils::SYMBOL_TO_STATUS_CODE`
354
+ # - One of the defined `ActionDispatch::TestResponse` aliases:
355
+ # - `:error`
356
+ # - `:missing`
357
+ # - `:redirect`
358
+ # - `:success`
359
+ #
360
+ # @example Accepts numeric and symbol statuses
361
+ # expect(response).to have_http_status(404)
362
+ # expect(response).to have_http_status(:created)
363
+ # expect(response).to have_http_status(:success)
364
+ # expect(response).to have_http_status(:error)
365
+ # expect(response).to have_http_status(:missing)
366
+ # expect(response).to have_http_status(:redirect)
367
+ #
368
+ # @example Works with standard `response` objects and Capybara's `page`
369
+ # expect(response).to have_http_status(404)
370
+ # expect(page).to have_http_status(:created)
371
+ #
372
+ # @see https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
373
+ # @see https://github.com/rack/rack/blob/master/lib/rack/utils.rb `Rack::Utils::SYMBOL_TO_STATUS_CODE`
374
+ def have_http_status(target)
375
+ raise ArgumentError, "Invalid HTTP status: nil" unless target
376
+
377
+ HaveHttpStatus.matcher_for_status(target)
378
+ end
379
+ end
380
+ end
381
+ end
@@ -0,0 +1,64 @@
1
+ module RSpec
2
+ module Rails
3
+ module Matchers
4
+ # Matcher for template rendering.
5
+ module RenderTemplate
6
+ # @private
7
+ class RenderTemplateMatcher < RSpec::Rails::Matchers::BaseMatcher
8
+ def initialize(scope, expected, message = nil)
9
+ @expected = Symbol === expected ? expected.to_s : expected
10
+ @message = message
11
+ @scope = scope
12
+ @redirect_is = nil
13
+ end
14
+
15
+ # @api private
16
+ def matches?(*)
17
+ match_check = match_unless_raises ActiveSupport::TestCase::Assertion do
18
+ @scope.assert_template expected, @message
19
+ end
20
+ check_redirect unless match_check
21
+ match_check
22
+ end
23
+
24
+ # Uses normalize_argument_to_redirection to find and format
25
+ # the redirect location. normalize_argument_to_redirection is private
26
+ # in ActionDispatch::Assertions::ResponseAssertions so we call it
27
+ # here using #send. This will keep the error message format consistent
28
+ # @api private
29
+ def check_redirect
30
+ response = @scope.response
31
+ return unless response.respond_to?(:redirect?) && response.redirect?
32
+
33
+ @redirect_is = @scope.send(:normalize_argument_to_redirection, response.location)
34
+ end
35
+
36
+ # @api private
37
+ def failure_message
38
+ if @redirect_is
39
+ rescued_exception.message[/(.*?)( but|$)/, 1] +
40
+ " but was a redirect to <#{@redirect_is}>"
41
+ else
42
+ rescued_exception.message
43
+ end
44
+ end
45
+
46
+ # @api private
47
+ def failure_message_when_negated
48
+ "expected not to render #{expected.inspect}, but did"
49
+ end
50
+ end
51
+
52
+ # Delegates to `assert_template`.
53
+ #
54
+ # @example
55
+ # expect(response).to have_rendered("new")
56
+ def have_rendered(options, message = nil)
57
+ RenderTemplateMatcher.new(self, options, message)
58
+ end
59
+
60
+ alias_method :render_template, :have_rendered
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,38 @@
1
+ module RSpec
2
+ module Rails
3
+ module Matchers
4
+ # Matcher for redirects.
5
+ module RedirectTo
6
+ # @private
7
+ class RedirectTo < RSpec::Rails::Matchers::BaseMatcher
8
+ def initialize(scope, expected)
9
+ @expected = expected
10
+ @scope = scope
11
+ end
12
+
13
+ def matches?(_)
14
+ match_unless_raises ActiveSupport::TestCase::Assertion do
15
+ @scope.assert_redirected_to(@expected)
16
+ end
17
+ end
18
+
19
+ def failure_message
20
+ rescued_exception.message
21
+ end
22
+
23
+ def failure_message_when_negated
24
+ "expected not to redirect to #{@expected.inspect}, but did"
25
+ end
26
+ end
27
+
28
+ # Delegates to `assert_redirected_to`.
29
+ #
30
+ # @example
31
+ # expect(response).to redirect_to(:action => "new")
32
+ def redirect_to(target)
33
+ RedirectTo.new(self, target)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ if defined?(ActiveRecord::Relation) && defined?(RSpec::Matchers::BuiltIn::OperatorMatcher) # RSpec 4 removed OperatorMatcher
2
+ RSpec::Matchers::BuiltIn::OperatorMatcher.register(ActiveRecord::Relation, '=~', RSpec::Matchers::BuiltIn::ContainExactly)
3
+ end
@@ -0,0 +1,125 @@
1
+ module RSpec
2
+ module Rails
3
+ module Matchers
4
+ # Matchers to help with specs for routing code.
5
+ module RoutingMatchers
6
+ extend RSpec::Matchers::DSL
7
+
8
+ # @private
9
+ class RouteToMatcher < RSpec::Rails::Matchers::BaseMatcher
10
+ def initialize(scope, *expected)
11
+ @scope = scope
12
+ @expected = expected[1] || {}
13
+ if Hash === expected[0]
14
+ @expected.merge!(expected[0])
15
+ else
16
+ controller, action = expected[0].split('#')
17
+ @expected.merge!(controller: controller, action: action)
18
+ end
19
+ end
20
+
21
+ def matches?(verb_to_path_map)
22
+ @actual = verb_to_path_map
23
+ # assert_recognizes does not consider ActionController::RoutingError an
24
+ # assertion failure, so we have to capture that and Assertion here.
25
+ match_unless_raises ActiveSupport::TestCase::Assertion, ActionController::RoutingError do
26
+ path, query = *verb_to_path_map.values.first.split('?')
27
+ @scope.assert_recognizes(
28
+ @expected,
29
+ { method: verb_to_path_map.keys.first, path: path },
30
+ Rack::Utils.parse_nested_query(query)
31
+ )
32
+ end
33
+ end
34
+
35
+ def failure_message
36
+ rescued_exception.message
37
+ end
38
+
39
+ def failure_message_when_negated
40
+ "expected #{@actual.inspect} not to route to #{@expected.inspect}"
41
+ end
42
+
43
+ def description
44
+ "route #{@actual.inspect} to #{@expected.inspect}"
45
+ end
46
+ end
47
+
48
+ # Delegates to `assert_recognizes`. Supports short-hand controller/action
49
+ # declarations (e.g. `"controller#action"`).
50
+ #
51
+ # @example
52
+ #
53
+ # expect(get: "/things/special").to route_to(
54
+ # controller: "things",
55
+ # action: "special"
56
+ # )
57
+ #
58
+ # expect(get: "/things/special").to route_to("things#special")
59
+ #
60
+ # @see https://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_recognizes
61
+ def route_to(*expected)
62
+ RouteToMatcher.new(self, *expected)
63
+ end
64
+
65
+ # @private
66
+ class BeRoutableMatcher < RSpec::Rails::Matchers::BaseMatcher
67
+ def initialize(scope)
68
+ @scope = scope
69
+ end
70
+
71
+ def matches?(path)
72
+ @actual = path
73
+ match_unless_raises ActionController::RoutingError do
74
+ @routing_options = @scope.routes.recognize_path(
75
+ path.values.first, method: path.keys.first
76
+ )
77
+ end
78
+ end
79
+
80
+ def failure_message
81
+ "expected #{@actual.inspect} to be routable"
82
+ end
83
+
84
+ def failure_message_when_negated
85
+ "expected #{@actual.inspect} not to be routable, but it routes to #{@routing_options.inspect}"
86
+ end
87
+
88
+ def description
89
+ "be routable"
90
+ end
91
+ end
92
+
93
+ # Passes if the route expression is recognized by the Rails router based on
94
+ # the declarations in `config/routes.rb`. Delegates to
95
+ # `RouteSet#recognize_path`.
96
+ #
97
+ # @example You can use route helpers provided by rspec-rails.
98
+ # expect(get: "/a/path").to be_routable
99
+ # expect(post: "/another/path").to be_routable
100
+ # expect(put: "/yet/another/path").to be_routable
101
+ def be_routable
102
+ BeRoutableMatcher.new(self)
103
+ end
104
+
105
+ # Helpers for matching different route types.
106
+ module RouteHelpers
107
+ # @!method get
108
+ # @!method post
109
+ # @!method put
110
+ # @!method patch
111
+ # @!method delete
112
+ # @!method options
113
+ # @!method head
114
+ #
115
+ # Shorthand method for matching this type of route.
116
+ %w[get post put patch delete options head].each do |method|
117
+ define_method method do |path|
118
+ { method.to_sym => path }
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end