Skip to content

Commit

Permalink
allow partial args when using have_enqueued_mail (#2118)
Browse files Browse the repository at this point in the history
this provide parity with have_enqueued_job with partial arguments
which would be useful especially in negated case where
we want to make sure that absolutely no emails are enqueued
  • Loading branch information
JonRowe committed May 14, 2019
2 parents f970835 + 6d3e66b commit 780b3d2
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
26 changes: 21 additions & 5 deletions lib/rspec/rails/matchers/have_enqueued_mail.rb
Expand Up @@ -22,7 +22,7 @@ def initialize(mailer_class, method_name)
end

def description
"enqueues #{@mailer_class.name}.#{@method_name}"
"enqueues #{mailer_class_name}.#{@method_name}"
end

def with(*args, &block)
Expand Down Expand Up @@ -50,7 +50,7 @@ def failure_message_when_negated
private

def base_message
"#{@mailer_class.name}.#{@method_name}".tap do |msg|
[mailer_class_name, @method_name].compact.join('.').tap do |msg|
msg << " #{expected_count_message}"
msg << " with #{@mail_args}," if @mail_args.any?
msg << " on queue #{@queue}," if @queue
Expand All @@ -63,10 +63,14 @@ def expected_count_message
"#{message_expectation_modifier} #{@expected_number} #{@expected_number == 1 ? 'time' : 'times'}"
end

def mailer_class_name
@mailer_class ? @mailer_class.name : 'ActionMailer::Base'
end

def mailer_args
if @mail_args.any?
base_mailer_args + @mail_args
else
elsif @mailer_class && @method_name
mailer_method_arity = @mailer_class.instance_method(@method_name).arity

number_of_args = if mailer_method_arity < 0
Expand All @@ -76,11 +80,15 @@ def mailer_args
end

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

def base_mailer_args
[@mailer_class.name, @method_name.to_s, MAILER_JOB_METHOD]
[mailer_class_name, @method_name.to_s, MAILER_JOB_METHOD]
end

def yield_mail_args(block)
Expand Down Expand Up @@ -135,6 +143,14 @@ def mailer_job
# @example
# expect {
# MyMailer.welcome(user).deliver_later
# }.to have_enqueued_mail
#
# expect {
# MyMailer.welcome(user).deliver_later
# }.to have_enqueued_mail(MyMailer)
#
# expect {
# MyMailer.welcome(user).deliver_later
# }.to have_enqueued_mail(MyMailer, :welcome)
#
# # Using alias
Expand Down Expand Up @@ -162,7 +178,7 @@ def mailer_job
# expect {
# MyMailer.welcome(user).deliver_later(queue: :urgent_mail)
# }.to have_enqueued_mail(MyMailer, :welcome).on_queue(:urgent_mail)
def have_enqueued_mail(mailer_class, mail_method_name)
def have_enqueued_mail(mailer_class = nil, mail_method_name = nil)
HaveEnqueuedMail.new(mailer_class, mail_method_name)
end
alias_method :have_enqueued_email, :have_enqueued_mail
Expand Down
44 changes: 44 additions & 0 deletions spec/rspec/rails/matchers/have_enqueued_mail_spec.rb
Expand Up @@ -10,6 +10,10 @@ def test_email; end
def email_with_args(arg1, arg2); end
def email_with_optional_args(required_arg, optional_arg = nil); end
end

class AnotherTestMailer < ActionMailer::Base
def test_email; end
end
end

RSpec.describe "HaveEnqueuedMail matchers", :skip => !RSpec::Rails::FeatureCheck.has_active_job? do
Expand Down Expand Up @@ -53,6 +57,34 @@ def email_with_optional_args(required_arg, optional_arg = nil); end
expect { }.not_to have_enqueued_mail(TestMailer, :test_email)
end

it "passes when given 0 arguments" do
expect {
TestMailer.test_email.deliver_later
}.to have_enqueued_email
end

it "passes when negated with 0 arguments" do
expect { }.not_to have_enqueued_email
end

it "passes when only given mailer argument" do
expect {
TestMailer.test_email.deliver_later
}.to have_enqueued_email(TestMailer)
end

it "passes when negated with only mailer arguments" do
expect { }.not_to have_enqueued_email(TestMailer)
end

it "ensure that the right mailer is enqueued" do
expect {
expect {
AnotherTestMailer.test_email.deliver_later
}.to have_enqueued_mail(TestMailer)
}.to raise_error(/expected to enqueue TestMailer exactly 1 time but enqueued 0/)
end

it "counts only emails enqueued in the block" do
TestMailer.test_email.deliver_later

Expand Down Expand Up @@ -126,6 +158,18 @@ def email_with_optional_args(required_arg, optional_arg = nil); end
}.to have_enqueued_mail(TestMailer, :test_email).at_most(:twice)
end

it "generates a failure message when given 0 argument" do
expect {
expect { }.to have_enqueued_mail.at_least(:once)
}.to raise_error(/expected to enqueue ActionMailer::Base at least 1 time but enqueued 0/)
end

it "generates a failure message when given only mailer argument" do
expect {
expect { }.to have_enqueued_mail(TestMailer).at_least(:once)
}.to raise_error(/expected to enqueue TestMailer at least 1 time but enqueued 0/)
end

it "generates a failure message with at least hint" do
expect {
expect { }.to have_enqueued_mail(TestMailer, :test_email).at_least(:once)
Expand Down

0 comments on commit 780b3d2

Please sign in to comment.