rspec-rails 4.0.0 → 6.1.2
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.
- 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
|