Skip to content

Commit

Permalink
A #have_sent_email matcher
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-burns committed Jun 8, 2010
1 parent 389c236 commit 8c773df
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/shoulda/action_mailer.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
require 'shoulda'
require 'shoulda/action_mailer/assertions'
require 'shoulda/action_mailer/matchers'

module Test # :nodoc: all
module Unit
class TestCase
include Shoulda::ActionMailer::Assertions
include Shoulda::ActionMailer::Matchers
end
end
end
2 changes: 2 additions & 0 deletions lib/shoulda/action_mailer/assertions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ def assert_sent_email
end
end

# should have_sent_email.with_subject(/hi there/).to('[email protected]').from('[email protected]').with_body(/reach out/)

# Asserts that no ActionMailer mails were delivered
#
# assert_did_not_send_email
Expand Down
9 changes: 9 additions & 0 deletions lib/shoulda/action_mailer/matchers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'shoulda/action_mailer/matchers/have_sent_email'

module Shoulda # :nodoc:
module ActiveRecord # :nodoc:
# = blah blah blah
module Matchers
end
end
end
107 changes: 107 additions & 0 deletions lib/shoulda/action_mailer/matchers/have_sent_email.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
module Shoulda # :nodoc:
module ActionMailer # :nodoc:
module Matchers

def have_sent_email
HaveSentEmailMatcher.new
end

class HaveSentEmailMatcher # :nodoc:

def initialize
end

def with_subject(email_subject)
@email_subject = email_subject
self
end

def from(sender)
@sender = sender
self
end

def with_body(body)
@body = body
self
end

def to(recipient)
@recipient = recipient
self
end

def matches?(subject)
@mail = subject
@subject_failed = !regexp_or_string_match(@mail.subject, @email_subject) if @email_subject
@body_failed = !regexp_or_string_match(@mail.body, @body) if @body
@sender_failed = !regexp_or_string_match_in_array(@mail.from, @sender) if @sender
@recipient_failed = !regexp_or_string_match_in_array(@mail.to, @recipient) if @recipient

!anything_failed?
end

def failure_message
msg = "expected a sent email"
msg += " with subject #{@email_subject.inspect}" if @subject_failed
msg += " with body #{@body.inspect}" if @body_failed
msg += " from #{@sender.inspect}" if @sender_failed
msg += " to #{@recipient.inspect}" if @recipient_failed
if anything_failed?
msg += " but got"
msg += " the subject #{@mail.subject.inspect}" if @subject_failed
msg += " the body #{@mail.body.inspect}" if @body_failed
msg += " from #{@mail.from.inspect}" if @sender_failed
msg += " to #{@mail.to.inspect}" if @recipient_failed
end
msg
end

def negative_failure_message
msg = "expected no sent email"
msg += " with subject #{@email_subject.inspect}" if @subject_failed
msg += " with body #{@body.inspect}" if @body_failed
msg += " from #{@sender.inspect}" if @sender_failed
msg += " to #{@recipient.inspect}" if @recipient_failed
if anything_failed?
msg += " but got"
msg += " the subject #{@mail.subject.inspect}" if @subject_failed
msg += " the body #{@mail.body.inspect}" if @body_failed
msg += " from #{@mail.from.inspect}" if @sender_failed
msg += " to #{@mail.to.inspect}" if @recipient_failed
end
msg
end

def description
"send an email"
end

private

def anything_failed?
@subject_failed || @body_failed || @sender_failed || @recipient_failed
end

def regexp_or_string_match(a_string, a_regexp_or_string)
case a_regexp_or_string
when Regexp
a_string =~ a_regexp_or_string
when String
a_string == a_regexp_or_string
end
end

def regexp_or_string_match_in_array(an_array, a_regexp_or_string)
case a_regexp_or_string
when Regexp
an_array.detect{|e| e =~ a_regexp_or_string}.any?
when String
an_array.include?(a_regexp_or_string)
end
end
end
end
end
end

2 changes: 2 additions & 0 deletions lib/shoulda/rspec.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
require 'shoulda/active_record/matchers'
require 'shoulda/action_controller/matchers'
require 'shoulda/action_mailer/matchers'
require 'active_support/test_case'

# :enddoc:
module ActiveSupport
class TestCase
include Shoulda::ActiveRecord::Matchers
include Shoulda::ActionController::Matchers
include Shoulda::ActionMailer::Matchers
end
end
42 changes: 42 additions & 0 deletions test/matchers/action_mailer/have_sent_email_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')

class HaveSentEmailTest < ActiveSupport::TestCase # :nodoc:
context "an email" do
setup do
define_mailer :mailer, [:the_email] do
def the_email
from "[email protected]"
recipients "[email protected]"
subject "This is spam"
body :body => "Every email is spam."
end
end
@mail = Mailer.create_the_email
end

should "accept based on the subject" do
assert_accepts have_sent_email.with_subject(/is spam$/), @mail
assert_rejects have_sent_email.with_subject(/totally safe/), @mail
end

should "accept based on the sender" do
assert_accepts have_sent_email.from('[email protected]'), @mail
assert_rejects have_sent_email.from('[email protected]'), @mail
end

should "accept based on the body" do
assert_accepts have_sent_email.with_body(/is spam\./), @mail
assert_rejects have_sent_email.with_body(/totally safe/), @mail
end

should "accept baed on the recipienct" do
assert_accepts have_sent_email.to('[email protected]'), @mail
assert_rejects have_sent_email.to('[email protected]'), @mail
end

should "chain" do
assert_accepts have_sent_email.with_subject(/spam/).from('[email protected]').with_body(/spam/).to('[email protected]'), @mail
assert_rejects have_sent_email.with_subject(/ham/).from('[email protected]').with_body(/ham/).to('[email protected]'), @mail
end
end
end
8 changes: 8 additions & 0 deletions test/model_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ def define_model(name, columns = {}, &block)
define_model_class(class_name, &block)
end

def define_mailer(name, paths, &block)
class_name = name.to_s.pluralize.classify
klass = define_constant(class_name, ActionMailer::Base, &block)

paths.each {|path| create_view("#{name}/#{path}", "<%= @body %>")}
klass.template_root = TMP_VIEW_PATH
end

def define_controller(class_name, &block)
class_name = class_name.to_s
class_name << 'Controller' unless class_name =~ /Controller$/
Expand Down

0 comments on commit 8c773df

Please sign in to comment.