Skip to content

Commit

Permalink
add support for recognizing mailer many jobs:
Browse files Browse the repository at this point in the history
- parameterized mailer when RAILS_VERSION >= 5.1
- unified mailer job when RAILS_VERSION >= 6.0
  • Loading branch information
ignatiusreza committed May 15, 2019
1 parent 81d0d60 commit 0cbd5b2
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 24 deletions.
8 changes: 8 additions & 0 deletions lib/rspec/rails/feature_check.rb
Expand Up @@ -38,6 +38,14 @@ def has_action_mailer_show_preview?
::ActionMailer::Base.respond_to?(:show_previews=)
end

def has_action_mailer_parameterized?
has_action_mailer? && defined?(::ActionMailer::Parameterized)
end

def has_action_mailer_unified_delivery?
has_action_mailer? && defined?(::ActionMailer::MailDeliveryJob)
end

def has_action_mailbox?
defined?(::ActionMailbox)
end
Expand Down
7 changes: 5 additions & 2 deletions lib/rspec/rails/matchers/active_job.rb
Expand Up @@ -97,7 +97,7 @@ def supports_block_expectations?

def check(jobs)
@matching_jobs, @unmatching_jobs = jobs.partition do |job|
if arguments_match?(job) && other_attributes_match?(job)
if job_match?(job) && arguments_match?(job) && other_attributes_match?(job)
args = deserialize_arguments(job)
@block.call(*args)
true
Expand Down Expand Up @@ -134,6 +134,10 @@ def base_job_message(job)
end
end

def job_match?(job)
@job ? @job == job[:job] : true
end

def arguments_match?(job)
if @args.any?
deserialized_args = deserialize_arguments(job)
Expand All @@ -151,7 +155,6 @@ def serialized_attributes
{}.tap do |attributes|
attributes[:at] = serialized_at if @at
attributes[:queue] = @queue if @queue
attributes[:job] = @job if @job
end
end

Expand Down
50 changes: 28 additions & 22 deletions lib/rspec/rails/matchers/have_enqueued_mail.rb
Expand Up @@ -14,11 +14,10 @@ class HaveEnqueuedMail < ActiveJob::HaveEnqueuedJob
include RSpec::Mocks::ExampleMethods

def initialize(mailer_class, method_name)
super(mailer_job)
super(nil)
@mailer_class = mailer_class
@method_name = method_name
@mail_args = []
@args = mailer_args
end

def description
Expand All @@ -27,7 +26,7 @@ def description

def with(*args, &block)
@mail_args = args
block.nil? ? super(*mailer_args) : super(*mailer_args, &yield_mail_args(block))
block.nil? ? super : super(&yield_mail_args(block))
end

def matches?(block)
Expand Down Expand Up @@ -67,24 +66,23 @@ def mailer_class_name
@mailer_class ? @mailer_class.name : 'ActionMailer::Base'
end

def mailer_args
if @mail_args.any?
base_mailer_args + @mail_args
elsif @mailer_class && @method_name
mailer_method_arity = @mailer_class.instance_method(@method_name).arity
def job_match?(job)
legacy_mail?(job) || parameterized_mail?(job) || unified_mail?(job)
end

number_of_args = if mailer_method_arity < 0
(mailer_method_arity + 1).abs
else
mailer_method_arity
end
def arguments_match?(job)
@args =
if @mail_args.any?
base_mailer_args + @mail_args
elsif @mailer_class && @method_name
base_mailer_args + [any_args]
elsif @mailer_class
[mailer_class_name, any_args]
else
[]
end

base_mailer_args + Array.new(number_of_args) { anything }
elsif @mailer_class
[mailer_class_name, any_args]
else
[]
end
super(job)
end

def base_mailer_args
Expand All @@ -103,7 +101,7 @@ def check_active_job_adapter

def unmatching_mail_jobs
@unmatching_jobs.select do |job|
job[:job] == mailer_job
job_match?(job)
end
end

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

def mailer_job
ActionMailer::DeliveryJob
def legacy_mail?(job)
job[:job] == ActionMailer::DeliveryJob
end

def parameterized_mail?(job)
RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? && job[:job] == ActionMailer::Parameterized::DeliveryJob
end

def unified_mail?(job)
RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? && job[:job] == ActionMailer::MailDeliveryJob
end
end
# @api public
Expand Down
63 changes: 63 additions & 0 deletions spec/rspec/rails/matchers/have_enqueued_mail_spec.rb
Expand Up @@ -14,6 +14,15 @@ def email_with_optional_args(required_arg, optional_arg = nil); end
class AnotherTestMailer < ActionMailer::Base
def test_email; end
end

if RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery?
class UnifiedMailer < ActionMailer::Base
self.delivery_job = ActionMailer::MailDeliveryJob

def test_email; end
def email_with_args(arg1, arg2); end
end
end
end

RSpec.describe "HaveEnqueuedMail matchers", :skip => !RSpec::Rails::FeatureCheck.has_active_job? do
Expand Down Expand Up @@ -327,5 +336,59 @@ def self.name; "NonMailerJob"; end
expect(second_arg).to eq('noon')
}
end

context 'when parameterized', :skip => !RSpec::Rails::FeatureCheck.has_action_mailer_parameterized? do
it "passes when mailer is parameterized" do
expect {
TestMailer.with('foo' => 'bar').test_email.deliver_later
}.to have_enqueued_mail(TestMailer, :test_email)
end

it "passes when mixing parameterized and non-parameterized emails" do
expect {
TestMailer.with('foo' => 'bar').test_email.deliver_later
TestMailer.email_with_args(1, 2).deliver_later
}.to have_enqueued_mail(TestMailer, :test_email).and have_enqueued_mail(TestMailer, :email_with_args)
end

it "passes with provided argument matchers" do
expect {
TestMailer.with('foo' => 'bar').test_email.deliver_later
}.to have_enqueued_mail(TestMailer, :test_email).with('foo' => 'bar')

expect {
TestMailer.with('foo' => 'bar').email_with_args(1, 2).deliver_later
}.to have_enqueued_mail(TestMailer, :email_with_args).with({ 'foo' => 'bar' }, 1, 2)
end
end

context 'mailer job is unified', :skip => !RSpec::Rails::FeatureCheck.has_action_mailer_unified_delivery? do
it "passes when mailer is parameterized" do
expect {
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
}.to have_enqueued_mail(UnifiedMailer, :test_email)
end

it "passes when mixing parameterized and non-parameterized emails" do
expect {
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
UnifiedMailer.email_with_args(1, 2).deliver_later
}.to have_enqueued_mail(UnifiedMailer, :test_email).and have_enqueued_mail(UnifiedMailer, :email_with_args)
end

it "passes with provided argument matchers" do
expect {
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
}.to have_enqueued_mail(UnifiedMailer, :test_email).with(
a_hash_including(:params => { 'foo' => 'bar' })
)

expect {
UnifiedMailer.with('foo' => 'bar').email_with_args(1, 2).deliver_later
}.to have_enqueued_mail(UnifiedMailer, :email_with_args).with(
a_hash_including(:params => { 'foo' => 'bar' }, :args => [1, 2])
)
end
end
end
end

0 comments on commit 0cbd5b2

Please sign in to comment.