Skip to content

Commit 16a6605

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 f970835 commit 16a6605

File tree

4 files changed

+104
-19
lines changed

4 files changed

+104
-19
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: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,21 @@ module Matchers
99
# @private
1010
# @see RSpec::Rails::Matchers#have_enqueued_mail
1111
class HaveEnqueuedMail < ActiveJob::HaveEnqueuedJob
12+
MAILER_JOBS = [
13+
:legacy_mail?,
14+
:parameterized_mail?,
15+
:unified_mail?,
16+
].reject(&:blank?)
1217
MAILER_JOB_METHOD = 'deliver_now'.freeze
1318

1419
include RSpec::Mocks::ExampleMethods
1520

1621
def initialize(mailer_class, method_name)
17-
super(mailer_job)
22+
super(nil)
1823
@mailer_class = mailer_class
1924
@method_name = method_name
2025
@mail_args = []
21-
@args = mailer_args
26+
@args = []
2227
end
2328

2429
def description
@@ -27,7 +32,7 @@ def description
2732

2833
def with(*args, &block)
2934
@mail_args = args
30-
block.nil? ? super(*mailer_args) : super(*mailer_args, &yield_mail_args(block))
35+
block.nil? ? super : super(&yield_mail_args(block))
3136
end
3237

3338
def matches?(block)
@@ -63,20 +68,18 @@ def expected_count_message
6368
"#{message_expectation_modifier} #{@expected_number} #{@expected_number == 1 ? 'time' : 'times'}"
6469
end
6570

66-
def mailer_args
71+
def job_match?(job)
72+
MAILER_JOBS.any? { |mailer_job| send(mailer_job, job) }
73+
end
74+
75+
def arguments_match?(job)
6776
if @mail_args.any?
68-
base_mailer_args + @mail_args
77+
@args = base_mailer_args + @mail_args
6978
else
70-
mailer_method_arity = @mailer_class.instance_method(@method_name).arity
71-
72-
number_of_args = if mailer_method_arity < 0
73-
(mailer_method_arity + 1).abs
74-
else
75-
mailer_method_arity
76-
end
77-
78-
base_mailer_args + Array.new(number_of_args) { anything }
79+
@args = base_mailer_args + [any_args]
7980
end
81+
82+
super(job)
8083
end
8184

8285
def base_mailer_args
@@ -95,7 +98,7 @@ def check_active_job_adapter
9598

9699
def unmatching_mail_jobs
97100
@unmatching_jobs.select do |job|
98-
job[:job] == mailer_job
101+
job_match?(job)
99102
end
100103
end
101104

@@ -121,8 +124,16 @@ def mail_job_message(job)
121124
"#{mailer_method} #{msg_parts.join(', ')}".strip
122125
end
123126

124-
def mailer_job
125-
ActionMailer::DeliveryJob
127+
def legacy_mail?(job)
128+
job[:job] == ActionMailer::DeliveryJob
129+
end
130+
131+
def parameterized_mail?(job)
132+
RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? && job[:job] == ActionMailer::Parameterized::DeliveryJob
133+
end
134+
135+
def unified_mail?(job)
136+
RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? && job[:job] == ActionMailer::MailDeliveryJob
126137
end
127138
end
128139
# @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
@@ -10,6 +10,15 @@ def test_email; end
1010
def email_with_args(arg1, arg2); end
1111
def email_with_optional_args(required_arg, optional_arg = nil); end
1212
end
13+
14+
if RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery?
15+
class UnifiedMailer < ActionMailer::Base
16+
self.delivery_job = ActionMailer::MailDeliveryJob
17+
18+
def test_email; end
19+
def email_with_args(arg1, arg2); end
20+
end
21+
end
1322
end
1423

1524
RSpec.describe "HaveEnqueuedMail matchers", :skip => !RSpec::Rails::FeatureCheck.has_active_job? do
@@ -283,5 +292,59 @@ def self.name; "NonMailerJob"; end
283292
expect(second_arg).to eq('noon')
284293
}
285294
end
295+
296+
context 'when parameterized', :skip => !RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? do
297+
it "passes when mailer is parameterized" do
298+
expect {
299+
TestMailer.with('foo' => 'bar').test_email.deliver_later
300+
}.to have_enqueued_mail(TestMailer, :test_email)
301+
end
302+
303+
it "passes when mixing parameterized and non-parameterized emails" do
304+
expect {
305+
TestMailer.with('foo' => 'bar').test_email.deliver_later
306+
TestMailer.email_with_args(1, 2).deliver_later
307+
}.to have_enqueued_mail(TestMailer, :test_email).and have_enqueued_mail(TestMailer, :email_with_args)
308+
end
309+
310+
it "passes with provided argument matchers" do
311+
expect {
312+
TestMailer.with('foo' => 'bar').test_email.deliver_later
313+
}.to have_enqueued_mail(TestMailer, :test_email).with('foo' => 'bar')
314+
315+
expect {
316+
TestMailer.with('foo' => 'bar').email_with_args(1, 2).deliver_later
317+
}.to have_enqueued_mail(TestMailer, :email_with_args).with({ 'foo' => 'bar' }, 1, 2)
318+
end
319+
end
320+
321+
context 'mailer job is unified', :skip => !RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? do
322+
it "passes when mailer is parameterized" do
323+
expect {
324+
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
325+
}.to have_enqueued_mail(UnifiedMailer, :test_email)
326+
end
327+
328+
it "passes when mixing parameterized and non-parameterized emails" do
329+
expect {
330+
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
331+
UnifiedMailer.email_with_args(1, 2).deliver_later
332+
}.to have_enqueued_mail(UnifiedMailer, :test_email).and have_enqueued_mail(UnifiedMailer, :email_with_args)
333+
end
334+
335+
it "passes with provided argument matchers" do
336+
expect {
337+
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
338+
}.to have_enqueued_mail(UnifiedMailer, :test_email).with(
339+
a_hash_including(:params => { 'foo' => 'bar' })
340+
)
341+
342+
expect {
343+
UnifiedMailer.with('foo' => 'bar').email_with_args(1, 2).deliver_later
344+
}.to have_enqueued_mail(UnifiedMailer, :email_with_args).with(
345+
a_hash_including(:params => { 'foo' => 'bar' }, :args => [1, 2])
346+
)
347+
end
348+
end
286349
end
287350
end

0 commit comments

Comments
 (0)