Skip to content

Commit 2a95ded

Browse files
authored
Merge pull request #2125 from ignatiusreza/mailer-job
add support for recognizing mailer many jobs:
2 parents ac64a6b + 0cbd5b2 commit 2a95ded

File tree

4 files changed

+104
-24
lines changed

4 files changed

+104
-24
lines changed

lib/rspec/rails/feature_check.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ def has_action_mailer_show_preview?
4242
::ActionMailer::Base.respond_to?(:show_previews=)
4343
end
4444

45+
def has_action_mailer_parameterized?
46+
has_action_mailer? && defined?(::ActionMailer::Parameterized)
47+
end
48+
49+
def has_action_mailer_unified_delivery?
50+
has_action_mailer? && defined?(::ActionMailer::MailDeliveryJob)
51+
end
52+
4553
def has_action_mailbox?
4654
defined?(::ActionMailbox)
4755
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: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ 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
2221
end
2322

2423
def description
@@ -27,7 +26,7 @@ def description
2726

2827
def with(*args, &block)
2928
@mail_args = args
30-
block.nil? ? super(*mailer_args) : super(*mailer_args, &yield_mail_args(block))
29+
block.nil? ? super : super(&yield_mail_args(block))
3130
end
3231

3332
def matches?(block)
@@ -67,24 +66,23 @@ def mailer_class_name
6766
@mailer_class ? @mailer_class.name : 'ActionMailer::Base'
6867
end
6968

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
69+
def job_match?(job)
70+
legacy_mail?(job) || parameterized_mail?(job) || unified_mail?(job)
71+
end
7572

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

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
85+
super(job)
8886
end
8987

9088
def base_mailer_args
@@ -103,7 +101,7 @@ def check_active_job_adapter
103101

104102
def unmatching_mail_jobs
105103
@unmatching_jobs.select do |job|
106-
job[:job] == mailer_job
104+
job_match?(job)
107105
end
108106
end
109107

@@ -129,8 +127,16 @@ def mail_job_message(job)
129127
"#{mailer_method} #{msg_parts.join(', ')}".strip
130128
end
131129

132-
def mailer_job
133-
ActionMailer::DeliveryJob
130+
def legacy_mail?(job)
131+
job[:job] == ActionMailer::DeliveryJob
132+
end
133+
134+
def parameterized_mail?(job)
135+
RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? && job[:job] == ActionMailer::Parameterized::DeliveryJob
136+
end
137+
138+
def unified_mail?(job)
139+
RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? && job[:job] == ActionMailer::MailDeliveryJob
134140
end
135141
end
136142
# @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)