Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for recognizing mailer many jobs: #2125

Merged
merged 1 commit into from May 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
benoittgt marked this conversation as resolved.
Show resolved Hide resolved
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