Skip to content

Commit

Permalink
Add block functionality to HaveSentEmailMatcher so instance variables…
Browse files Browse the repository at this point in the history
… can be used
  • Loading branch information
wingrunr21 committed Jun 10, 2011
1 parent 6789b93 commit 6c22247
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 20 deletions.
50 changes: 39 additions & 11 deletions lib/shoulda/matchers/action_mailer/have_sent_email.rb
Expand Up @@ -12,56 +12,74 @@ module ActionMailer # :nodoc:
# from('do-not-reply@example.com').
# with_body(/spam/).
# to('myself@me.com') }
#
# Use values of instance variables
# it {should have_sent_email.to {@user.email} }
def have_sent_email
HaveSentEmailMatcher.new
HaveSentEmailMatcher.new(self)
end

class HaveSentEmailMatcher # :nodoc:

def initialize
def initialize(context)
@context = context
end

def in_context(context)
@context = context
self
end

def with_subject(email_subject)
def with_subject(email_subject = nil, &block)
@email_subject = email_subject
@email_subject_block = block
self
end

def from(sender)
def from(sender = nil, &block)
@sender = sender
@sender_block = block
self
end

def with_body(body)
def with_body(body = nil, &block)
@body = body
@body_block = block
self
end

def to(recipient)
def to(recipient = nil, &block)
@recipient = recipient
@recipient_block = block
self
end

def cc(recipient)
def cc(recipient = nil, &block)
@cc = recipient
@cc_block = block
self
end

def with_cc(recipients)
def with_cc(recipients = nil, &block)
@cc_recipients = recipients
@cc_recipients_block = block
self
end

def bcc(recipient)
def bcc(recipient = nil, &block)
@bcc = recipient
@bcc_block = block
self
end

def with_bcc(recipients)
def with_bcc(recipients = nil, &block)
@bcc_recipients = recipients
@bcc_recipients_block = block
self
end

def matches?(subject)
normalize_blocks
::ActionMailer::Base.deliveries.each do |mail|
@subject_failed = !regexp_or_string_match(mail.subject, @email_subject) if @email_subject
@body_failed = !regexp_or_string_match(mail.body, @body) if @body
Expand Down Expand Up @@ -123,6 +141,17 @@ def anything_failed?
@subject_failed || @body_failed || @sender_failed || @recipient_failed || @cc_failed || @cc_recipients_failed || @bcc_failed || @bcc_recipients_failed
end

def normalize_blocks
@email_subject = @context.instance_eval(&@email_subject_block) if @email_subject_block
@sender = @context.instance_eval(&@sender_block) if @sender_block
@body = @context.instance_eval(&@body_block) if @body_block
@recipient = @context.instance_eval(&@recipient_block) if @recipient_block
@cc = @context.instance_eval(&@cc_block) if @cc_block
@cc_recipients = @context.instance_eval(&@cc_recipients_block) if @cc_recipients_block
@bcc = @context.instance_eval(&@bcc_block) if @bcc_block
@bcc_recipients = @context.instance_eval(&@bcc_recipients_block) if @bcc_recipients_block
end

def regexp_or_string_match(a_string, a_regexp_or_string)
case a_regexp_or_string
when Regexp
Expand Down Expand Up @@ -150,5 +179,4 @@ def match_array_in_array(target_array, match_array)
end
end
end

end
71 changes: 62 additions & 9 deletions spec/shoulda/action_mailer/have_sent_email_spec.rb
@@ -1,14 +1,67 @@
require 'spec_helper'

describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
def add_mail_to_deliveries
::ActionMailer::Base.deliveries << Mailer.the_email
def add_mail_to_deliveries(params = nil)
::ActionMailer::Base.deliveries << Mailer.the_email(params)
end

context "testing with instance variables" do
before do
@info = {
:from => "do-not-reply@example.com",
:to => "myself@me.com",
:cc => ["you@you.com", "joe@bob.com", "hello@goodbye.com"],
:bcc => ["test@example.com", "sam@bob.com", "goodbye@hello.com"],
:subject => "This is spam",
:body => "Every email is spam." }

define_mailer :mailer, [:the_email] do
def the_email(params)
mail params
end
end
add_mail_to_deliveries(@info)
end

after { ::ActionMailer::Base.deliveries.clear }

it "should send an e-mail based on subject" do
should have_sent_email.with_subject{ @info[:subject] }
end

it "should send an e-mail based on recipient" do
should have_sent_email.to{ @info[:to] }
end

it "should send an e-mail based on sender" do
should have_sent_email.from{ @info[:from] }
end

it "should send an e-mail based on cc" do
should have_sent_email.cc{ @info[:cc][0] }
end

it "should send an e-mail based on cc list" do
should have_sent_email.with_cc{ @info[:cc] }
end

it "should send an e-mail based on bcc" do
should have_sent_email.bcc{ @info[:bcc][0] }
end

it "should send an e-mail based on bcc list" do
should have_sent_email.with_bcc{ @info[:bcc] }
end

it "should send an e-mail based on body" do
should have_sent_email.with_body{ @info[:body] }
end
end

context "an email" do
before do
define_mailer :mailer, [:the_email] do
def the_email
def the_email(params)
mail :from => "do-not-reply@example.com",
:to => "myself@me.com",
:subject => "This is spam",
Expand Down Expand Up @@ -56,42 +109,42 @@ def the_email
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email to/
end

it "accepts sent e-mail based on cc string" do
should have_sent_email.cc('joe@bob.com')
matcher = have_sent_email.cc('you@example.com')
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email cc/
end

it "accepts sent-email based on cc regex" do
should have_sent_email.cc(/@bob\.com/)
matcher = have_sent_email.cc(/us@/)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email cc/
end

it "accepts sent e-mail based on cc list" do
should have_sent_email.with_cc(['you@you.com', 'joe@bob.com'])
matcher = have_sent_email.with_cc(['you@example.com'])
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email with cc/
end

it "accepts sent e-mail based on bcc string" do
should have_sent_email.bcc("goodbye@hello.com")
matcher = have_sent_email.bcc("test@hello.com")
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email bcc/
end

it "accepts sent e-mail based on bcc regex" do
should have_sent_email.bcc(/@example\.com/)
matcher = have_sent_email.bcc(/you@/)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email bcc/
end

it "accepts sent e-mail based on bcc list" do
should have_sent_email.with_bcc(['sam@bob.com', 'test@example.com'])
matcher = have_sent_email.with_bcc(['you@you.com', 'joe@bob.com'])
Expand Down

0 comments on commit 6c22247

Please sign in to comment.