rspec-rails 3.9.1 → 4.0.0

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 (73) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Capybara.md +5 -54
  4. data/Changelog.md +167 -80
  5. data/README.md +4 -5
  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 +21 -4
  9. data/lib/generators/rspec/controller/templates/request_spec.rb +14 -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/{generators → generator}/generator_generator.rb +2 -2
  13. data/lib/generators/rspec/{generators → generator}/templates/generator_spec.rb +0 -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 +17 -16
  17. data/lib/generators/rspec/integration/integration_generator.rb +3 -3
  18. data/lib/generators/rspec/mailbox/mailbox_generator.rb +14 -0
  19. data/lib/generators/rspec/mailbox/templates/mailbox_spec.rb.erb +7 -0
  20. data/lib/generators/rspec/mailer/mailer_generator.rb +2 -1
  21. data/lib/generators/rspec/model/model_generator.rb +5 -4
  22. data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
  23. data/lib/generators/rspec/request/request_generator.rb +1 -1
  24. data/lib/generators/rspec/scaffold/scaffold_generator.rb +29 -19
  25. data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +0 -36
  26. data/lib/generators/rspec/scaffold/templates/api_request_spec.rb +131 -0
  27. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +10 -10
  28. data/lib/generators/rspec/scaffold/templates/edit_spec.rb +1 -1
  29. data/lib/generators/rspec/scaffold/templates/index_spec.rb +2 -2
  30. data/lib/generators/rspec/scaffold/templates/new_spec.rb +1 -1
  31. data/lib/generators/rspec/scaffold/templates/request_spec.rb +133 -0
  32. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +8 -10
  33. data/lib/generators/rspec/scaffold/templates/show_spec.rb +1 -1
  34. data/lib/generators/rspec/system/system_generator.rb +1 -1
  35. data/lib/generators/rspec/view/view_generator.rb +2 -2
  36. data/lib/generators/rspec.rb +0 -6
  37. data/lib/rspec/rails/adapters.rb +11 -76
  38. data/lib/rspec/rails/configuration.rb +43 -33
  39. data/lib/rspec/rails/example/channel_example_group.rb +93 -0
  40. data/lib/rspec/rails/example/controller_example_group.rb +4 -4
  41. data/lib/rspec/rails/example/feature_example_group.rb +6 -26
  42. data/lib/rspec/rails/example/helper_example_group.rb +2 -9
  43. data/lib/rspec/rails/example/mailbox_example_group.rb +80 -0
  44. data/lib/rspec/rails/example/mailer_example_group.rb +1 -1
  45. data/lib/rspec/rails/example/rails_example_group.rb +1 -1
  46. data/lib/rspec/rails/example/system_example_group.rb +24 -8
  47. data/lib/rspec/rails/example/view_example_group.rb +38 -27
  48. data/lib/rspec/rails/example.rb +2 -0
  49. data/lib/rspec/rails/extensions/active_record/proxy.rb +1 -9
  50. data/lib/rspec/rails/feature_check.rb +12 -29
  51. data/lib/rspec/rails/fixture_file_upload_support.rb +1 -1
  52. data/lib/rspec/rails/fixture_support.rb +37 -31
  53. data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +170 -0
  54. data/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
  55. data/lib/rspec/rails/matchers/action_cable.rb +65 -0
  56. data/lib/rspec/rails/matchers/action_mailbox.rb +64 -0
  57. data/lib/rspec/rails/matchers/active_job.rb +142 -20
  58. data/lib/rspec/rails/matchers/base_matcher.rb +5 -10
  59. data/lib/rspec/rails/matchers/have_enqueued_mail.rb +52 -28
  60. data/lib/rspec/rails/matchers/have_http_status.rb +11 -7
  61. data/lib/rspec/rails/matchers/have_rendered.rb +1 -0
  62. data/lib/rspec/rails/matchers/routing_matchers.rb +12 -12
  63. data/lib/rspec/rails/matchers.rb +9 -0
  64. data/lib/rspec/rails/tasks/rspec.rake +7 -17
  65. data/lib/rspec/rails/vendor/capybara.rb +10 -15
  66. data/lib/rspec/rails/version.rb +1 -1
  67. data/lib/rspec/rails/view_path_builder.rb +1 -1
  68. data/lib/rspec/rails/view_rendering.rb +15 -4
  69. data/lib/rspec-rails.rb +8 -9
  70. data.tar.gz.sig +0 -0
  71. metadata +42 -30
  72. metadata.gz.sig +0 -0
  73. data/lib/generators/rspec/observer/observer_generator.rb +0 -13
@@ -8,14 +8,14 @@ module RSpec
8
8
  #
9
9
  # @api private
10
10
  module ActiveJob
11
- # rubocop: disable Style/ClassLength
11
+ # rubocop: disable Metrics/ClassLength
12
12
  # @private
13
13
  class Base < RSpec::Rails::Matchers::BaseMatcher
14
14
  def initialize
15
15
  @args = []
16
16
  @queue = nil
17
17
  @at = nil
18
- @block = Proc.new {}
18
+ @block = proc { }
19
19
  set_expected_number(:exactly, 1)
20
20
  end
21
21
 
@@ -26,7 +26,7 @@ module RSpec
26
26
  end
27
27
 
28
28
  def on_queue(queue)
29
- @queue = queue
29
+ @queue = queue.to_s
30
30
  self
31
31
  end
32
32
 
@@ -67,7 +67,7 @@ module RSpec
67
67
  end
68
68
 
69
69
  def failure_message
70
- "expected to enqueue #{base_message}".tap do |msg|
70
+ "expected to #{self.class::FAILURE_MESSAGE_EXPECTATION_ACTION} #{base_message}".tap do |msg|
71
71
  if @unmatching_jobs.any?
72
72
  msg << "\nQueued jobs:"
73
73
  @unmatching_jobs.each do |job|
@@ -78,7 +78,7 @@ module RSpec
78
78
  end
79
79
 
80
80
  def failure_message_when_negated
81
- "expected not to enqueue #{base_message}"
81
+ "expected not to #{self.class::FAILURE_MESSAGE_EXPECTATION_ACTION} #{base_message}"
82
82
  end
83
83
 
84
84
  def message_expectation_modifier
@@ -97,7 +97,7 @@ module RSpec
97
97
 
98
98
  def check(jobs)
99
99
  @matching_jobs, @unmatching_jobs = jobs.partition do |job|
100
- if arguments_match?(job) && other_attributes_match?(job)
100
+ if job_match?(job) && arguments_match?(job) && queue_match?(job) && at_match?(job)
101
101
  args = deserialize_arguments(job)
102
102
  @block.call(*args)
103
103
  true
@@ -119,7 +119,7 @@ module RSpec
119
119
  msg << " with #{@args}," if @args.any?
120
120
  msg << " on queue #{@queue}," if @queue
121
121
  msg << " at #{@at.inspect}," if @at
122
- msg << " but enqueued #{@matching_jobs_count}"
122
+ msg << " but #{self.class::MESSAGE_EXPECTATION_ACTION} #{@matching_jobs_count}"
123
123
  end
124
124
  end
125
125
 
@@ -134,29 +134,32 @@ module RSpec
134
134
  end
135
135
  end
136
136
 
137
+ def job_match?(job)
138
+ @job ? @job == job[:job] : true
139
+ end
140
+
137
141
  def arguments_match?(job)
138
142
  if @args.any?
143
+ args = serialize_and_deserialize_arguments(@args)
139
144
  deserialized_args = deserialize_arguments(job)
140
- RSpec::Mocks::ArgumentListMatcher.new(*@args).args_match?(*deserialized_args)
145
+ RSpec::Mocks::ArgumentListMatcher.new(*args).args_match?(*deserialized_args)
141
146
  else
142
147
  true
143
148
  end
144
149
  end
145
150
 
146
- def other_attributes_match?(job)
147
- serialized_attributes.all? { |key, value| value == job[key] }
148
- end
151
+ def queue_match?(job)
152
+ return true unless @queue
149
153
 
150
- def serialized_attributes
151
- {}.tap do |attributes|
152
- attributes[:at] = serialized_at if @at
153
- attributes[:queue] = @queue if @queue
154
- attributes[:job] = @job if @job
155
- end
154
+ @queue == job[:queue]
156
155
  end
157
156
 
158
- def serialized_at
159
- @at == :no_wait ? nil : @at.to_f
157
+ def at_match?(job)
158
+ return true unless @at
159
+ return job[:at].nil? if @at == :no_wait
160
+ return false unless job[:at]
161
+
162
+ values_match?(@at, Time.at(job[:at]))
160
163
  end
161
164
 
162
165
  def set_expected_number(relativity, count)
@@ -169,6 +172,13 @@ module RSpec
169
172
  end
170
173
  end
171
174
 
175
+ def serialize_and_deserialize_arguments(args)
176
+ serialized = ::ActiveJob::Arguments.serialize(args)
177
+ ::ActiveJob::Arguments.deserialize(serialized)
178
+ rescue ::ActiveJob::SerializationError
179
+ args
180
+ end
181
+
172
182
  def deserialize_arguments(job)
173
183
  ::ActiveJob::Arguments.deserialize(job[:args])
174
184
  rescue ::ActiveJob::DeserializationError
@@ -179,10 +189,13 @@ module RSpec
179
189
  ::ActiveJob::Base.queue_adapter
180
190
  end
181
191
  end
182
- # rubocop: enable Style/ClassLength
192
+ # rubocop: enable Metrics/ClassLength
183
193
 
184
194
  # @private
185
195
  class HaveEnqueuedJob < Base
196
+ FAILURE_MESSAGE_EXPECTATION_ACTION = 'enqueue'.freeze
197
+ MESSAGE_EXPECTATION_ACTION = 'enqueued'.freeze
198
+
186
199
  def initialize(job)
187
200
  super()
188
201
  @job = job
@@ -207,6 +220,9 @@ module RSpec
207
220
 
208
221
  # @private
209
222
  class HaveBeenEnqueued < Base
223
+ FAILURE_MESSAGE_EXPECTATION_ACTION = 'enqueue'.freeze
224
+ MESSAGE_EXPECTATION_ACTION = 'enqueued'.freeze
225
+
210
226
  def matches?(job)
211
227
  @job = job
212
228
  check(queue_adapter.enqueued_jobs)
@@ -218,6 +234,38 @@ module RSpec
218
234
  !matches?(proc)
219
235
  end
220
236
  end
237
+
238
+ # @private
239
+ class HavePerformedJob < Base
240
+ FAILURE_MESSAGE_EXPECTATION_ACTION = 'perform'.freeze
241
+ MESSAGE_EXPECTATION_ACTION = 'performed'.freeze
242
+
243
+ def initialize(job)
244
+ super()
245
+ @job = job
246
+ end
247
+
248
+ def matches?(proc)
249
+ raise ArgumentError, "have_performed_job only supports block expectations" unless Proc === proc
250
+
251
+ original_performed_jobs_count = queue_adapter.performed_jobs.count
252
+ proc.call
253
+ in_block_jobs = queue_adapter.performed_jobs.drop(original_performed_jobs_count)
254
+
255
+ check(in_block_jobs)
256
+ end
257
+ end
258
+
259
+ # @private
260
+ class HaveBeenPerformed < Base
261
+ FAILURE_MESSAGE_EXPECTATION_ACTION = 'perform'.freeze
262
+ MESSAGE_EXPECTATION_ACTION = 'performed'.freeze
263
+
264
+ def matches?(job)
265
+ @job = job
266
+ check(queue_adapter.performed_jobs)
267
+ end
268
+ end
221
269
  end
222
270
 
223
271
  # @api public
@@ -305,11 +353,85 @@ module RSpec
305
353
  ActiveJob::HaveBeenEnqueued.new
306
354
  end
307
355
 
356
+ # @api public
357
+ # Passes if a job has been performed inside block. May chain at_least, at_most or exactly to specify a number of times.
358
+ #
359
+ # @example
360
+ # expect {
361
+ # perform_jobs { HeavyLiftingJob.perform_later }
362
+ # }.to have_performed_job
363
+ #
364
+ # expect {
365
+ # perform_jobs {
366
+ # HelloJob.perform_later
367
+ # HeavyLiftingJob.perform_later
368
+ # }
369
+ # }.to have_performed_job(HelloJob).exactly(:once)
370
+ #
371
+ # expect {
372
+ # perform_jobs { 3.times { HelloJob.perform_later } }
373
+ # }.to have_performed_job(HelloJob).at_least(2).times
374
+ #
375
+ # expect {
376
+ # perform_jobs { HelloJob.perform_later }
377
+ # }.to have_performed_job(HelloJob).at_most(:twice)
378
+ #
379
+ # expect {
380
+ # perform_jobs {
381
+ # HelloJob.perform_later
382
+ # HeavyLiftingJob.perform_later
383
+ # }
384
+ # }.to have_performed_job(HelloJob).and have_performed_job(HeavyLiftingJob)
385
+ #
386
+ # expect {
387
+ # perform_jobs {
388
+ # HelloJob.set(wait_until: Date.tomorrow.noon, queue: "low").perform_later(42)
389
+ # }
390
+ # }.to have_performed_job.with(42).on_queue("low").at(Date.tomorrow.noon)
391
+ def have_performed_job(job = nil)
392
+ check_active_job_adapter
393
+ ActiveJob::HavePerformedJob.new(job)
394
+ end
395
+ alias_method :perform_job, :have_performed_job
396
+
397
+ # @api public
398
+ # Passes if a job has been performed. May chain at_least, at_most or exactly to specify a number of times.
399
+ #
400
+ # @example
401
+ # before do
402
+ # ActiveJob::Base.queue_adapter.performed_jobs.clear
403
+ # ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
404
+ # ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
405
+ # end
406
+ #
407
+ # HeavyLiftingJob.perform_later
408
+ # expect(HeavyLiftingJob).to have_been_performed
409
+ #
410
+ # HelloJob.perform_later
411
+ # HeavyLiftingJob.perform_later
412
+ # expect(HeavyLiftingJob).to have_been_performed.exactly(:once)
413
+ #
414
+ # 3.times { HelloJob.perform_later }
415
+ # expect(HelloJob).to have_been_performed.at_least(2).times
416
+ #
417
+ # HelloJob.perform_later
418
+ # HeavyLiftingJob.perform_later
419
+ # expect(HelloJob).to have_been_performed
420
+ # expect(HeavyLiftingJob).to have_been_performed
421
+ #
422
+ # HelloJob.set(wait_until: Date.tomorrow.noon, queue: "low").perform_later(42)
423
+ # expect(HelloJob).to have_been_performed.with(42).on_queue("low").at(Date.tomorrow.noon)
424
+ def have_been_performed
425
+ check_active_job_adapter
426
+ ActiveJob::HaveBeenPerformed.new
427
+ end
428
+
308
429
  private
309
430
 
310
431
  # @private
311
432
  def check_active_job_adapter
312
433
  return if ::ActiveJob::QueueAdapters::TestAdapter === ::ActiveJob::Base.queue_adapter
434
+
313
435
  raise StandardError, "To use ActiveJob matchers set `ActiveJob::Base.queue_adapter = :test`"
314
436
  end
315
437
  end
@@ -1,7 +1,9 @@
1
1
  module RSpec
2
2
  module Rails
3
3
  module Matchers
4
- # @ api private
4
+ # @api private
5
+ #
6
+ # Base class to build matchers. Should not be instantiated directly.
5
7
  class BaseMatcher
6
8
  include RSpec::Matchers::Composable
7
9
 
@@ -114,19 +116,12 @@ module RSpec
114
116
 
115
117
  def assert_ivars(*expected_ivars)
116
118
  return unless (expected_ivars - present_ivars).any?
119
+
117
120
  ivar_list = RSpec::Matchers::EnglishPhrasing.list(expected_ivars)
118
121
  raise "#{self.class.name} needs to supply#{ivar_list}"
119
122
  end
120
123
 
121
- if RUBY_VERSION.to_f < 1.9
122
- # :nocov:
123
- def present_ivars
124
- instance_variables.map(&:to_sym)
125
- end
126
- # :nocov:
127
- else
128
- alias present_ivars instance_variables
129
- end
124
+ alias present_ivars instance_variables
130
125
 
131
126
  # @private
132
127
  module HashFormatting
@@ -1,4 +1,7 @@
1
- require "rspec/mocks"
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"
2
5
  require "rspec/rails/matchers/active_job"
3
6
 
4
7
  module RSpec
@@ -6,33 +9,32 @@ module RSpec
6
9
  module Matchers
7
10
  # Matcher class for `have_enqueued_mail`. Should not be instantiated directly.
8
11
  #
9
- # rubocop: disable Style/ClassLength
10
12
  # @private
11
13
  # @see RSpec::Rails::Matchers#have_enqueued_mail
12
14
  class HaveEnqueuedMail < ActiveJob::HaveEnqueuedJob
13
15
  MAILER_JOB_METHOD = 'deliver_now'.freeze
14
16
 
15
- include RSpec::Mocks::ExampleMethods
17
+ include RSpec::Mocks::ArgumentMatchers
16
18
 
17
19
  def initialize(mailer_class, method_name)
18
- super(mailer_job)
20
+ super(nil)
19
21
  @mailer_class = mailer_class
20
22
  @method_name = method_name
21
23
  @mail_args = []
22
- @args = mailer_args
23
24
  end
24
25
 
25
26
  def description
26
- "enqueues #{@mailer_class.name}.#{@method_name}"
27
+ "enqueues #{mailer_class_name}.#{@method_name}"
27
28
  end
28
29
 
29
30
  def with(*args, &block)
30
31
  @mail_args = args
31
- block.nil? ? super(*mailer_args) : super(*mailer_args, &yield_mail_args(block))
32
+ block.nil? ? super : super(&yield_mail_args(block))
32
33
  end
33
34
 
34
35
  def matches?(block)
35
36
  raise ArgumentError, 'have_enqueued_mail and enqueue_mail only work with block arguments' unless block.respond_to?(:call)
37
+
36
38
  check_active_job_adapter
37
39
  super
38
40
  end
@@ -50,7 +52,7 @@ module RSpec
50
52
  private
51
53
 
52
54
  def base_message
53
- "#{@mailer_class.name}.#{@method_name}".tap do |msg|
55
+ [mailer_class_name, @method_name].compact.join('.').tap do |msg|
54
56
  msg << " #{expected_count_message}"
55
57
  msg << " with #{@mail_args}," if @mail_args.any?
56
58
  msg << " on queue #{@queue}," if @queue
@@ -63,38 +65,46 @@ module RSpec
63
65
  "#{message_expectation_modifier} #{@expected_number} #{@expected_number == 1 ? 'time' : 'times'}"
64
66
  end
65
67
 
66
- def mailer_args
67
- if @mail_args.any?
68
- base_mailer_args + @mail_args
69
- else
70
- mailer_method_arity = @mailer_class.instance_method(@method_name).arity
68
+ def mailer_class_name
69
+ @mailer_class ? @mailer_class.name : 'ActionMailer::Base'
70
+ end
71
71
 
72
- number_of_args = if mailer_method_arity < 0
73
- (mailer_method_arity + 1).abs
74
- else
75
- mailer_method_arity
76
- end
72
+ def job_match?(job)
73
+ legacy_mail?(job) || parameterized_mail?(job) || unified_mail?(job)
74
+ end
77
75
 
78
- base_mailer_args + Array.new(number_of_args) { anything }
79
- end
76
+ def arguments_match?(job)
77
+ @args =
78
+ if @mail_args.any?
79
+ base_mailer_args + @mail_args
80
+ elsif @mailer_class && @method_name
81
+ base_mailer_args + [any_args]
82
+ elsif @mailer_class
83
+ [mailer_class_name, any_args]
84
+ else
85
+ []
86
+ end
87
+
88
+ super(job)
80
89
  end
81
90
 
82
91
  def base_mailer_args
83
- [@mailer_class.name, @method_name.to_s, MAILER_JOB_METHOD]
92
+ [mailer_class_name, @method_name.to_s, MAILER_JOB_METHOD]
84
93
  end
85
94
 
86
95
  def yield_mail_args(block)
87
- Proc.new { |*job_args| block.call(*(job_args - base_mailer_args)) }
96
+ proc { |*job_args| block.call(*(job_args - base_mailer_args)) }
88
97
  end
89
98
 
90
99
  def check_active_job_adapter
91
100
  return if ::ActiveJob::QueueAdapters::TestAdapter === ::ActiveJob::Base.queue_adapter
101
+
92
102
  raise StandardError, "To use HaveEnqueuedMail matcher set `ActiveJob::Base.queue_adapter = :test`"
93
103
  end
94
104
 
95
105
  def unmatching_mail_jobs
96
106
  @unmatching_jobs.select do |job|
97
- job[:job] == mailer_job
107
+ job_match?(job)
98
108
  end
99
109
  end
100
110
 
@@ -120,12 +130,18 @@ module RSpec
120
130
  "#{mailer_method} #{msg_parts.join(', ')}".strip
121
131
  end
122
132
 
123
- def mailer_job
124
- ActionMailer::DeliveryJob
133
+ def legacy_mail?(job)
134
+ job[:job] == ActionMailer::DeliveryJob
135
+ end
136
+
137
+ def parameterized_mail?(job)
138
+ RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? && job[:job] == ActionMailer::Parameterized::DeliveryJob
125
139
  end
126
- end
127
- # rubocop: enable Style/ClassLength
128
140
 
141
+ def unified_mail?(job)
142
+ RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? && job[:job] == ActionMailer::MailDeliveryJob
143
+ end
144
+ end
129
145
  # @api public
130
146
  # Passes if an email has been enqueued inside block.
131
147
  # May chain with to specify expected arguments.
@@ -136,6 +152,14 @@ module RSpec
136
152
  # @example
137
153
  # expect {
138
154
  # MyMailer.welcome(user).deliver_later
155
+ # }.to have_enqueued_mail
156
+ #
157
+ # expect {
158
+ # MyMailer.welcome(user).deliver_later
159
+ # }.to have_enqueued_mail(MyMailer)
160
+ #
161
+ # expect {
162
+ # MyMailer.welcome(user).deliver_later
139
163
  # }.to have_enqueued_mail(MyMailer, :welcome)
140
164
  #
141
165
  # # Using alias
@@ -163,7 +187,7 @@ module RSpec
163
187
  # expect {
164
188
  # MyMailer.welcome(user).deliver_later(queue: :urgent_mail)
165
189
  # }.to have_enqueued_mail(MyMailer, :welcome).on_queue(:urgent_mail)
166
- def have_enqueued_mail(mailer_class, mail_method_name)
190
+ def have_enqueued_mail(mailer_class = nil, mail_method_name = nil)
167
191
  HaveEnqueuedMail.new(mailer_class, mail_method_name)
168
192
  end
169
193
  alias_method :have_enqueued_email, :have_enqueued_mail
@@ -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,7 +73,7 @@ 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
+ # @see RSpec::Rails::Matchers#have_http_status
76
77
  class NumericCode < RSpec::Rails::Matchers::BaseMatcher
77
78
  include HaveHttpStatus
78
79
 
@@ -122,7 +123,7 @@ 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
128
  class SymbolicStatus < RSpec::Rails::Matchers::BaseMatcher
128
129
  include HaveHttpStatus
@@ -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,8 +236,8 @@ 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
+ # @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`
239
241
  class GenericStatus < RSpec::Rails::Matchers::BaseMatcher
240
242
  include HaveHttpStatus
241
243
 
@@ -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
@@ -290,9 +293,9 @@ module RSpec
290
293
  protected
291
294
 
292
295
  RESPONSE_METHODS = {
293
- :success => 'successful',
294
- :error => 'server_error',
295
- :missing => 'not_found'
296
+ success: 'successful',
297
+ error: 'server_error',
298
+ missing: 'not_found'
296
299
  }.freeze
297
300
 
298
301
  def check_expected_status(test_response, expected)
@@ -374,6 +377,7 @@ module RSpec
374
377
  # @see https://github.com/rack/rack/blob/master/lib/rack/utils.rb `Rack::Utils::SYMBOL_TO_STATUS_CODE`
375
378
  def have_http_status(target)
376
379
  raise ArgumentError, "Invalid HTTP status: nil" unless target
380
+
377
381
  HaveHttpStatus.matcher_for_status(target)
378
382
  end
379
383
  end
@@ -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
 
@@ -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,14 +50,14 @@ 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
@@ -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
@@ -20,7 +20,16 @@ require 'rspec/rails/matchers/be_a_new'
20
20
  require 'rspec/rails/matchers/relation_match_array'
21
21
  require 'rspec/rails/matchers/be_valid'
22
22
  require 'rspec/rails/matchers/have_http_status'
23
+
23
24
  if RSpec::Rails::FeatureCheck.has_active_job?
24
25
  require 'rspec/rails/matchers/active_job'
25
26
  require 'rspec/rails/matchers/have_enqueued_mail'
26
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'
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|