Skip to content

Commit c978f7b

Browse files
committed
add support for recognizing mailer many jobs:
- parameterized mailer when RAILS_VERSION >= 5.1 - unified mailer job when RAILS_VERSION >= 6.0
1 parent 81d0d60 commit c978f7b

File tree

4 files changed

+105
-24
lines changed

4 files changed

+105
-24
lines changed

lib/rspec/rails/feature_check.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ def has_action_mailer_show_preview?
3838
::ActionMailer::Base.respond_to?(:show_previews=)
3939
end
4040

41+
def has_action_mailer_parameterized?
42+
has_action_mailer? && defined?(::ActionMailer::Parameterized)
43+
end
44+
45+
def has_action_mailer_unified_delivery?
46+
has_action_mailer? && defined?(::ActionMailer::MailDeliveryJob)
47+
end
48+
4149
def has_action_mailbox?
4250
defined?(::ActionMailbox)
4351
end

lib/rspec/rails/matchers/active_job.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def supports_block_expectations?
9797

9898
def check(jobs)
9999
@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) && other_attributes_match?(job)
101101
args = deserialize_arguments(job)
102102
@block.call(*args)
103103
true
@@ -134,6 +134,10 @@ def base_job_message(job)
134134
end
135135
end
136136

137+
def job_match?(job)
138+
@job ? @job == job[:job] : true
139+
end
140+
137141
def arguments_match?(job)
138142
if @args.any?
139143
deserialized_args = deserialize_arguments(job)
@@ -151,7 +155,6 @@ def serialized_attributes
151155
{}.tap do |attributes|
152156
attributes[:at] = serialized_at if @at
153157
attributes[:queue] = @queue if @queue
154-
attributes[:job] = @job if @job
155158
end
156159
end
157160

lib/rspec/rails/matchers/have_enqueued_mail.rb

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ class HaveEnqueuedMail < ActiveJob::HaveEnqueuedJob
1414
include RSpec::Mocks::ExampleMethods
1515

1616
def initialize(mailer_class, method_name)
17-
super(mailer_job)
17+
super(nil)
1818
@mailer_class = mailer_class
1919
@method_name = method_name
2020
@mail_args = []
21-
@args = mailer_args
21+
@args = []
2222
end
2323

2424
def description
@@ -27,7 +27,7 @@ def description
2727

2828
def with(*args, &block)
2929
@mail_args = args
30-
block.nil? ? super(*mailer_args) : super(*mailer_args, &yield_mail_args(block))
30+
block.nil? ? super : super(&yield_mail_args(block))
3131
end
3232

3333
def matches?(block)
@@ -67,24 +67,23 @@ def mailer_class_name
6767
@mailer_class ? @mailer_class.name : 'ActionMailer::Base'
6868
end
6969

70-
def mailer_args
71-
if @mail_args.any?
72-
base_mailer_args + @mail_args
73-
elsif @mailer_class && @method_name
74-
mailer_method_arity = @mailer_class.instance_method(@method_name).arity
70+
def job_match?(job)
71+
legacy_mail?(job) || parameterized_mail?(job) || unified_mail?(job)
72+
end
7573

76-
number_of_args = if mailer_method_arity < 0
77-
(mailer_method_arity + 1).abs
78-
else
79-
mailer_method_arity
80-
end
74+
def arguments_match?(job)
75+
@args =
76+
if @mail_args.any?
77+
base_mailer_args + @mail_args
78+
elsif @mailer_class && @method_name
79+
base_mailer_args + [any_args]
80+
elsif @mailer_class
81+
[mailer_class_name, any_args]
82+
else
83+
[]
84+
end
8185

82-
base_mailer_args + Array.new(number_of_args) { anything }
83-
elsif @mailer_class
84-
[mailer_class_name, any_args]
85-
else
86-
[]
87-
end
86+
super(job)
8887
end
8988

9089
def base_mailer_args
@@ -103,7 +102,7 @@ def check_active_job_adapter
103102

104103
def unmatching_mail_jobs
105104
@unmatching_jobs.select do |job|
106-
job[:job] == mailer_job
105+
job_match?(job)
107106
end
108107
end
109108

@@ -129,8 +128,16 @@ def mail_job_message(job)
129128
"#{mailer_method} #{msg_parts.join(', ')}".strip
130129
end
131130

132-
def mailer_job
133-
ActionMailer::DeliveryJob
131+
def legacy_mail?(job)
132+
job[:job] == ActionMailer::DeliveryJob
133+
end
134+
135+
def parameterized_mail?(job)
136+
RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? && job[:job] == ActionMailer::Parameterized::DeliveryJob
137+
end
138+
139+
def unified_mail?(job)
140+
RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? && job[:job] == ActionMailer::MailDeliveryJob
134141
end
135142
end
136143
# @api public

spec/rspec/rails/matchers/have_enqueued_mail_spec.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ def email_with_optional_args(required_arg, optional_arg = nil); end
1414
class AnotherTestMailer < ActionMailer::Base
1515
def test_email; end
1616
end
17+
18+
if RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery?
19+
class UnifiedMailer < ActionMailer::Base
20+
self.delivery_job = ActionMailer::MailDeliveryJob
21+
22+
def test_email; end
23+
def email_with_args(arg1, arg2); end
24+
end
25+
end
1726
end
1827

1928
RSpec.describe "HaveEnqueuedMail matchers", :skip => !RSpec::Rails::FeatureCheck.has_active_job? do
@@ -327,5 +336,59 @@ def self.name; "NonMailerJob"; end
327336
expect(second_arg).to eq('noon')
328337
}
329338
end
339+
340+
context 'when parameterized', :skip => !RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? do
341+
it "passes when mailer is parameterized" do
342+
expect {
343+
TestMailer.with('foo' => 'bar').test_email.deliver_later
344+
}.to have_enqueued_mail(TestMailer, :test_email)
345+
end
346+
347+
it "passes when mixing parameterized and non-parameterized emails" do
348+
expect {
349+
TestMailer.with('foo' => 'bar').test_email.deliver_later
350+
TestMailer.email_with_args(1, 2).deliver_later
351+
}.to have_enqueued_mail(TestMailer, :test_email).and have_enqueued_mail(TestMailer, :email_with_args)
352+
end
353+
354+
it "passes with provided argument matchers" do
355+
expect {
356+
TestMailer.with('foo' => 'bar').test_email.deliver_later
357+
}.to have_enqueued_mail(TestMailer, :test_email).with('foo' => 'bar')
358+
359+
expect {
360+
TestMailer.with('foo' => 'bar').email_with_args(1, 2).deliver_later
361+
}.to have_enqueued_mail(TestMailer, :email_with_args).with({ 'foo' => 'bar' }, 1, 2)
362+
end
363+
end
364+
365+
context 'mailer job is unified', :skip => !RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? do
366+
it "passes when mailer is parameterized" do
367+
expect {
368+
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
369+
}.to have_enqueued_mail(UnifiedMailer, :test_email)
370+
end
371+
372+
it "passes when mixing parameterized and non-parameterized emails" do
373+
expect {
374+
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
375+
UnifiedMailer.email_with_args(1, 2).deliver_later
376+
}.to have_enqueued_mail(UnifiedMailer, :test_email).and have_enqueued_mail(UnifiedMailer, :email_with_args)
377+
end
378+
379+
it "passes with provided argument matchers" do
380+
expect {
381+
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
382+
}.to have_enqueued_mail(UnifiedMailer, :test_email).with(
383+
a_hash_including(:params => { 'foo' => 'bar' })
384+
)
385+
386+
expect {
387+
UnifiedMailer.with('foo' => 'bar').email_with_args(1, 2).deliver_later
388+
}.to have_enqueued_mail(UnifiedMailer, :email_with_args).with(
389+
a_hash_including(:params => { 'foo' => 'bar' }, :args => [1, 2])
390+
)
391+
end
392+
end
330393
end
331394
end

0 commit comments

Comments
 (0)