rspec-rails 4.0.0 → 6.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/Changelog.md +247 -53
- data/README.md +73 -61
- data/lib/generators/rspec/channel/channel_generator.rb +1 -1
- data/lib/generators/rspec/controller/controller_generator.rb +5 -5
- data/lib/generators/rspec/controller/templates/request_spec.rb +6 -1
- data/lib/generators/rspec/feature/feature_generator.rb +1 -1
- data/lib/generators/rspec/generator/generator_generator.rb +3 -3
- data/lib/generators/rspec/generator/templates/generator_spec.rb +1 -2
- data/lib/generators/rspec/helper/helper_generator.rb +1 -1
- data/lib/generators/rspec/install/install_generator.rb +19 -2
- data/lib/generators/rspec/install/templates/spec/rails_helper.rb +13 -8
- data/lib/generators/rspec/integration/integration_generator.rb +10 -3
- data/lib/generators/rspec/job/job_generator.rb +2 -1
- data/lib/generators/rspec/job/templates/job_spec.rb.erb +1 -1
- data/lib/generators/rspec/mailbox/mailbox_generator.rb +1 -1
- data/lib/generators/rspec/mailer/mailer_generator.rb +5 -3
- data/lib/generators/rspec/mailer/templates/mailer_spec.rb +2 -2
- data/lib/generators/rspec/mailer/templates/preview.rb +2 -2
- data/lib/generators/rspec/model/model_generator.rb +3 -3
- data/lib/generators/rspec/request/request_generator.rb +10 -3
- data/lib/generators/rspec/scaffold/scaffold_generator.rb +8 -4
- data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +13 -13
- data/lib/generators/rspec/scaffold/templates/api_request_spec.rb +20 -20
- data/lib/generators/rspec/scaffold/templates/controller_spec.rb +25 -58
- data/lib/generators/rspec/scaffold/templates/edit_spec.rb +8 -8
- data/lib/generators/rspec/scaffold/templates/index_spec.rb +2 -1
- data/lib/generators/rspec/scaffold/templates/new_spec.rb +1 -5
- data/lib/generators/rspec/scaffold/templates/request_spec.rb +38 -18
- data/lib/generators/rspec/scaffold/templates/show_spec.rb +1 -1
- data/lib/generators/rspec/system/system_generator.rb +14 -16
- data/lib/generators/rspec/view/view_generator.rb +2 -2
- data/lib/generators/rspec.rb +18 -1
- data/lib/rspec/rails/adapters.rb +11 -0
- data/lib/rspec/rails/configuration.rb +82 -18
- data/lib/rspec/rails/example/controller_example_group.rb +1 -0
- data/lib/rspec/rails/example/mailbox_example_group.rb +2 -2
- data/lib/rspec/rails/example/mailer_example_group.rb +2 -2
- data/lib/rspec/rails/example/rails_example_group.rb +8 -0
- data/lib/rspec/rails/example/request_example_group.rb +1 -4
- data/lib/rspec/rails/example/routing_example_group.rb +0 -2
- data/lib/rspec/rails/example/system_example_group.rb +63 -15
- data/lib/rspec/rails/example/view_example_group.rb +6 -5
- data/lib/rspec/rails/extensions/active_record/proxy.rb +4 -1
- data/lib/rspec/rails/feature_check.rb +6 -2
- data/lib/rspec/rails/file_fixture_support.rb +11 -10
- data/lib/rspec/rails/fixture_file_upload_support.rb +19 -14
- data/lib/rspec/rails/fixture_support.rb +49 -24
- data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +6 -3
- data/lib/rspec/rails/matchers/action_mailbox.rb +14 -5
- data/lib/rspec/rails/matchers/active_job.rb +32 -6
- data/lib/rspec/rails/matchers/have_enqueued_mail.rb +34 -5
- data/lib/rspec/rails/matchers/have_http_status.rb +5 -5
- data/lib/rspec/rails/matchers/relation_match_array.rb +1 -1
- data/lib/rspec/rails/matchers/routing_matchers.rb +2 -2
- data/lib/rspec/rails/matchers/send_email.rb +122 -0
- data/lib/rspec/rails/matchers.rb +1 -0
- data/lib/rspec/rails/vendor/capybara.rb +1 -3
- data/lib/rspec/rails/version.rb +1 -1
- data/lib/rspec/rails/view_assigns.rb +0 -18
- data/lib/rspec/rails/view_rendering.rb +13 -11
- data/lib/rspec-rails.rb +13 -11
- data.tar.gz.sig +0 -0
- metadata +28 -27
- metadata.gz.sig +0 -0
- /data/lib/generators/rspec/{integration → request}/templates/request_spec.rb +0 -0
@@ -13,7 +13,7 @@ module RSpec
|
|
13
13
|
def self.create_inbound_email(arg)
|
14
14
|
case arg
|
15
15
|
when Hash
|
16
|
-
create_inbound_email_from_mail(arg)
|
16
|
+
create_inbound_email_from_mail(**arg)
|
17
17
|
else
|
18
18
|
create_inbound_email_from_source(arg.to_s)
|
19
19
|
end
|
@@ -69,7 +69,7 @@ module RSpec
|
|
69
69
|
#
|
70
70
|
# @param message [Hash, Mail::Message] a mail message or hash of
|
71
71
|
# attributes used to build one
|
72
|
-
# @return [
|
72
|
+
# @return [ActionMailbox::InboundMessage]
|
73
73
|
def process(message)
|
74
74
|
MailboxExampleGroup.create_inbound_email(message).tap do |mail|
|
75
75
|
self.class.mailbox_class.receive(mail)
|
@@ -21,8 +21,8 @@ if defined?(ActionMailer)
|
|
21
21
|
|
22
22
|
included do
|
23
23
|
include ::Rails.application.routes.url_helpers
|
24
|
-
options = ::Rails.configuration.action_mailer.default_url_options
|
25
|
-
options
|
24
|
+
options = ::Rails.configuration.action_mailer.default_url_options || {}
|
25
|
+
options.each { |key, value| default_url_options[key] = value }
|
26
26
|
end
|
27
27
|
|
28
28
|
# Class-level DSL for mailer specs.
|
@@ -2,6 +2,10 @@
|
|
2
2
|
# suite and ammeter.
|
3
3
|
require 'rspec/rails/matchers'
|
4
4
|
|
5
|
+
if ::Rails::VERSION::MAJOR >= 7
|
6
|
+
require 'active_support/execution_context/test_helper'
|
7
|
+
end
|
8
|
+
|
5
9
|
module RSpec
|
6
10
|
module Rails
|
7
11
|
# @api public
|
@@ -12,6 +16,10 @@ module RSpec
|
|
12
16
|
include RSpec::Rails::MinitestLifecycleAdapter
|
13
17
|
include RSpec::Rails::MinitestAssertionAdapter
|
14
18
|
include RSpec::Rails::FixtureSupport
|
19
|
+
if ::Rails::VERSION::MAJOR >= 7
|
20
|
+
include RSpec::Rails::TaggedLoggingAdapter
|
21
|
+
include ActiveSupport::ExecutionContext::TestHelper
|
22
|
+
end
|
15
23
|
end
|
16
24
|
end
|
17
25
|
end
|
@@ -10,10 +10,7 @@ module RSpec
|
|
10
10
|
include RSpec::Rails::Matchers::RedirectTo
|
11
11
|
include RSpec::Rails::Matchers::RenderTemplate
|
12
12
|
include ActionController::TemplateAssertions
|
13
|
-
|
14
|
-
if ActionPack::VERSION::MAJOR >= 5
|
15
|
-
include ActionDispatch::IntegrationTest::Behavior
|
16
|
-
end
|
13
|
+
include ActionDispatch::IntegrationTest::Behavior
|
17
14
|
|
18
15
|
# Delegates to `Rails.application`.
|
19
16
|
def app
|
@@ -41,7 +41,53 @@ module RSpec
|
|
41
41
|
@method_name ||= [
|
42
42
|
self.class.name.underscore,
|
43
43
|
RSpec.current_example.description.underscore
|
44
|
-
].join("_").tr(CHARS_TO_TRANSLATE.join, "_")
|
44
|
+
].join("_").tr(CHARS_TO_TRANSLATE.join, "_").byteslice(0...200).scrub("") + "_#{rand(1000)}"
|
45
|
+
end
|
46
|
+
|
47
|
+
if ::Rails::VERSION::STRING.to_f >= 7.1
|
48
|
+
# @private
|
49
|
+
# Allows failure screenshot to work whilst not exposing metadata
|
50
|
+
class SuppressRailsScreenshotMetadata
|
51
|
+
def initialize
|
52
|
+
@example_data = {}
|
53
|
+
end
|
54
|
+
|
55
|
+
def [](key)
|
56
|
+
if @example_data.key?(key)
|
57
|
+
@example_data[key]
|
58
|
+
else
|
59
|
+
raise_wrong_scope_error
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def []=(key, value)
|
64
|
+
if key == :failure_screenshot_path
|
65
|
+
@example_data[key] = value
|
66
|
+
else
|
67
|
+
raise_wrong_scope_error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def method_missing(_name, *_args, &_block)
|
72
|
+
raise_wrong_scope_error
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def raise_wrong_scope_error
|
78
|
+
raise RSpec::Core::ExampleGroup::WrongScopeError,
|
79
|
+
"`metadata` is not available from within an example " \
|
80
|
+
"(e.g. an `it` block) or from constructs that run in the " \
|
81
|
+
"scope of an example (e.g. `before`, `let`, etc). It is " \
|
82
|
+
"only available on an example group (e.g. a `describe` or "\
|
83
|
+
"`context` block)"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# @private
|
88
|
+
def metadata
|
89
|
+
@metadata ||= SuppressRailsScreenshotMetadata.new
|
90
|
+
end
|
45
91
|
end
|
46
92
|
|
47
93
|
# Delegates to `Rails.application`.
|
@@ -54,23 +100,22 @@ module RSpec
|
|
54
100
|
ActionDispatch::SystemTesting::Server.silence_puma = true
|
55
101
|
end
|
56
102
|
|
103
|
+
require 'action_dispatch/system_test_case'
|
104
|
+
|
57
105
|
begin
|
58
106
|
require 'capybara'
|
59
|
-
require 'action_dispatch/system_test_case'
|
60
107
|
rescue LoadError => e
|
61
108
|
abort """
|
62
109
|
LoadError: #{e.message}
|
63
|
-
System test integration
|
110
|
+
System test integration has a hard
|
64
111
|
dependency on a webserver and `capybara`, please add capybara to
|
65
112
|
your Gemfile and configure a webserver (e.g. `Capybara.server =
|
66
|
-
:
|
113
|
+
:puma`) before attempting to use system specs.
|
67
114
|
""".gsub(/\s+/, ' ').strip
|
68
115
|
end
|
69
116
|
|
70
|
-
|
71
|
-
|
72
|
-
::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:before_teardown)
|
73
|
-
end
|
117
|
+
original_before_teardown =
|
118
|
+
::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:before_teardown)
|
74
119
|
|
75
120
|
original_after_teardown =
|
76
121
|
::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:after_teardown)
|
@@ -96,8 +141,8 @@ module RSpec
|
|
96
141
|
end
|
97
142
|
end
|
98
143
|
|
99
|
-
def driven_by(
|
100
|
-
@driver = ::ActionDispatch::SystemTestCase.driven_by(
|
144
|
+
def driven_by(driver, **driver_options, &blk)
|
145
|
+
@driver = ::ActionDispatch::SystemTestCase.driven_by(driver, **driver_options, &blk).tap(&:use)
|
101
146
|
end
|
102
147
|
|
103
148
|
before do
|
@@ -108,16 +153,19 @@ module RSpec
|
|
108
153
|
orig_stdout = $stdout
|
109
154
|
$stdout = StringIO.new
|
110
155
|
begin
|
111
|
-
|
112
|
-
original_before_teardown.bind(self).call
|
113
|
-
end
|
114
|
-
original_after_teardown.bind(self).call
|
156
|
+
original_before_teardown.bind(self).call
|
115
157
|
ensure
|
116
158
|
myio = $stdout
|
117
|
-
|
159
|
+
myio.rewind
|
160
|
+
RSpec.current_example.metadata[:extra_failure_lines] = myio.readlines
|
118
161
|
$stdout = orig_stdout
|
119
162
|
end
|
120
163
|
end
|
164
|
+
|
165
|
+
around do |example|
|
166
|
+
example.run
|
167
|
+
original_after_teardown.bind(self).call
|
168
|
+
end
|
121
169
|
end
|
122
170
|
end
|
123
171
|
end
|
@@ -65,6 +65,7 @@ module RSpec
|
|
65
65
|
# end
|
66
66
|
def render(options = {}, local_assigns = {}, &block)
|
67
67
|
options = _default_render_options if Hash === options && options.empty?
|
68
|
+
options = options.merge(_default_render_options) if Hash === options && options.keys == [:locals]
|
68
69
|
super(options, local_assigns, &block)
|
69
70
|
end
|
70
71
|
|
@@ -89,7 +90,7 @@ module RSpec
|
|
89
90
|
#
|
90
91
|
# stub_template("widgets/_widget.html.erb" => "This content.")
|
91
92
|
def stub_template(hash)
|
92
|
-
|
93
|
+
controller.prepend_view_path(StubResolverCache.resolver_for(hash))
|
93
94
|
end
|
94
95
|
|
95
96
|
# Provides access to the params hash that will be available within the
|
@@ -149,11 +150,11 @@ module RSpec
|
|
149
150
|
# the original string.
|
150
151
|
match = path_regex.match(_default_file_to_render)
|
151
152
|
|
152
|
-
render_options = {template: match[:template]}
|
153
|
-
render_options[:handlers] = [match[:handler]] if match[:handler]
|
153
|
+
render_options = { template: match[:template] }
|
154
|
+
render_options[:handlers] = [match[:handler].to_sym] if match[:handler]
|
154
155
|
render_options[:formats] = [match[:format].to_sym] if match[:format]
|
155
|
-
render_options[:locales] = [match[:locale]] if match[:locale]
|
156
|
-
render_options[:variants] = [match[:variant]] if match[:variant]
|
156
|
+
render_options[:locales] = [match[:locale].to_sym] if match[:locale]
|
157
|
+
render_options[:variants] = [match[:variant].to_sym] if match[:variant]
|
157
158
|
|
158
159
|
render_options
|
159
160
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
RSpec.configure do |rspec|
|
2
2
|
# Delay this in order to give users a chance to configure `expect_with`...
|
3
3
|
rspec.before(:suite) do
|
4
|
-
if defined?(RSpec::Matchers) &&
|
4
|
+
if defined?(RSpec::Matchers) &&
|
5
|
+
RSpec::Matchers.configuration.respond_to?(:syntax) && # RSpec 4 dropped support for monkey-patching `should` syntax
|
6
|
+
RSpec::Matchers.configuration.syntax.include?(:should) &&
|
7
|
+
defined?(ActiveRecord::Associations)
|
5
8
|
RSpec::Matchers.configuration.add_should_and_should_not_to ActiveRecord::Associations::CollectionProxy
|
6
9
|
end
|
7
10
|
end
|
@@ -24,17 +24,21 @@ module RSpec
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def has_action_cable_testing?
|
27
|
-
defined?(::ActionCable)
|
27
|
+
defined?(::ActionCable)
|
28
28
|
end
|
29
29
|
|
30
30
|
def has_action_mailer_parameterized?
|
31
|
-
has_action_mailer? && defined?(::ActionMailer::Parameterized)
|
31
|
+
has_action_mailer? && defined?(::ActionMailer::Parameterized::DeliveryJob)
|
32
32
|
end
|
33
33
|
|
34
34
|
def has_action_mailer_unified_delivery?
|
35
35
|
has_action_mailer? && defined?(::ActionMailer::MailDeliveryJob)
|
36
36
|
end
|
37
37
|
|
38
|
+
def has_action_mailer_legacy_delivery_job?
|
39
|
+
defined?(ActionMailer::DeliveryJob)
|
40
|
+
end
|
41
|
+
|
38
42
|
def has_action_mailbox?
|
39
43
|
defined?(::ActionMailbox)
|
40
44
|
end
|
@@ -1,15 +1,16 @@
|
|
1
|
-
|
2
|
-
require 'active_support/testing/file_fixtures'
|
1
|
+
require 'active_support/testing/file_fixtures'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
module RSpec
|
4
|
+
module Rails
|
5
|
+
# @private
|
6
|
+
module FileFixtureSupport
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include ActiveSupport::Testing::FileFixtures
|
10
9
|
|
11
|
-
|
12
|
-
|
10
|
+
included do
|
11
|
+
self.file_fixture_path = RSpec.configuration.file_fixture_path
|
12
|
+
if defined?(ActiveStorage::FixtureSet)
|
13
|
+
ActiveStorage::FixtureSet.file_fixture_path = RSpec.configuration.file_fixture_path
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
@@ -6,33 +6,38 @@ module RSpec
|
|
6
6
|
|
7
7
|
private
|
8
8
|
|
9
|
+
# In Rails 7.0 fixture file path needs to be relative to `file_fixture_path` instead, this change
|
10
|
+
# was brought in with a deprecation warning on 6.1. In Rails 7.0 expect to rework this to remove
|
11
|
+
# the old accessor.
|
9
12
|
def rails_fixture_file_wrapper
|
10
|
-
RailsFixtureFileWrapper.
|
11
|
-
resolved_fixture_path =
|
12
|
-
|
13
|
+
RailsFixtureFileWrapper.file_fixture_path = nil
|
14
|
+
resolved_fixture_path =
|
15
|
+
if respond_to?(:file_fixture_path) && !file_fixture_path.nil?
|
16
|
+
file_fixture_path.to_s
|
17
|
+
elsif respond_to?(:fixture_paths)
|
18
|
+
(RSpec.configuration.fixture_paths&.first || '').to_s
|
19
|
+
else
|
20
|
+
(RSpec.configuration.fixture_path || '').to_s
|
21
|
+
end
|
22
|
+
RailsFixtureFileWrapper.file_fixture_path = File.join(resolved_fixture_path, '') unless resolved_fixture_path.strip.empty?
|
13
23
|
RailsFixtureFileWrapper.instance
|
14
24
|
end
|
15
25
|
|
16
26
|
class RailsFixtureFileWrapper
|
17
27
|
include ActionDispatch::TestProcess if defined?(ActionDispatch::TestProcess)
|
28
|
+
include ActiveSupport::Testing::FileFixtures
|
18
29
|
|
19
30
|
class << self
|
20
|
-
|
31
|
+
if ::Rails::VERSION::STRING < "7.1.0"
|
32
|
+
attr_accessor :fixture_path
|
33
|
+
else
|
34
|
+
attr_accessor :fixture_paths
|
35
|
+
end
|
21
36
|
|
22
37
|
# Get instance of wrapper
|
23
38
|
def instance
|
24
39
|
@instance ||= new
|
25
40
|
end
|
26
|
-
|
27
|
-
# Override fixture_path set
|
28
|
-
# to support Rails 3.0->3.1 using ActionController::TestCase class to resolve fixture_path
|
29
|
-
# see https://apidock.com/rails/v3.0.0/ActionDispatch/TestProcess/fixture_file_upload
|
30
|
-
def fixture_path=(value)
|
31
|
-
if ActionController::TestCase.respond_to?(:fixture_path)
|
32
|
-
ActionController::TestCase.fixture_path = value
|
33
|
-
end
|
34
|
-
@fixture_path = value
|
35
|
-
end
|
36
41
|
end
|
37
42
|
end
|
38
43
|
end
|
@@ -9,16 +9,26 @@ module RSpec
|
|
9
9
|
include RSpec::Rails::MinitestAssertionAdapter
|
10
10
|
include ActiveRecord::TestFixtures
|
11
11
|
|
12
|
+
# @private prevent ActiveSupport::TestFixtures to start a DB transaction.
|
13
|
+
# Monkey patched to avoid collisions with 'let(:name)' in Rails 6.1 and after
|
14
|
+
# and let(:method_name) before Rails 6.1.
|
15
|
+
def run_in_transaction?
|
16
|
+
current_example_name = (RSpec.current_example && RSpec.current_example.metadata[:description])
|
17
|
+
use_transactional_tests && !self.class.uses_transaction?(current_example_name)
|
18
|
+
end
|
19
|
+
|
12
20
|
included do
|
13
21
|
if RSpec.configuration.use_active_record?
|
14
22
|
include Fixtures
|
15
23
|
|
16
|
-
|
17
|
-
if
|
18
|
-
self.
|
24
|
+
# TestFixtures#fixture_path is deprecated and will be removed in Rails 7.2
|
25
|
+
if respond_to?(:fixture_paths=)
|
26
|
+
self.fixture_paths = RSpec.configuration.fixture_paths
|
19
27
|
else
|
20
|
-
self.
|
28
|
+
self.fixture_path = RSpec.configuration.fixture_path
|
21
29
|
end
|
30
|
+
|
31
|
+
self.use_transactional_tests = RSpec.configuration.use_transactional_fixtures
|
22
32
|
self.use_instantiated_fixtures = RSpec.configuration.use_instantiated_fixtures
|
23
33
|
|
24
34
|
fixtures RSpec.configuration.global_fixtures if RSpec.configuration.global_fixtures
|
@@ -28,35 +38,50 @@ module RSpec
|
|
28
38
|
module Fixtures
|
29
39
|
extend ActiveSupport::Concern
|
30
40
|
|
41
|
+
# rubocop:disable Metrics/BlockLength
|
31
42
|
class_methods do
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
43
|
+
if ::Rails.version.to_f >= 7.1
|
44
|
+
def fixtures(*args)
|
45
|
+
super.tap do
|
46
|
+
fixture_sets.each_pair do |method_name, fixture_name|
|
47
|
+
proxy_method_warning_if_called_in_before_context_scope(method_name, fixture_name)
|
48
|
+
end
|
38
49
|
end
|
39
50
|
end
|
40
|
-
end
|
41
51
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
52
|
+
def proxy_method_warning_if_called_in_before_context_scope(method_name, fixture_name)
|
53
|
+
define_method(method_name) do |*args, **kwargs, &blk|
|
54
|
+
if RSpec.current_scope == :before_context_hook
|
55
|
+
RSpec.warn_with("Calling fixture method in before :context ")
|
56
|
+
else
|
57
|
+
access_fixture(fixture_name, *args, **kwargs, &blk)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
else
|
62
|
+
def fixtures(*args)
|
63
|
+
orig_methods = private_instance_methods
|
64
|
+
super.tap do
|
65
|
+
new_methods = private_instance_methods - orig_methods
|
66
|
+
new_methods.each do |method_name|
|
67
|
+
proxy_method_warning_if_called_in_before_context_scope(method_name)
|
68
|
+
end
|
49
69
|
end
|
50
70
|
end
|
51
|
-
end
|
52
|
-
end
|
53
71
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
72
|
+
def proxy_method_warning_if_called_in_before_context_scope(method_name)
|
73
|
+
orig_implementation = instance_method(method_name)
|
74
|
+
define_method(method_name) do |*args, &blk|
|
75
|
+
if RSpec.current_scope == :before_context_hook
|
76
|
+
RSpec.warn_with("Calling fixture method in before :context ")
|
77
|
+
else
|
78
|
+
orig_implementation.bind(self).call(*args, &blk)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
58
82
|
end
|
59
83
|
end
|
84
|
+
# rubocop:enable Metrics/BlockLength
|
60
85
|
end
|
61
86
|
end
|
62
87
|
end
|
@@ -96,8 +96,11 @@ module RSpec
|
|
96
96
|
private
|
97
97
|
|
98
98
|
def stream
|
99
|
-
@stream ||=
|
99
|
+
@stream ||= case @target
|
100
|
+
when String
|
100
101
|
@target
|
102
|
+
when Symbol
|
103
|
+
@target.to_s
|
101
104
|
else
|
102
105
|
check_channel_presence
|
103
106
|
@channel.broadcasting_for(@target)
|
@@ -109,7 +112,7 @@ module RSpec
|
|
109
112
|
decoded = ActiveSupport::JSON.decode(msg)
|
110
113
|
decoded = decoded.with_indifferent_access if decoded.is_a?(Hash)
|
111
114
|
|
112
|
-
if @data.nil? || @data
|
115
|
+
if @data.nil? || values_match?(@data, decoded)
|
113
116
|
@block.call(decoded)
|
114
117
|
true
|
115
118
|
else
|
@@ -159,7 +162,7 @@ module RSpec
|
|
159
162
|
def check_channel_presence
|
160
163
|
return if @channel.present? && @channel.respond_to?(:channel_name)
|
161
164
|
|
162
|
-
error_msg = "Broadcasting channel can't be
|
165
|
+
error_msg = "Broadcasting channel can't be inferred. Please, specify it with `from_channel`"
|
163
166
|
raise ArgumentError, error_msg
|
164
167
|
end
|
165
168
|
end
|
@@ -22,11 +22,20 @@ module RSpec
|
|
22
22
|
@inbound_email = create_inbound_email(message)
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
if defined?(::ApplicationMailbox) && ::ApplicationMailbox.router.respond_to?(:mailbox_for)
|
26
|
+
def matches?(mailbox)
|
27
|
+
@mailbox = mailbox
|
28
|
+
@receiver = ApplicationMailbox.router.mailbox_for(inbound_email)
|
28
29
|
|
29
|
-
|
30
|
+
@receiver == @mailbox
|
31
|
+
end
|
32
|
+
else
|
33
|
+
def matches?(mailbox)
|
34
|
+
@mailbox = mailbox
|
35
|
+
@receiver = ApplicationMailbox.router.send(:match_to_mailbox, inbound_email)
|
36
|
+
|
37
|
+
@receiver == @mailbox
|
38
|
+
end
|
30
39
|
end
|
31
40
|
|
32
41
|
def failure_message
|
@@ -41,7 +50,7 @@ module RSpec
|
|
41
50
|
"expected #{describe_inbound_email} not to route to #{mailbox}"
|
42
51
|
end
|
43
52
|
|
44
|
-
|
53
|
+
private
|
45
54
|
|
46
55
|
attr_reader :inbound_email, :mailbox, :receiver
|
47
56
|
|
@@ -30,8 +30,12 @@ module RSpec
|
|
30
30
|
self
|
31
31
|
end
|
32
32
|
|
33
|
-
def at(
|
34
|
-
|
33
|
+
def at(time_or_date)
|
34
|
+
case time_or_date
|
35
|
+
when Time then @at = Time.at(time_or_date.to_f)
|
36
|
+
else
|
37
|
+
@at = time_or_date
|
38
|
+
end
|
35
39
|
self
|
36
40
|
end
|
37
41
|
|
@@ -159,7 +163,29 @@ module RSpec
|
|
159
163
|
return job[:at].nil? if @at == :no_wait
|
160
164
|
return false unless job[:at]
|
161
165
|
|
162
|
-
|
166
|
+
scheduled_at = Time.at(job[:at])
|
167
|
+
values_match?(@at, scheduled_at) || check_for_inprecise_value(scheduled_at)
|
168
|
+
end
|
169
|
+
|
170
|
+
def check_for_inprecise_value(scheduled_at)
|
171
|
+
return unless Time === @at && values_match?(@at.change(usec: 0), scheduled_at)
|
172
|
+
|
173
|
+
RSpec.warn_with((<<-WARNING).gsub(/^\s+\|/, '').chomp)
|
174
|
+
|[WARNING] Your expected `at(...)` value does not match the job scheduled_at value
|
175
|
+
|unless microseconds are removed. This precision error often occurs when checking
|
176
|
+
|values against `Time.current` / `Time.now` which have usec precision, but Rails
|
177
|
+
|uses `n.seconds.from_now` internally which has a usec count of `0`.
|
178
|
+
|
|
179
|
+
|Use `change(usec: 0)` to correct these values. For example:
|
180
|
+
|
|
181
|
+
|`Time.current.change(usec: 0)`
|
182
|
+
|
|
183
|
+
|Note: RSpec cannot do this for you because jobs can be scheduled with usec
|
184
|
+
|precision and we do not know whether it is on purpose or not.
|
185
|
+
|
|
186
|
+
|
|
187
|
+
WARNING
|
188
|
+
false
|
163
189
|
end
|
164
190
|
|
165
191
|
def set_expected_number(relativity, count)
|
@@ -204,11 +230,11 @@ module RSpec
|
|
204
230
|
def matches?(proc)
|
205
231
|
raise ArgumentError, "have_enqueued_job and enqueue_job only support block expectations" unless Proc === proc
|
206
232
|
|
207
|
-
|
233
|
+
original_enqueued_jobs = Set.new(queue_adapter.enqueued_jobs)
|
208
234
|
proc.call
|
209
|
-
|
235
|
+
enqueued_jobs = Set.new(queue_adapter.enqueued_jobs)
|
210
236
|
|
211
|
-
check(
|
237
|
+
check(enqueued_jobs - original_enqueued_jobs)
|
212
238
|
end
|
213
239
|
|
214
240
|
def does_not_match?(proc)
|
@@ -4,6 +4,7 @@
|
|
4
4
|
require "rspec/mocks/argument_matchers"
|
5
5
|
require "rspec/rails/matchers/active_job"
|
6
6
|
|
7
|
+
# rubocop: disable Metrics/ClassLength
|
7
8
|
module RSpec
|
8
9
|
module Rails
|
9
10
|
module Matchers
|
@@ -119,9 +120,11 @@ module RSpec
|
|
119
120
|
end
|
120
121
|
|
121
122
|
def mail_job_message(job)
|
122
|
-
|
123
|
+
job_args = deserialize_arguments(job)
|
124
|
+
|
125
|
+
mailer_method = job_args[0..1].join('.')
|
126
|
+
mailer_args = job_args[3..-1]
|
123
127
|
|
124
|
-
mailer_args = job[:args][3..-1]
|
125
128
|
msg_parts = []
|
126
129
|
msg_parts << "with #{mailer_args}" if mailer_args.any?
|
127
130
|
msg_parts << "on queue #{job[:queue]}" if job[:queue] && job[:queue] != 'mailers'
|
@@ -130,18 +133,43 @@ module RSpec
|
|
130
133
|
"#{mailer_method} #{msg_parts.join(', ')}".strip
|
131
134
|
end
|
132
135
|
|
136
|
+
# Ruby 3.1 changed how params were serialized on Rails 6.1
|
137
|
+
# so we override the active job implementation and customize 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
|
+
|
133
160
|
def legacy_mail?(job)
|
134
|
-
job[:job]
|
161
|
+
RSpec::Rails::FeatureCheck.has_action_mailer_legacy_delivery_job? && job[:job] <= ActionMailer::DeliveryJob
|
135
162
|
end
|
136
163
|
|
137
164
|
def parameterized_mail?(job)
|
138
|
-
RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? && job[:job]
|
165
|
+
RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? && job[:job] <= ActionMailer::Parameterized::DeliveryJob
|
139
166
|
end
|
140
167
|
|
141
168
|
def unified_mail?(job)
|
142
|
-
RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? && job[:job]
|
169
|
+
RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? && job[:job] <= ActionMailer::MailDeliveryJob
|
143
170
|
end
|
144
171
|
end
|
172
|
+
|
145
173
|
# @api public
|
146
174
|
# Passes if an email has been enqueued inside block.
|
147
175
|
# May chain with to specify expected arguments.
|
@@ -196,3 +224,4 @@ module RSpec
|
|
196
224
|
end
|
197
225
|
end
|
198
226
|
end
|
227
|
+
# rubocop: enable Metrics/ClassLength
|