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

Fix parameter matching with mail delivery job and ActionMailer::MailDeliveryJob #2516

Closed
Closed
Show file tree
Hide file tree
Changes from 2 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
37 changes: 37 additions & 0 deletions features/matchers/have_enqueued_mail_matcher.feature
Expand Up @@ -38,3 +38,40 @@ Feature: have_enqueued_mail matcher
"""
When I run `rspec spec/mailers/user_mailer_spec.rb`
Then the examples should all pass

Scenario: Checking mailer arguments
Given a file named "app/mailers/my_mailer.rb" with:
"""ruby
class MyMailer < ApplicationMailer

def signup(user = nil)
@user = user

mail to: "to@example.org"
end
end
"""
Given a file named "spec/mailers/my_mailer_spec.rb" with:
"""ruby
require "rails_helper"

RSpec.describe MyMailer do
it "matches with enqueued mailer" do
ActiveJob::Base.queue_adapter = :test
# Works with plain args
expect {
MyMailer.signup('user').deliver_later
}.to have_enqueued_mail(MyMailer, :signup).with('user')
# Works with named parameters
expect {
MyMailer.with('foo' => 'bar').signup.deliver_later
pirj marked this conversation as resolved.
Show resolved Hide resolved
}.to have_enqueued_mail(MyMailer, :signup).with('foo' => 'bar')
# Works also with both, named parameters match first argument
pirj marked this conversation as resolved.
Show resolved Hide resolved
expect {
MyMailer.with('foo' => 'bar').signup('user').deliver_later
pirj marked this conversation as resolved.
Show resolved Hide resolved
}.to have_enqueued_mail(MyMailer, :signup).with({'foo' => 'bar'}, 'user')
end
end
"""
When I run `rspec spec/mailers/my_mailer_spec.rb`
Then the examples should all pass
15 changes: 13 additions & 2 deletions lib/rspec/rails/matchers/have_enqueued_mail.rb
Expand Up @@ -76,7 +76,7 @@ def job_match?(job)
def arguments_match?(job)
@args =
if @mail_args.any?
base_mailer_args + @mail_args
base_mailer_args + process_arguments(job, @mail_args)
elsif @mailer_class && @method_name
base_mailer_args + [any_args]
elsif @mailer_class
Expand All @@ -88,6 +88,18 @@ def arguments_match?(job)
super(job)
end

def process_arguments(job, given_mail_args)
if job[:job] == ActionMailer::MailDeliveryJob
pirj marked this conversation as resolved.
Show resolved Hide resolved
if given_mail_args.first.is_a?(Hash) && job[:args][3]['params'].present?
pirj marked this conversation as resolved.
Show resolved Hide resolved
[hash_including(params: given_mail_args[0], args: given_mail_args.drop(1))]
else
[hash_including(args: given_mail_args)]
end
else
pirj marked this conversation as resolved.
Show resolved Hide resolved
given_mail_args
end
end

def base_mailer_args
[mailer_class_name, @method_name.to_s, MAILER_JOB_METHOD]
end
Expand Down Expand Up @@ -120,7 +132,6 @@ def unmatching_mail_jobs_message

def mail_job_message(job)
mailer_method = job[:args][0..1].join('.')

mailer_args = job[:args][3..-1]
msg_parts = []
msg_parts << "with #{mailer_args}" if mailer_args.any?
Expand Down
18 changes: 11 additions & 7 deletions spec/rspec/rails/matchers/have_enqueued_mail_spec.rb
Expand Up @@ -393,18 +393,22 @@ def self.name; "NonMailerJob"; end
}.to have_enqueued_mail(UnifiedMailer, :test_email).and have_enqueued_mail(UnifiedMailer, :email_with_args)
end

it "passes with provided argument matchers" do
it "matches arguments when mailer has only args" do
expect {
UnifiedMailer.email_with_args(1, 2).deliver_later
}.to have_enqueued_mail(UnifiedMailer, :email_with_args).with(1, 2)
end

it "matches arguments when mailer is parameterized" do
expect {
UnifiedMailer.with('foo' => 'bar').test_email.deliver_later
}.to have_enqueued_mail(UnifiedMailer, :test_email).with(
a_hash_including(params: {'foo' => 'bar'})
)
}.to have_enqueued_mail(UnifiedMailer, :test_email).with('foo' => 'bar')
end

it "matches arguments when mixing parameterized and non-parameterized emails" do
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])
)
}.to have_enqueued_mail(UnifiedMailer, :email_with_args).with({'foo' => 'bar'}, 1, 2)
end

it "passes when using a mailer with `delivery_job` set to a sub class of `ActionMailer::DeliveryJob`" do
Expand Down