Skip to content

Commit 34c6391

Browse files
petergoldsteinfabnmhenrixonpirj
committed
Fix arguments for have_enqueued_mail matcher
Add additional logic to the ActionMailer argument parsing to accomodate for differences under Ruby 3.1/Rails 6.1 Co-authored-by: Fabio Napoleoni <[email protected]> Co-authored-by: Mikael Henriksson <[email protected]> Co-authored-by: Phil Pirozhkov <[email protected]>
1 parent b49cfc1 commit 34c6391

File tree

4 files changed

+68
-14
lines changed

4 files changed

+68
-14
lines changed

‎.rubocop_todo.yml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@ Layout/LineLength:
99
# Over time we'd like to get this down, but this is what we're at now.
1010
Metrics/MethodLength:
1111
Max: 43# default: 10
12+
13+
Metrics/ClassLength:
14+
Exclude:
15+
- lib/rspec/rails/matchers/have_enqueued_mail.rb

‎lib/rspec/rails/feature_check.rb‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@ def has_action_mailer_unified_delivery?
3535
has_action_mailer? && defined?(::ActionMailer::MailDeliveryJob)
3636
end
3737

38+
defhas_action_mailer_legacy_delivery_job?
39+
defined?(ActionMailer::DeliveryJob)
40+
end
41+
3842
defhas_action_mailbox?
3943
defined?(::ActionMailbox)
4044
end
4145

46+
defruby_3_1?
47+
RUBY_VERSION >= "3.1"
48+
end
49+
4250
deftype_metatag(type)
4351
"type: :#{type}"
4452
end

‎lib/rspec/rails/matchers/have_enqueued_mail.rb‎

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def job_match?(job)
7676
defarguments_match?(job)
7777
@args=
7878
if@mail_args.any?
79-
base_mailer_args + @mail_args
79+
base_mailer_args + process_arguments(job,@mail_args)
8080
elsif@mailer_class && @method_name
8181
base_mailer_args + [any_args]
8282
elsif@mailer_class
@@ -88,12 +88,38 @@ def arguments_match?(job)
8888
super(job)
8989
end
9090

91+
defprocess_arguments(job,given_mail_args)
92+
# Old matcher behavior working with all builtin classes but ActionMailer::MailDeliveryJob
93+
returngiven_mail_argsifuse_given_mail_args?(job)
94+
95+
# If matching args starts with a hash and job instance has params match with them
96+
ifgiven_mail_args.first.is_a?(Hash) && job[:args][3]['params'].present?
97+
[hash_including(params: given_mail_args[0],args: given_mail_args.drop(1))]
98+
else
99+
[hash_including(args: given_mail_args)]
100+
end
101+
end
102+
103+
defuse_given_mail_args?(job)
104+
returntrueifFeatureCheck.has_action_mailer_parameterized? && job[:job] <= ActionMailer::Parameterized::DeliveryJob
105+
returnfalseifFeatureCheck.ruby_3_1?
106+
107+
!(FeatureCheck.has_action_mailer_unified_delivery? && job[:job] <= ActionMailer::MailDeliveryJob)
108+
end
109+
91110
defbase_mailer_args
92111
[mailer_class_name,@method_name.to_s,MAILER_JOB_METHOD]
93112
end
94113

95114
defyield_mail_args(block)
96-
proc{ |*job_args| block.call(*(job_args - base_mailer_args))}
115+
procdo |*job_args|
116+
mailer_args=job_args - base_mailer_args
117+
ifmailer_args.first.is_a?(Hash)
118+
block.call(*mailer_args.first[:args])
119+
else
120+
block.call(*mailer_args)
121+
end
122+
end
97123
end
98124

99125
defcheck_active_job_adapter
@@ -120,18 +146,25 @@ def unmatching_mail_jobs_message
120146

121147
defmail_job_message(job)
122148
mailer_method=job[:args][0..1].join('.')
123-
124-
mailer_args=job[:args][3..-1]
149+
mailer_args=deserialize_arguments(job)[3..-1]
150+
mailer_args=mailer_args.first[:args]ifunified_mail?(job)
125151
msg_parts=[]
126-
msg_parts << "with #{mailer_args}"ifmailer_args.any?
152+
display_args=display_mailer_args(mailer_args)
153+
msg_parts << "with #{display_args}"ifdisplay_args.any?
127154
msg_parts << "on queue #{job[:queue]}"ifjob[:queue] && job[:queue] != 'mailers'
128155
msg_parts << "at #{Time.at(job[:at])}"ifjob[:at]
129156

130157
"#{mailer_method}#{msg_parts.join(', ')}".strip
131158
end
132159

160+
defdisplay_mailer_args(mailer_args)
161+
returnmailer_argsunlessmailer_args.first.is_a?(Hash) && mailer_args.first.key?(:args)
162+
163+
mailer_args.first[:args]
164+
end
165+
133166
deflegacy_mail?(job)
134-
job[:job] <= ActionMailer::DeliveryJob
167+
RSpec::Rails::FeatureCheck.has_action_mailer_legacy_delivery_job? && job[:job] <= ActionMailer::DeliveryJob
135168
end
136169

137170
defparameterized_mail?(job)

‎spec/rspec/rails/matchers/have_enqueued_mail_spec.rb‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ def test_email; end
2222
defemail_with_args(arg1,arg2);end
2323
end
2424

25-
classDeliveryJobSubClass < ActionMailer::DeliveryJob
25+
ifRSpec::Rails::FeatureCheck.has_action_mailer_legacy_delivery_job?
26+
classDeliveryJobSubClass < ActionMailer::DeliveryJob
27+
end
28+
else
29+
classDeliveryJobSubClass < ActionMailer::MailDeliveryJob
30+
end
2631
end
2732

2833
classUnifiedMailerWithDeliveryJobSubClass < ActionMailer::Base
@@ -393,18 +398,22 @@ def self.name; "NonMailerJob" end
393398
}.tohave_enqueued_mail(UnifiedMailer,:test_email).andhave_enqueued_mail(UnifiedMailer,:email_with_args)
394399
end
395400

396-
it"passes with provided argument matchers"do
401+
it"matches arguments when mailer has only args"do
402+
expect{
403+
UnifiedMailer.email_with_args(1,2).deliver_later
404+
}.tohave_enqueued_mail(UnifiedMailer,:email_with_args).with(1,2)
405+
end
406+
407+
it"matches arguments when mailer is parameterized"do
397408
expect{
398409
UnifiedMailer.with('foo'=>'bar').test_email.deliver_later
399-
}.tohave_enqueued_mail(UnifiedMailer,:test_email).with(
400-
a_hash_including(params: {'foo'=>'bar'})
401-
)
410+
}.tohave_enqueued_mail(UnifiedMailer,:test_email).with('foo'=>'bar')
411+
end
402412

413+
it"matches arguments when mixing parameterized and non-parameterized emails"do
403414
expect{
404415
UnifiedMailer.with('foo'=>'bar').email_with_args(1,2).deliver_later
405-
}.tohave_enqueued_mail(UnifiedMailer,:email_with_args).with(
406-
a_hash_including(params: {'foo'=>'bar'},args: [1,2])
407-
)
416+
}.tohave_enqueued_mail(UnifiedMailer,:email_with_args).with({'foo'=>'bar'},1,2)
408417
end
409418

410419
it"passes when using a mailer with `delivery_job` set to a sub class of `ActionMailer::DeliveryJob`"do

0 commit comments

Comments
(0)