rspec-rails 3.8.2 → 5.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Capybara.md +5 -54
  4. data/Changelog.md +284 -74
  5. data/README.md +278 -500
  6. data/lib/generators/rspec/channel/channel_generator.rb +12 -0
  7. data/lib/generators/rspec/{observer/templates/observer_spec.rb → channel/templates/channel_spec.rb.erb} +1 -1
  8. data/lib/generators/rspec/controller/controller_generator.rb +22 -5
  9. data/lib/generators/rspec/controller/templates/request_spec.rb +19 -0
  10. data/lib/generators/rspec/controller/templates/routing_spec.rb +13 -0
  11. data/lib/generators/rspec/feature/feature_generator.rb +2 -2
  12. data/lib/generators/rspec/generator/generator_generator.rb +24 -0
  13. data/lib/generators/rspec/generator/templates/generator_spec.rb +6 -0
  14. data/lib/generators/rspec/helper/helper_generator.rb +1 -1
  15. data/lib/generators/rspec/install/install_generator.rb +4 -4
  16. data/lib/generators/rspec/install/templates/spec/rails_helper.rb +18 -13
  17. data/lib/generators/rspec/integration/integration_generator.rb +3 -3
  18. data/lib/generators/rspec/job/job_generator.rb +2 -1
  19. data/lib/generators/rspec/job/templates/job_spec.rb.erb +1 -1
  20. data/lib/generators/rspec/mailbox/mailbox_generator.rb +14 -0
  21. data/lib/generators/rspec/mailbox/templates/mailbox_spec.rb.erb +7 -0
  22. data/lib/generators/rspec/mailer/mailer_generator.rb +2 -1
  23. data/lib/generators/rspec/mailer/templates/mailer_spec.rb +2 -2
  24. data/lib/generators/rspec/mailer/templates/preview.rb +1 -1
  25. data/lib/generators/rspec/model/model_generator.rb +6 -5
  26. data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
  27. data/lib/generators/rspec/request/request_generator.rb +1 -1
  28. data/lib/generators/rspec/scaffold/scaffold_generator.rb +33 -19
  29. data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +13 -49
  30. data/lib/generators/rspec/scaffold/templates/api_request_spec.rb +131 -0
  31. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +10 -58
  32. data/lib/generators/rspec/scaffold/templates/edit_spec.rb +1 -5
  33. data/lib/generators/rspec/scaffold/templates/index_spec.rb +2 -2
  34. data/lib/generators/rspec/scaffold/templates/new_spec.rb +1 -5
  35. data/lib/generators/rspec/scaffold/templates/request_spec.rb +138 -0
  36. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +8 -10
  37. data/lib/generators/rspec/scaffold/templates/show_spec.rb +1 -1
  38. data/lib/generators/rspec/system/system_generator.rb +24 -0
  39. data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
  40. data/lib/generators/rspec/view/view_generator.rb +2 -2
  41. data/lib/generators/rspec.rb +0 -6
  42. data/lib/rspec/rails/adapters.rb +11 -76
  43. data/lib/rspec/rails/configuration.rb +82 -37
  44. data/lib/rspec/rails/example/channel_example_group.rb +93 -0
  45. data/lib/rspec/rails/example/controller_example_group.rb +5 -4
  46. data/lib/rspec/rails/example/feature_example_group.rb +6 -26
  47. data/lib/rspec/rails/example/helper_example_group.rb +2 -9
  48. data/lib/rspec/rails/example/mailbox_example_group.rb +80 -0
  49. data/lib/rspec/rails/example/mailer_example_group.rb +2 -2
  50. data/lib/rspec/rails/example/rails_example_group.rb +1 -1
  51. data/lib/rspec/rails/example/request_example_group.rb +1 -4
  52. data/lib/rspec/rails/example/system_example_group.rb +29 -12
  53. data/lib/rspec/rails/example/view_example_group.rb +38 -27
  54. data/lib/rspec/rails/example.rb +2 -0
  55. data/lib/rspec/rails/extensions/active_record/proxy.rb +5 -10
  56. data/lib/rspec/rails/feature_check.rb +12 -29
  57. data/lib/rspec/rails/file_fixture_support.rb +9 -11
  58. data/lib/rspec/rails/fixture_file_upload_support.rb +33 -17
  59. data/lib/rspec/rails/fixture_support.rb +35 -32
  60. data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +170 -0
  61. data/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
  62. data/lib/rspec/rails/matchers/action_cable.rb +65 -0
  63. data/lib/rspec/rails/matchers/action_mailbox.rb +73 -0
  64. data/lib/rspec/rails/matchers/active_job.rb +170 -22
  65. data/lib/rspec/rails/matchers/base_matcher.rb +179 -0
  66. data/lib/rspec/rails/matchers/be_a_new.rb +1 -1
  67. data/lib/rspec/rails/matchers/be_new_record.rb +1 -1
  68. data/lib/rspec/rails/matchers/be_valid.rb +1 -1
  69. data/lib/rspec/rails/matchers/have_enqueued_mail.rb +226 -0
  70. data/lib/rspec/rails/matchers/have_http_status.rb +20 -25
  71. data/lib/rspec/rails/matchers/have_rendered.rb +2 -1
  72. data/lib/rspec/rails/matchers/redirect_to.rb +1 -1
  73. data/lib/rspec/rails/matchers/relation_match_array.rb +1 -1
  74. data/lib/rspec/rails/matchers/routing_matchers.rb +14 -14
  75. data/lib/rspec/rails/matchers.rb +11 -0
  76. data/lib/rspec/rails/tasks/rspec.rake +7 -17
  77. data/lib/rspec/rails/vendor/capybara.rb +10 -15
  78. data/lib/rspec/rails/version.rb +1 -1
  79. data/lib/rspec/rails/view_path_builder.rb +1 -1
  80. data/lib/rspec/rails/view_rendering.rb +15 -4
  81. data/lib/rspec-rails.rb +13 -16
  82. data.tar.gz.sig +0 -0
  83. metadata +64 -34
  84. metadata.gz.sig +0 -0
  85. data/lib/generators/rspec/observer/observer_generator.rb +0 -13
@@ -15,7 +15,7 @@ module RSpec
15
15
  def failure_message
16
16
  message = "expected #{actual.inspect} to be valid"
17
17
 
18
- if actual.respond_to?(:errors)
18
+ if actual.respond_to?(:errors) && actual.method(:errors).arity < 1
19
19
  errors = if actual.errors.respond_to?(:full_messages)
20
20
  actual.errors.full_messages
21
21
  else
@@ -0,0 +1,226 @@
1
+ # We require the minimum amount of rspec-mocks possible to avoid
2
+ # conflicts with other mocking frameworks.
3
+ # See: https://github.com/rspec/rspec-rails/issues/2252
4
+ require "rspec/mocks/argument_matchers"
5
+ require "rspec/rails/matchers/active_job"
6
+
7
+ # rubocop: disable Metrics/ClassLength
8
+ module RSpec
9
+ module Rails
10
+ module Matchers
11
+ # Matcher class for `have_enqueued_mail`. Should not be instantiated directly.
12
+ #
13
+ # @private
14
+ # @see RSpec::Rails::Matchers#have_enqueued_mail
15
+ class HaveEnqueuedMail < ActiveJob::HaveEnqueuedJob
16
+ MAILER_JOB_METHOD = 'deliver_now'.freeze
17
+
18
+ include RSpec::Mocks::ArgumentMatchers
19
+
20
+ def initialize(mailer_class, method_name)
21
+ super(nil)
22
+ @mailer_class = mailer_class
23
+ @method_name = method_name
24
+ @mail_args = []
25
+ end
26
+
27
+ def description
28
+ "enqueues #{mailer_class_name}.#{@method_name}"
29
+ end
30
+
31
+ def with(*args, &block)
32
+ @mail_args = args
33
+ block.nil? ? super : super(&yield_mail_args(block))
34
+ end
35
+
36
+ def matches?(block)
37
+ raise ArgumentError, 'have_enqueued_mail and enqueue_mail only work with block arguments' unless block.respond_to?(:call)
38
+
39
+ check_active_job_adapter
40
+ super
41
+ end
42
+
43
+ def failure_message
44
+ "expected to enqueue #{base_message}".tap do |msg|
45
+ msg << "\n#{unmatching_mail_jobs_message}" if unmatching_mail_jobs.any?
46
+ end
47
+ end
48
+
49
+ def failure_message_when_negated
50
+ "expected not to enqueue #{base_message}"
51
+ end
52
+
53
+ private
54
+
55
+ def base_message
56
+ [mailer_class_name, @method_name].compact.join('.').tap do |msg|
57
+ msg << " #{expected_count_message}"
58
+ msg << " with #{@mail_args}," if @mail_args.any?
59
+ msg << " on queue #{@queue}," if @queue
60
+ msg << " at #{@at.inspect}," if @at
61
+ msg << " but enqueued #{@matching_jobs.size}"
62
+ end
63
+ end
64
+
65
+ def expected_count_message
66
+ "#{message_expectation_modifier} #{@expected_number} #{@expected_number == 1 ? 'time' : 'times'}"
67
+ end
68
+
69
+ def mailer_class_name
70
+ @mailer_class ? @mailer_class.name : 'ActionMailer::Base'
71
+ end
72
+
73
+ def job_match?(job)
74
+ legacy_mail?(job) || parameterized_mail?(job) || unified_mail?(job)
75
+ end
76
+
77
+ def arguments_match?(job)
78
+ @args =
79
+ if @mail_args.any?
80
+ base_mailer_args + @mail_args
81
+ elsif @mailer_class && @method_name
82
+ base_mailer_args + [any_args]
83
+ elsif @mailer_class
84
+ [mailer_class_name, any_args]
85
+ else
86
+ []
87
+ end
88
+
89
+ super(job)
90
+ end
91
+
92
+ def base_mailer_args
93
+ [mailer_class_name, @method_name.to_s, MAILER_JOB_METHOD]
94
+ end
95
+
96
+ def yield_mail_args(block)
97
+ proc { |*job_args| block.call(*(job_args - base_mailer_args)) }
98
+ end
99
+
100
+ def check_active_job_adapter
101
+ return if ::ActiveJob::QueueAdapters::TestAdapter === ::ActiveJob::Base.queue_adapter
102
+
103
+ raise StandardError, "To use HaveEnqueuedMail matcher set `ActiveJob::Base.queue_adapter = :test`"
104
+ end
105
+
106
+ def unmatching_mail_jobs
107
+ @unmatching_jobs.select do |job|
108
+ job_match?(job)
109
+ end
110
+ end
111
+
112
+ def unmatching_mail_jobs_message
113
+ msg = "Queued deliveries:"
114
+
115
+ unmatching_mail_jobs.each do |job|
116
+ msg << "\n #{mail_job_message(job)}"
117
+ end
118
+
119
+ msg
120
+ end
121
+
122
+ def mail_job_message(job)
123
+ job_args = deserialize_arguments(job)
124
+
125
+ mailer_method = job_args[0..1].join('.')
126
+ mailer_args = job_args[3..-1]
127
+
128
+ msg_parts = []
129
+ msg_parts << "with #{mailer_args}" if mailer_args.any?
130
+ msg_parts << "on queue #{job[:queue]}" if job[:queue] && job[:queue] != 'mailers'
131
+ msg_parts << "at #{Time.at(job[:at])}" if job[:at]
132
+
133
+ "#{mailer_method} #{msg_parts.join(', ')}".strip
134
+ end
135
+
136
+ # Ruby 3.1 changed how params were serialized on Rails 6.1
137
+ # so we override the active job implementation and customise it here.
138
+ def deserialize_arguments(job)
139
+ args = super
140
+
141
+ return args unless Hash === args.last
142
+
143
+ hash = args.pop
144
+
145
+ if hash.key?("_aj_ruby2_keywords")
146
+ keywords = hash["_aj_ruby2_keywords"]
147
+
148
+ original_hash = keywords.each_with_object({}) { |keyword, new_hash| new_hash[keyword.to_sym] = hash[keyword] }
149
+
150
+ args + [original_hash]
151
+ elsif hash.key?(:args) && hash.key?(:params)
152
+ args + [hash]
153
+ elsif hash.key?(:args)
154
+ args + hash[:args]
155
+ else
156
+ args + [hash]
157
+ end
158
+ end
159
+
160
+ def legacy_mail?(job)
161
+ job[:job] <= ActionMailer::DeliveryJob
162
+ end
163
+
164
+ def parameterized_mail?(job)
165
+ RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? && job[:job] <= ActionMailer::Parameterized::DeliveryJob
166
+ end
167
+
168
+ def unified_mail?(job)
169
+ RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? && job[:job] <= ActionMailer::MailDeliveryJob
170
+ end
171
+ end
172
+ # @api public
173
+ # Passes if an email has been enqueued inside block.
174
+ # May chain with to specify expected arguments.
175
+ # May chain at_least, at_most or exactly to specify a number of times.
176
+ # May chain at to specify a send time.
177
+ # May chain on_queue to specify a queue.
178
+ #
179
+ # @example
180
+ # expect {
181
+ # MyMailer.welcome(user).deliver_later
182
+ # }.to have_enqueued_mail
183
+ #
184
+ # expect {
185
+ # MyMailer.welcome(user).deliver_later
186
+ # }.to have_enqueued_mail(MyMailer)
187
+ #
188
+ # expect {
189
+ # MyMailer.welcome(user).deliver_later
190
+ # }.to have_enqueued_mail(MyMailer, :welcome)
191
+ #
192
+ # # Using alias
193
+ # expect {
194
+ # MyMailer.welcome(user).deliver_later
195
+ # }.to enqueue_mail(MyMailer, :welcome)
196
+ #
197
+ # expect {
198
+ # MyMailer.welcome(user).deliver_later
199
+ # }.to have_enqueued_mail(MyMailer, :welcome).with(user)
200
+ #
201
+ # expect {
202
+ # MyMailer.welcome(user).deliver_later
203
+ # MyMailer.welcome(user).deliver_later
204
+ # }.to have_enqueued_mail(MyMailer, :welcome).at_least(:once)
205
+ #
206
+ # expect {
207
+ # MyMailer.welcome(user).deliver_later
208
+ # }.to have_enqueued_mail(MyMailer, :welcome).at_most(:twice)
209
+ #
210
+ # expect {
211
+ # MyMailer.welcome(user).deliver_later(wait_until: Date.tomorrow.noon)
212
+ # }.to have_enqueued_mail(MyMailer, :welcome).at(Date.tomorrow.noon)
213
+ #
214
+ # expect {
215
+ # MyMailer.welcome(user).deliver_later(queue: :urgent_mail)
216
+ # }.to have_enqueued_mail(MyMailer, :welcome).on_queue(:urgent_mail)
217
+ def have_enqueued_mail(mailer_class = nil, mail_method_name = nil)
218
+ HaveEnqueuedMail.new(mailer_class, mail_method_name)
219
+ end
220
+ alias_method :have_enqueued_email, :have_enqueued_mail
221
+ alias_method :enqueue_mail, :have_enqueued_mail
222
+ alias_method :enqueue_email, :have_enqueued_mail
223
+ end
224
+ end
225
+ end
226
+ # rubocop: enable Metrics/ClassLength
@@ -1,6 +1,6 @@
1
1
  # The following code inspired and modified from Rails' `assert_response`:
2
2
  #
3
- # https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/assertions/response.rb#L22-L38
3
+ # https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/testing/assertions/response.rb#L22-L38
4
4
  #
5
5
  # Thank you to all the Rails devs who did the heavy lifting on this!
6
6
 
@@ -59,6 +59,7 @@ module RSpec
59
59
  # `@invalid_response` is present, `nil` otherwise
60
60
  def invalid_response_type_message
61
61
  return unless @invalid_response
62
+
62
63
  "expected a response object, but an instance of " \
63
64
  "#{@invalid_response.class} was received"
64
65
  end
@@ -72,8 +73,8 @@ module RSpec
72
73
  # @example
73
74
  # expect(response).to have_http_status(404)
74
75
  #
75
- # @see RSpec::Rails::Matchers.have_http_status
76
- class NumericCode < RSpec::Matchers::BuiltIn::BaseMatcher
76
+ # @see RSpec::Rails::Matchers#have_http_status
77
+ class NumericCode < RSpec::Rails::Matchers::BaseMatcher
77
78
  include HaveHttpStatus
78
79
 
79
80
  def initialize(code)
@@ -122,9 +123,9 @@ module RSpec
122
123
  # @example
123
124
  # expect(response).to have_http_status(:created)
124
125
  #
125
- # @see RSpec::Rails::Matchers.have_http_status
126
+ # @see RSpec::Rails::Matchers#have_http_status
126
127
  # @see https://github.com/rack/rack/blob/master/lib/rack/utils.rb `Rack::Utils::SYMBOL_TO_STATUS_CODE`
127
- class SymbolicStatus < RSpec::Matchers::BuiltIn::BaseMatcher
128
+ class SymbolicStatus < RSpec::Rails::Matchers::BaseMatcher
128
129
  include HaveHttpStatus
129
130
 
130
131
  def initialize(status)
@@ -174,6 +175,7 @@ module RSpec
174
175
  # @return [Symbol] representing the actual http numeric code
175
176
  def actual_status
176
177
  return unless actual
178
+
177
179
  @actual_status ||= compute_status_from(actual)
178
180
  end
179
181
 
@@ -234,14 +236,14 @@ module RSpec
234
236
  # expect(response).to have_http_status(:missing)
235
237
  # expect(response).to have_http_status(:redirect)
236
238
  #
237
- # @see RSpec::Rails::Matchers.have_http_status
238
- # @see ActionDispatch::TestResponse
239
- class GenericStatus < RSpec::Matchers::BuiltIn::BaseMatcher
239
+ # @see RSpec::Rails::Matchers#have_http_status
240
+ # @see https://github.com/rails/rails/blob/6-0-stable/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
241
+ class GenericStatus < RSpec::Rails::Matchers::BaseMatcher
240
242
  include HaveHttpStatus
241
243
 
242
244
  # @return [Array<Symbol>] of status codes which represent a HTTP status
243
245
  # code "group"
244
- # @see https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
246
+ # @see https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
245
247
  def self.valid_statuses
246
248
  [
247
249
  :error, :success, :missing,
@@ -254,6 +256,7 @@ module RSpec
254
256
  unless self.class.valid_statuses.include?(type)
255
257
  raise ArgumentError, "Invalid generic HTTP status: #{type.inspect}"
256
258
  end
259
+
257
260
  @expected = type
258
261
  @actual = nil
259
262
  @invalid_response = nil
@@ -289,20 +292,11 @@ module RSpec
289
292
 
290
293
  protected
291
294
 
292
- if 5 < ::Rails::VERSION::MAJOR ||
293
- (::Rails::VERSION::MAJOR == 5 && 2 <= ::Rails::VERSION::MINOR)
294
- RESPONSE_METHODS = {
295
- :success => 'successful',
296
- :error => 'server_error',
297
- :missing => 'not_found'
298
- }.freeze
299
- else
300
- RESPONSE_METHODS = {
301
- :successful => 'success',
302
- :server_error => 'error',
303
- :not_found => 'missing'
304
- }.freeze
305
- end
295
+ RESPONSE_METHODS = {
296
+ success: 'successful',
297
+ error: 'server_error',
298
+ missing: 'not_found'
299
+ }.freeze
306
300
 
307
301
  def check_expected_status(test_response, expected)
308
302
  test_response.send(
@@ -319,7 +313,7 @@ module RSpec
319
313
 
320
314
  # @return [String] formatting the associated code(s) for the various
321
315
  # status code "groups"
322
- # @see https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
316
+ # @see https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
323
317
  # @see https://github.com/rack/rack/blob/master/lib/rack/response.rb `Rack::Response`
324
318
  def type_codes
325
319
  # At the time of this commit the most recent version of
@@ -379,10 +373,11 @@ module RSpec
379
373
  # expect(response).to have_http_status(404)
380
374
  # expect(page).to have_http_status(:created)
381
375
  #
382
- # @see https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
376
+ # @see https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/testing/test_response.rb `ActionDispatch::TestResponse`
383
377
  # @see https://github.com/rack/rack/blob/master/lib/rack/utils.rb `Rack::Utils::SYMBOL_TO_STATUS_CODE`
384
378
  def have_http_status(target)
385
379
  raise ArgumentError, "Invalid HTTP status: nil" unless target
380
+
386
381
  HaveHttpStatus.matcher_for_status(target)
387
382
  end
388
383
  end
@@ -4,7 +4,7 @@ module RSpec
4
4
  # Matcher for template rendering.
5
5
  module RenderTemplate
6
6
  # @private
7
- class RenderTemplateMatcher < RSpec::Matchers::BuiltIn::BaseMatcher
7
+ class RenderTemplateMatcher < RSpec::Rails::Matchers::BaseMatcher
8
8
  def initialize(scope, expected, message = nil)
9
9
  @expected = Symbol === expected ? expected.to_s : expected
10
10
  @message = message
@@ -29,6 +29,7 @@ module RSpec
29
29
  def check_redirect
30
30
  response = @scope.response
31
31
  return unless response.respond_to?(:redirect?) && response.redirect?
32
+
32
33
  @redirect_is = @scope.send(:normalize_argument_to_redirection, response.location)
33
34
  end
34
35
 
@@ -4,7 +4,7 @@ module RSpec
4
4
  # Matcher for redirects.
5
5
  module RedirectTo
6
6
  # @private
7
- class RedirectTo < RSpec::Matchers::BuiltIn::BaseMatcher
7
+ class RedirectTo < RSpec::Rails::Matchers::BaseMatcher
8
8
  def initialize(scope, expected)
9
9
  @expected = expected
10
10
  @scope = scope
@@ -1,3 +1,3 @@
1
- if defined?(ActiveRecord::Relation)
1
+ if defined?(ActiveRecord::Relation) && defined?(RSpec::Matchers::BuiltIn::OperatorMatcher) # RSpec 4 removed OperatorMatcher
2
2
  RSpec::Matchers::BuiltIn::OperatorMatcher.register(ActiveRecord::Relation, '=~', RSpec::Matchers::BuiltIn::ContainExactly)
3
3
  end
@@ -6,7 +6,7 @@ module RSpec
6
6
  extend RSpec::Matchers::DSL
7
7
 
8
8
  # @private
9
- class RouteToMatcher < RSpec::Matchers::BuiltIn::BaseMatcher
9
+ class RouteToMatcher < RSpec::Rails::Matchers::BaseMatcher
10
10
  def initialize(scope, *expected)
11
11
  @scope = scope
12
12
  @expected = expected[1] || {}
@@ -14,7 +14,7 @@ module RSpec
14
14
  @expected.merge!(expected[0])
15
15
  else
16
16
  controller, action = expected[0].split('#')
17
- @expected.merge!(:controller => controller, :action => action)
17
+ @expected.merge!(controller: controller, action: action)
18
18
  end
19
19
  end
20
20
 
@@ -26,7 +26,7 @@ module RSpec
26
26
  path, query = *verb_to_path_map.values.first.split('?')
27
27
  @scope.assert_recognizes(
28
28
  @expected,
29
- { :method => verb_to_path_map.keys.first, :path => path },
29
+ {method: verb_to_path_map.keys.first, path: path},
30
30
  Rack::Utils.parse_nested_query(query)
31
31
  )
32
32
  end
@@ -50,20 +50,20 @@ module RSpec
50
50
  #
51
51
  # @example
52
52
  #
53
- # expect(:get => "/things/special").to route_to(
54
- # :controller => "things",
55
- # :action => "special"
53
+ # expect(get: "/things/special").to route_to(
54
+ # controller: "things",
55
+ # action: "special"
56
56
  # )
57
57
  #
58
- # expect(:get => "/things/special").to route_to("things#special")
58
+ # expect(get: "/things/special").to route_to("things#special")
59
59
  #
60
- # @see http://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_recognizes
60
+ # @see https://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_recognizes
61
61
  def route_to(*expected)
62
62
  RouteToMatcher.new(self, *expected)
63
63
  end
64
64
 
65
65
  # @private
66
- class BeRoutableMatcher < RSpec::Matchers::BuiltIn::BaseMatcher
66
+ class BeRoutableMatcher < RSpec::Rails::Matchers::BaseMatcher
67
67
  def initialize(scope)
68
68
  @scope = scope
69
69
  end
@@ -72,7 +72,7 @@ module RSpec
72
72
  @actual = path
73
73
  match_unless_raises ActionController::RoutingError do
74
74
  @routing_options = @scope.routes.recognize_path(
75
- path.values.first, :method => path.keys.first
75
+ path.values.first, method: path.keys.first
76
76
  )
77
77
  end
78
78
  end
@@ -95,9 +95,9 @@ module RSpec
95
95
  # `RouteSet#recognize_path`.
96
96
  #
97
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
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
101
  def be_routable
102
102
  BeRoutableMatcher.new(self)
103
103
  end
@@ -115,7 +115,7 @@ module RSpec
115
115
  # Shorthand method for matching this type of route.
116
116
  %w[get post put patch delete options head].each do |method|
117
117
  define_method method do |path|
118
- { method.to_sym => path }
118
+ {method.to_sym => path}
119
119
  end
120
120
  end
121
121
  end
@@ -11,6 +11,7 @@ module RSpec
11
11
  end
12
12
  end
13
13
 
14
+ require 'rspec/rails/matchers/base_matcher'
14
15
  require 'rspec/rails/matchers/have_rendered'
15
16
  require 'rspec/rails/matchers/redirect_to'
16
17
  require 'rspec/rails/matchers/routing_matchers'
@@ -19,6 +20,16 @@ require 'rspec/rails/matchers/be_a_new'
19
20
  require 'rspec/rails/matchers/relation_match_array'
20
21
  require 'rspec/rails/matchers/be_valid'
21
22
  require 'rspec/rails/matchers/have_http_status'
23
+
22
24
  if RSpec::Rails::FeatureCheck.has_active_job?
23
25
  require 'rspec/rails/matchers/active_job'
26
+ require 'rspec/rails/matchers/have_enqueued_mail'
27
+ end
28
+
29
+ if RSpec::Rails::FeatureCheck.has_action_cable_testing?
30
+ require 'rspec/rails/matchers/action_cable'
31
+ end
32
+
33
+ if RSpec::Rails::FeatureCheck.has_action_mailbox?
34
+ require 'rspec/rails/matchers/action_mailbox'
24
35
  end
@@ -3,19 +3,19 @@ if default = Rake.application.instance_variable_get('@tasks')['default']
3
3
  default.prerequisites.delete('test')
4
4
  end
5
5
 
6
- task :default => :spec
6
+ task default: :spec
7
7
 
8
- task :stats => "spec:statsetup"
8
+ task stats: "spec:statsetup"
9
9
 
10
10
  desc "Run all specs in spec directory (excluding plugin specs)"
11
- RSpec::Core::RakeTask.new(:spec => "spec:prepare")
11
+ RSpec::Core::RakeTask.new(spec: "spec:prepare")
12
12
 
13
13
  namespace :spec do
14
14
  types = begin
15
- dirs = Dir['./spec/**/*_spec.rb'].
16
- map { |f| f.sub(/^\.\/(spec\/\w+)\/.*/, '\\1') }.
17
- uniq.
18
- select { |f| File.directory?(f) }
15
+ dirs = Dir['./spec/**/*_spec.rb']
16
+ .map { |f| f.sub(/^\.\/(spec\/\w+)\/.*/, '\\1') }
17
+ .uniq
18
+ .select { |f| File.directory?(f) }
19
19
  Hash[dirs.map { |d| [d.split('/').last, d] }]
20
20
  end
21
21
 
@@ -35,16 +35,6 @@ namespace :spec do
35
35
  end
36
36
  end
37
37
 
38
- # RCov task only enabled for Ruby 1.8
39
- if RUBY_VERSION < '1.9'
40
- desc "Run all specs with rcov"
41
- RSpec::Core::RakeTask.new(:rcov => "spec:prepare") do |t|
42
- t.rcov = true
43
- t.pattern = "./spec/**/*_spec.rb"
44
- t.rcov_opts = '--exclude /gems/,/Library/,/usr/,lib/tasks,.bundle,config,/lib/rspec/,/lib/rspec-,spec'
45
- end
46
- end
47
-
48
38
  task :statsetup do
49
39
  require 'rails/code_statistics'
50
40
  types.each do |type, dir|
@@ -9,31 +9,26 @@ rescue LoadError
9
9
  end
10
10
 
11
11
  if defined?(Capybara)
12
- require 'rspec/support/comparable_version'
13
- unless RSpec::Support::ComparableVersion.new(Capybara::VERSION) >= '2.2.0'
14
- raise "You are using capybara #{Capybara::VERSION}. RSpec requires >= 2.2.0."
15
- end
16
-
17
12
  RSpec.configure do |c|
18
13
  if defined?(Capybara::DSL)
19
- c.include Capybara::DSL, :type => :feature
14
+ c.include Capybara::DSL, type: :feature
20
15
  if defined?(ActionPack) && ActionPack::VERSION::STRING >= "5.1"
21
- c.include Capybara::DSL, :type => :system
16
+ c.include Capybara::DSL, type: :system
22
17
  end
23
18
  end
24
19
 
25
20
  if defined?(Capybara::RSpecMatchers)
26
- c.include Capybara::RSpecMatchers, :type => :view
27
- c.include Capybara::RSpecMatchers, :type => :helper
28
- c.include Capybara::RSpecMatchers, :type => :mailer
29
- c.include Capybara::RSpecMatchers, :type => :controller
30
- c.include Capybara::RSpecMatchers, :type => :feature
31
- c.include Capybara::RSpecMatchers, :type => :system
21
+ c.include Capybara::RSpecMatchers, type: :view
22
+ c.include Capybara::RSpecMatchers, type: :helper
23
+ c.include Capybara::RSpecMatchers, type: :mailer
24
+ c.include Capybara::RSpecMatchers, type: :controller
25
+ c.include Capybara::RSpecMatchers, type: :feature
26
+ c.include Capybara::RSpecMatchers, type: :system
32
27
  end
33
28
 
34
29
  unless defined?(Capybara::RSpecMatchers) || defined?(Capybara::DSL)
35
- c.include Capybara, :type => :request
36
- c.include Capybara, :type => :controller
30
+ c.include Capybara, type: :request
31
+ c.include Capybara, type: :controller
37
32
  end
38
33
  end
39
34
  end
@@ -3,7 +3,7 @@ module RSpec
3
3
  # Version information for RSpec Rails.
4
4
  module Version
5
5
  # Current version of RSpec Rails, in semantic versioning format.
6
- STRING = '3.8.2'
6
+ STRING = '5.1.2'
7
7
  end
8
8
  end
9
9
  end
@@ -20,7 +20,7 @@ module RSpec
20
20
  # view_path_builder.path_for({ :controller => 'posts', :action => 'delete' })
21
21
  # # => ActionController::UrlGenerationError: No route matches {:action=>"delete", :controller=>"posts"}
22
22
  def path_for(path_params)
23
- url_for(path_params.merge(:only_path => true))
23
+ url_for(path_params.merge(only_path: true))
24
24
  rescue => e
25
25
  e.message
26
26
  end
@@ -55,12 +55,23 @@ module RSpec
55
55
  "",
56
56
  template.identifier,
57
57
  EmptyTemplateHandler,
58
- :virtual_path => template.virtual_path,
59
- :format => template.formats
58
+ virtual_path: template.virtual_path,
59
+ format: template_format(template),
60
+ locals: []
60
61
  )
61
62
  end
62
63
  end
63
64
 
65
+ if ::Rails::VERSION::STRING >= '6'
66
+ def self.template_format(template)
67
+ template.format
68
+ end
69
+ else
70
+ def self.template_format(template)
71
+ template.formats
72
+ end
73
+ end
74
+
64
75
  # Delegates all methods to the submitted resolver and for all methods
65
76
  # that return a collection of `ActionView::Template` instances, return
66
77
  # templates with modified source
@@ -91,7 +102,7 @@ module RSpec
91
102
  #
92
103
  # @private
93
104
  class FileSystemResolver < ::ActionView::FileSystemResolver
94
- private
105
+ private
95
106
 
96
107
  def find_templates(*args)
97
108
  templates = super
@@ -102,7 +113,7 @@ module RSpec
102
113
 
103
114
  # @private
104
115
  class EmptyTemplateHandler
105
- def self.call(_template)
116
+ def self.call(_template, _source = nil)
106
117
  ::Rails.logger.info(" Template rendering was prevented by rspec-rails. Use `render_views` to verify rendered view contents if necessary.")
107
118
 
108
119
  %("")