## written by David Lowenfels @ Internaut Design
## may be used/modified as long as credit is given

def assert_emails_sent args = {}, &block
opts = args.dup
array_headers = [ :to, :from ]
# if was pass a string as :to, or :from, then it implies an array with one member
array_headers.each do |sym|
opts[sym] = opts[sym].email if opts[sym].respond_to? :email # convert to email if sent object with email attribute
opts[sym] = []<<opts[sym] if opts[sym].is_a?( String ) # convert to array if given string
end
opts[:count] ||= 1

ActionMailer::Base.deliveries.clear

block.call
deliveries = ActionMailer::Base.deliveries
assert !deliveries.empty?, "No e-mail in delivery list"
expected_deliveries = opts.delete(:count)
assert_equal expected_deliveries, deliveries.size, "An unexpected number of emails were delivered"

deliveries.each_with_index do |msg,idx|
opts.each_pair do |k,v|
val = msg.send( k )
case v
when Regexp
error = "failure on deliveries[#{idx}].#{k}"
if array_headers.include? k
assert !val.grep( v ).empty?, error+" does not match #{v}"
else
assert_match v, val, error
end
else
assert_equal v, val, error
end
end
end
end

def assert_email_sent args = {}, &block
assert_emails_sent args.merge(:count => 1), &block
return ActionMailer::Base.deliveries.first
end

def assert_email_not_sent
ActionMailer::Base.deliveries.clear
yield
assert ActionMailer::Base.deliveries.empty?, "Email was unexpectedly sent"
end