Added a matcher that matches a RE or String on parts matching a given content type

This commit is contained in:
Marcello Barnaba 2011-05-23 23:57:16 +02:00 committed by Jason Morrison
parent b59af15897
commit d468d3b79d
2 changed files with 56 additions and 5 deletions

View File

@ -36,6 +36,12 @@ module Shoulda # :nodoc:
self
end
def with_part(content_type, body)
@parts ||= []
@parts << [/#{Regexp.escape(content_type)}/, body, content_type]
self
end
def to(recipient)
@recipient = recipient
self
@ -49,6 +55,7 @@ module Shoulda # :nodoc:
def matches?(subject)
::ActionMailer::Base.deliveries.each do |mail|
@subject_failed = !regexp_or_string_match(mail.subject, @email_subject) if @email_subject
@parts_failed = !parts_match(mail, @parts) if @parts
@body_failed = !body_match(mail, @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
@ -71,6 +78,9 @@ module Shoulda # :nodoc:
description = "send an email"
description << " with a subject of #{@email_subject.inspect}" if @email_subject
description << " containing #{@body.inspect}" if @body
@parts.each do |_, body, content_type|
description << " having a #{content_type} part containing #{body.inspect}"
end if @parts
description << " from #{@sender.inspect}" if @sender
description << " to #{@recipient.inspect}" if @recipient
description
@ -82,6 +92,9 @@ module Shoulda # :nodoc:
expectation = "sent email"
expectation << " with subject #{@email_subject.inspect}" if @subject_failed
expectation << " with body #{@body.inspect}" if @body_failed
@parts.each do |_, body, content_type|
expectation << " with a #{content_type} part containing #{body}"
end if @parts && @parts_failed
expectation << " from #{@sender.inspect}" if @sender_failed
expectation << " to #{@recipient.inspect}" if @recipient_failed
expectation << " #{!@multipart && 'not '}being multipart" if @multipart_failed
@ -95,7 +108,8 @@ module Shoulda # :nodoc:
end
def anything_failed?
@subject_failed || @body_failed || @sender_failed || @recipient_failed || @multipart_failed
@subject_failed || @body_failed || @parts_failed || @sender_failed ||
@recipient_failed || @multipart_failed
end
def regexp_or_string_match(a_string, a_regexp_or_string)
@ -129,6 +143,23 @@ module Shoulda # :nodoc:
end
end
def parts_match(mail, parts)
return false if mail.parts.empty?
parts.all? do |content_type, match, _|
part_match(mail, content_type, match)
end
end
def part_match(mail, content_type, a_regexp_or_string)
matching = mail.parts.select {|p| p.content_type =~ content_type}
return false if matching.empty?
matching.all? do |part|
regexp_or_string_match(part.body, a_regexp_or_string)
end
end
end
end
end

View File

@ -51,6 +51,20 @@ describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
matcher.failure_message.should =~ /Expected sent email with body/
end
it "accepts sent e-mail based on a text/plain part" do
should have_sent_email.with_part('text/plain', /is spam\./)
matcher = have_sent_email.with_part('text/plain', /HTML is spam/)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email with a text\/plain part containing/
end
it "accepts sent e-mail based on a text/html part" do
should have_sent_email.with_part('text/html', /HTML is spam/)
matcher = have_sent_email.with_part('text/html', /HTML is not spam\./)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email with a text\/html part containing/
end
it "accept sent e-mail based on the recipient" do
should have_sent_email.to('myself@me.com')
matcher = have_sent_email.to('you@example.com')
@ -74,8 +88,10 @@ describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
end
it "allows chaining" do
should have_sent_email.with_subject(/spam/).from('do-not-reply@example.com').with_body(/spam/).to('myself@me.com')
should_not have_sent_email.with_subject(/ham/).from('you@example.com').with_body(/ham/).to('them@example.com')
should have_sent_email.with_subject(/spam/).from('do-not-reply@example.com').with_body(/spam/).
with_part('text/plain', /is spam\./).with_part('text/html', /HTML is spam/).to('myself@me.com')
should_not have_sent_email.with_subject(/ham/).from('you@example.com').with_body(/ham/).
with_part('text/plain', /is ham/).with_part('text/html', /HTML is ham/).to('them@example.com')
end
end
@ -86,9 +102,13 @@ describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
matcher.description.should == 'send an email with a subject of "Welcome!"'
matcher = matcher.with_body("Welcome, human!")
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!"'
matcher = matcher.with_part('text/plain', 'plain')
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain"'
matcher = matcher.with_part('text/html', 'html')
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html"'
matcher = matcher.from("alien@example.com")
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" from "alien@example.com"'
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html" from "alien@example.com"'
matcher = matcher.to("human@example.com")
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" from "alien@example.com" to "human@example.com"'
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html" from "alien@example.com" to "human@example.com"'
end
end