Permalink
Browse files

A #have_sent_email matcher

  • Loading branch information...
1 parent 389c236 commit 8c773df567f2459cd2e8aa9ca8d521b0aca8caf1 @mike-burns mike-burns committed Jun 8, 2010
@@ -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
@@ -25,6 +25,8 @@ def assert_sent_email
end
end
+ # should have_sent_email.with_subject(/hi there/).to('none@none.com').from('noreply@example.com').with_body(/reach out/)
+
# Asserts that no ActionMailer mails were delivered
#
# assert_did_not_send_email
@@ -0,0 +1,9 @@
+require 'shoulda/action_mailer/matchers/have_sent_email'
+
+module Shoulda # :nodoc:
+ module ActiveRecord # :nodoc:
+ # = blah blah blah
@seban

seban Jun 10, 2010

Helpful comment :)

+ module Matchers
+ end
+ end
+end
@@ -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
+
View
@@ -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
@@ -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 "do-not-reply@example.com"
+ recipients "myself@me.com"
+ 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('do-not-reply@example.com'), @mail
+ assert_rejects have_sent_email.from('you@example.com'), @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('myself@me.com'), @mail
+ assert_rejects have_sent_email.to('you@example.com'), @mail
+ end
+
+ should "chain" do
+ assert_accepts have_sent_email.with_subject(/spam/).from('do-not-reply@example.com').with_body(/spam/).to('myself@me.com'), @mail
+ assert_rejects have_sent_email.with_subject(/ham/).from('you@example.com').with_body(/ham/).to('them@example.com'), @mail
+ end
+ end
+end
View
@@ -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$/

0 comments on commit 8c773df

Please sign in to comment.