email_spec 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +79 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +125 -0
- data/Rakefile +51 -0
- data/examples/rails_root/Rakefile +7 -0
- data/examples/rails_root/app/controllers/application.rb +15 -0
- data/examples/rails_root/app/controllers/welcome_controller.rb +9 -0
- data/examples/rails_root/app/helpers/application_helper.rb +3 -0
- data/examples/rails_root/app/helpers/welcome_helper.rb +2 -0
- data/examples/rails_root/app/models/user.rb +2 -0
- data/examples/rails_root/app/models/user_mailer.rb +12 -0
- data/examples/rails_root/app/views/user_mailer/signup.erb +3 -0
- data/examples/rails_root/app/views/welcome/confirm.html.erb +1 -0
- data/examples/rails_root/app/views/welcome/index.html.erb +8 -0
- data/examples/rails_root/app/views/welcome/signup.html.erb +1 -0
- data/examples/rails_root/config/boot.rb +109 -0
- data/examples/rails_root/config/database.yml +22 -0
- data/examples/rails_root/config/environment.rb +22 -0
- data/examples/rails_root/config/environments/development.rb +17 -0
- data/examples/rails_root/config/environments/production.rb +24 -0
- data/examples/rails_root/config/environments/test.rb +33 -0
- data/examples/rails_root/config/initializers/inflections.rb +10 -0
- data/examples/rails_root/config/initializers/mime_types.rb +5 -0
- data/examples/rails_root/config/initializers/new_rails_defaults.rb +17 -0
- data/examples/rails_root/config/routes.rb +43 -0
- data/examples/rails_root/cucumber.yml +1 -0
- data/examples/rails_root/db/migrate/20090125013728_create_users.rb +11 -0
- data/examples/rails_root/db/schema.rb +19 -0
- data/examples/rails_root/doc/README_FOR_APP +5 -0
- data/examples/rails_root/features/errors.feature +42 -0
- data/examples/rails_root/features/example.feature +59 -0
- data/examples/rails_root/features/step_definitions/email_steps.rb +74 -0
- data/examples/rails_root/features/step_definitions/user_steps.rb +23 -0
- data/examples/rails_root/features/step_definitions/webrat_steps.rb +104 -0
- data/examples/rails_root/features/support/env.rb +21 -0
- data/examples/rails_root/log/development.log +1 -0
- data/examples/rails_root/log/test.log +224 -0
- data/examples/rails_root/public/404.html +30 -0
- data/examples/rails_root/public/422.html +30 -0
- data/examples/rails_root/public/500.html +33 -0
- data/examples/rails_root/public/dispatch.rb +10 -0
- data/examples/rails_root/public/favicon.ico +0 -0
- data/examples/rails_root/public/images/rails.png +0 -0
- data/examples/rails_root/public/javascripts/application.js +2 -0
- data/examples/rails_root/public/javascripts/controls.js +963 -0
- data/examples/rails_root/public/javascripts/dragdrop.js +973 -0
- data/examples/rails_root/public/javascripts/effects.js +1128 -0
- data/examples/rails_root/public/javascripts/prototype.js +4320 -0
- data/examples/rails_root/public/robots.txt +5 -0
- data/examples/rails_root/script/about +4 -0
- data/examples/rails_root/script/autospec +5 -0
- data/examples/rails_root/script/console +3 -0
- data/examples/rails_root/script/cucumber +7 -0
- data/examples/rails_root/script/dbconsole +3 -0
- data/examples/rails_root/script/destroy +3 -0
- data/examples/rails_root/script/generate +3 -0
- data/examples/rails_root/script/performance/benchmarker +3 -0
- data/examples/rails_root/script/performance/profiler +3 -0
- data/examples/rails_root/script/performance/request +3 -0
- data/examples/rails_root/script/plugin +3 -0
- data/examples/rails_root/script/process/inspector +3 -0
- data/examples/rails_root/script/process/reaper +3 -0
- data/examples/rails_root/script/process/spawner +3 -0
- data/examples/rails_root/script/runner +3 -0
- data/examples/rails_root/script/server +3 -0
- data/examples/rails_root/script/spec +5 -0
- data/examples/rails_root/script/spec_server +125 -0
- data/examples/rails_root/spec/controllers/welcome_controller_spec.rb +15 -0
- data/examples/rails_root/spec/model_factory.rb +6 -0
- data/examples/rails_root/spec/models/user_mailer_spec.rb +58 -0
- data/examples/rails_root/spec/models/user_spec.rb +5 -0
- data/examples/rails_root/spec/rcov.opts +2 -0
- data/examples/rails_root/spec/spec.opts +4 -0
- data/examples/rails_root/spec/spec_helper.rb +51 -0
- data/examples/rails_root/stories/all.rb +4 -0
- data/examples/rails_root/stories/helper.rb +3 -0
- data/examples/rails_root/vendor/plugins/email_spec/rails_generators/email_spec/email_spec_generator.rb +17 -0
- data/examples/rails_root/vendor/plugins/email_spec/rails_generators/email_spec/templates/email_steps.rb +74 -0
- data/install.rb +0 -0
- data/lib/email-spec.rb +1 -0
- data/lib/email_spec.rb +14 -0
- data/lib/email_spec/address_converter.rb +27 -0
- data/lib/email_spec/cucumber.rb +19 -0
- data/lib/email_spec/deliveries.rb +55 -0
- data/lib/email_spec/email_viewer.rb +70 -0
- data/lib/email_spec/helpers.rb +129 -0
- data/lib/email_spec/matchers.rb +122 -0
- data/rails_generators/email_spec/email_spec_generator.rb +17 -0
- data/rails_generators/email_spec/templates/email_steps.rb +74 -0
- data/spec/email_spec/matchers_spec.rb +159 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +4 -0
- metadata +181 -0
data/install.rb
ADDED
File without changes
|
data/lib/email-spec.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'email_spec'))
|
data/lib/email_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
unless defined?(ActionMailer)
|
2
|
+
Kernel.warn("ActionMailer did not appear to be loaded so email-spec is requiring it.")
|
3
|
+
require 'actionmailer'
|
4
|
+
end
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
|
7
|
+
|
8
|
+
require 'email_spec/deliveries'
|
9
|
+
require 'email_spec/address_converter'
|
10
|
+
require 'email_spec/email_viewer'
|
11
|
+
require 'email_spec/helpers'
|
12
|
+
require 'email_spec/matchers'
|
13
|
+
|
14
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module EmailSpec
|
2
|
+
class AddressConverter
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
attr_accessor :converter
|
6
|
+
|
7
|
+
# The block provided to conversion should convert to an email
|
8
|
+
# address string or return the input untouched. For example:
|
9
|
+
#
|
10
|
+
# EmailSpec::AddressConverter.instance.conversion do |input|
|
11
|
+
# if input.is_a?(User)
|
12
|
+
# input.email
|
13
|
+
# else
|
14
|
+
# input
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
def conversion(&block)
|
19
|
+
self.converter = block
|
20
|
+
end
|
21
|
+
|
22
|
+
def convert(input)
|
23
|
+
return input unless converter
|
24
|
+
converter.call(input)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# require this in your env.rb file after you require cucumber/rails/world
|
2
|
+
|
3
|
+
# Global Setup
|
4
|
+
ActionMailer::Base.delivery_method = :test unless ActionMailer::Base.delivery_method == :activerecord
|
5
|
+
ActionMailer::Base.perform_deliveries = true
|
6
|
+
|
7
|
+
Before do
|
8
|
+
# Scenario setup
|
9
|
+
ActionMailer::Base.deliveries.clear if ActionMailer::Base.delivery_method == :test
|
10
|
+
end
|
11
|
+
|
12
|
+
After do
|
13
|
+
EmailSpec::EmailViewer.save_and_open_all_raw_emails if ENV['SHOW_EMAILS']
|
14
|
+
EmailSpec::EmailViewer.save_and_open_all_html_emails if ENV['SHOW_HTML_EMAILS']
|
15
|
+
EmailSpec::EmailViewer.save_and_open_all_text_emails if ENV['SHOW_TEXT_EMAILS']
|
16
|
+
end
|
17
|
+
|
18
|
+
World(EmailSpec::Helpers)
|
19
|
+
World(EmailSpec::Matchers)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module EmailSpec
|
2
|
+
module TestDeliveries
|
3
|
+
def all_emails
|
4
|
+
ActionMailer::Base.deliveries
|
5
|
+
end
|
6
|
+
|
7
|
+
def last_email_sent
|
8
|
+
ActionMailer::Base.deliveries.last || raise("No email has been sent!")
|
9
|
+
end
|
10
|
+
|
11
|
+
def reset_mailer
|
12
|
+
ActionMailer::Base.deliveries.clear
|
13
|
+
end
|
14
|
+
|
15
|
+
def mailbox_for(address)
|
16
|
+
address = AddressConverter.instance.convert(address)
|
17
|
+
ActionMailer::Base.deliveries.select { |m| m.to.include?(address) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ARMailerDeliveries
|
22
|
+
def all_emails
|
23
|
+
Email.all.map{ |email| parse_to_tmail(email) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def last_email_sent
|
27
|
+
if email = Email.last
|
28
|
+
TMail::Mail.parse(email.mail)
|
29
|
+
else
|
30
|
+
raise("No email has been sent!")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset_mailer
|
35
|
+
Email.delete_all
|
36
|
+
end
|
37
|
+
|
38
|
+
def mailbox_for(address)
|
39
|
+
address = AddressConverter.instance.convert(address)
|
40
|
+
Email.all.select { |email| email.to.include?(address) }.map{ |email| parse_to_tmail(email) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_to_tmail(email)
|
44
|
+
TMail::Mail.parse(email.mail)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module Deliveries
|
49
|
+
if ActionMailer::Base.delivery_method == :activerecord
|
50
|
+
include EmailSpec::ARMailerDeliveries
|
51
|
+
else
|
52
|
+
include EmailSpec::TestDeliveries
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module EmailSpec
|
2
|
+
class EmailViewer
|
3
|
+
extend Deliveries
|
4
|
+
|
5
|
+
def self.save_and_open_all_raw_emails
|
6
|
+
filename = "#{RAILS_ROOT}/tmp/email-#{Time.now.to_i}.txt"
|
7
|
+
|
8
|
+
File.open(filename, "w") do |f|
|
9
|
+
all_emails.each do |m|
|
10
|
+
f.write m.to_s
|
11
|
+
f.write "\n" + '='*80 + "\n"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
open_in_text_editor(filename)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.save_and_open_all_html_emails
|
19
|
+
all_emails.each_with_index do |m, index|
|
20
|
+
if m.multipart? && html_part = m.parts.detect{ |p| p.content_type == 'text/html' }
|
21
|
+
filename = tmp_email_filename("-#{index}.html")
|
22
|
+
File.open(filename, "w") do |f|
|
23
|
+
f.write m.parts[1].body
|
24
|
+
end
|
25
|
+
open_in_browser(filename)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.save_and_open_all_text_emails
|
31
|
+
filename = tmp_email_filename
|
32
|
+
|
33
|
+
File.open(filename, "w") do |f|
|
34
|
+
all_emails.each do |m|
|
35
|
+
if m.multipart? && text_part = m.parts.detect{ |p| p.content_type == 'text/plain' }
|
36
|
+
m.ordered_each{|k,v| f.write "#{k}: #{v}\n" }
|
37
|
+
f.write text_part.body
|
38
|
+
else
|
39
|
+
f.write m.to_s
|
40
|
+
end
|
41
|
+
f.write "\n" + '='*80 + "\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
open_in_text_editor(filename)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.save_and_open_email(mail)
|
49
|
+
filename = "#{RAILS_ROOT}/tmp/email-#{Time.now.to_i}.txt"
|
50
|
+
|
51
|
+
File.open(filename, "w") do |f|
|
52
|
+
f.write mail.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
open_in_text_editor(filename)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.open_in_text_editor(filename)
|
59
|
+
`mate #{filename}`
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.open_in_browser(filename)
|
63
|
+
`open #{filename}`
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.tmp_email_filename(extension = '.txt')
|
67
|
+
"#{RAILS_ROOT}/tmp/email-#{Time.now.to_i}#{extension}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'email_spec/deliveries'
|
3
|
+
|
4
|
+
module EmailSpec
|
5
|
+
|
6
|
+
module Helpers
|
7
|
+
include Deliveries
|
8
|
+
|
9
|
+
def visit_in_email(link_text)
|
10
|
+
visit(parse_email_for_link(current_email, link_text))
|
11
|
+
end
|
12
|
+
|
13
|
+
def click_email_link_matching(regex, email = current_email)
|
14
|
+
url = links_in_email(email).detect { |link| link =~ regex }
|
15
|
+
raise "No link found matching #{regex.inspect} in #{email.body}" unless url
|
16
|
+
request_uri = URI::parse(url).request_uri
|
17
|
+
visit request_uri
|
18
|
+
end
|
19
|
+
|
20
|
+
def click_first_link_in_email(email = current_email)
|
21
|
+
link = links_in_email(email).first
|
22
|
+
request_uri = URI::parse(link).request_uri
|
23
|
+
visit request_uri
|
24
|
+
end
|
25
|
+
|
26
|
+
def open_email(address, opts={})
|
27
|
+
address = convert_address(address)
|
28
|
+
set_current_email(find_email!(address, opts))
|
29
|
+
end
|
30
|
+
|
31
|
+
alias_method :open_email_for, :open_email
|
32
|
+
|
33
|
+
def open_last_email
|
34
|
+
set_current_email(last_email_sent)
|
35
|
+
end
|
36
|
+
|
37
|
+
def open_last_email_for(address)
|
38
|
+
address = convert_address(address)
|
39
|
+
set_current_email(mailbox_for(address).last)
|
40
|
+
end
|
41
|
+
|
42
|
+
def current_email(address=nil)
|
43
|
+
address = convert_address(address)
|
44
|
+
email = address ? email_spec_hash[:current_emails][address] : email_spec_hash[:current_email]
|
45
|
+
raise Spec::Expectations::ExpectationNotMetError, "Expected an open email but none was found. Did you forget to call open_email?" unless email
|
46
|
+
email
|
47
|
+
end
|
48
|
+
|
49
|
+
def unread_emails_for(address)
|
50
|
+
address = convert_address(address)
|
51
|
+
mailbox_for(address) - read_emails_for(address)
|
52
|
+
end
|
53
|
+
|
54
|
+
def read_emails_for(address)
|
55
|
+
address = convert_address(address)
|
56
|
+
email_spec_hash[:read_emails][address] ||= []
|
57
|
+
end
|
58
|
+
|
59
|
+
def find_email(address, opts={})
|
60
|
+
address = convert_address(address)
|
61
|
+
if opts[:with_subject]
|
62
|
+
email = mailbox_for(address).find { |m| m.subject =~ Regexp.new(opts[:with_subject]) }
|
63
|
+
elsif opts[:with_text]
|
64
|
+
email = mailbox_for(address).find { |m| m.body =~ Regexp.new(opts[:with_text]) }
|
65
|
+
else
|
66
|
+
email = mailbox_for(address).first
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def links_in_email(email)
|
71
|
+
URI.extract(email.body, ['http', 'https'])
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def email_spec_hash
|
77
|
+
@email_spec_hash ||= {:read_emails => {}, :unread_emails => {}, :current_emails => {}, :current_email => nil}
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_email!(address, opts={})
|
81
|
+
address = convert_address(address)
|
82
|
+
email = find_email(address, opts)
|
83
|
+
if email.nil?
|
84
|
+
error = "#{opts.keys.first.to_s.humanize unless opts.empty?} #{('"' + opts.values.first.to_s.humanize + '"') unless opts.empty?}"
|
85
|
+
raise Spec::Expectations::ExpectationNotMetError, "Could not find email #{error}. \n Found the following emails:\n\n #{all_emails.to_s}"
|
86
|
+
end
|
87
|
+
email
|
88
|
+
end
|
89
|
+
|
90
|
+
def set_current_email(email)
|
91
|
+
return unless email
|
92
|
+
email.to.each do |to|
|
93
|
+
read_emails_for(to) << email
|
94
|
+
email_spec_hash[:current_emails][to] = email
|
95
|
+
end
|
96
|
+
email_spec_hash[:current_email] = email
|
97
|
+
end
|
98
|
+
|
99
|
+
def parse_email_for_link(email, text_or_regex)
|
100
|
+
email.should have_body_text(text_or_regex)
|
101
|
+
|
102
|
+
url = parse_email_for_explicit_link(email, text_or_regex)
|
103
|
+
url ||= parse_email_for_anchor_text_link(email, text_or_regex)
|
104
|
+
|
105
|
+
raise "No link found matching #{text_or_regex.inspect} in #{email}" unless url
|
106
|
+
url
|
107
|
+
end
|
108
|
+
|
109
|
+
# e.g. confirm in http://confirm
|
110
|
+
def parse_email_for_explicit_link(email, regex)
|
111
|
+
regex = /#{Regexp.escape(regex)}/ unless regex.is_a?(Regexp)
|
112
|
+
url = links_in_email(email).detect { |link| link =~ regex }
|
113
|
+
URI::parse(url).request_uri if url
|
114
|
+
end
|
115
|
+
|
116
|
+
# e.g. Click here in <a href="http://confirm">Click here</a>
|
117
|
+
def parse_email_for_anchor_text_link(email, link_text)
|
118
|
+
email.body =~ %r{<a[^>]*href=['"]?([^'"]*)['"]?[^>]*?>[^<]*?#{link_text}[^<]*?</a>}
|
119
|
+
URI.split($~[1])[5..-1].compact!.join("?").gsub("&", "&")
|
120
|
+
# sub correct ampersand after rails switches it (http://dev.rubyonrails.org/ticket/4002)
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
def convert_address(address)
|
125
|
+
AddressConverter.instance.convert(address)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module EmailSpec
|
2
|
+
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
class DeliverTo
|
6
|
+
|
7
|
+
def initialize(expected_email_addresses_or_objects_that_respond_to_email)
|
8
|
+
emails = expected_email_addresses_or_objects_that_respond_to_email.map do |email_or_object|
|
9
|
+
email_or_object.kind_of?(String) ? email_or_object : email_or_object.email
|
10
|
+
end
|
11
|
+
|
12
|
+
@expected_email_addresses = emails.sort
|
13
|
+
end
|
14
|
+
|
15
|
+
def description
|
16
|
+
"be delivered to #{@expected_email_addresses.inspect}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(email)
|
20
|
+
@email = email
|
21
|
+
@actual_recipients = (email.to || []).sort
|
22
|
+
@actual_recipients == @expected_email_addresses
|
23
|
+
end
|
24
|
+
|
25
|
+
def failure_message
|
26
|
+
"expected #{@email.inspect} to deliver to #{@expected_email_addresses.inspect}, but it delievered to #{@actual_recipients.inspect}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def negative_failure_message
|
30
|
+
"expected #{@email.inspect} not to deliver to #{@expected_email_addresses.inspect}, but it did"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def deliver_to(*expected_email_addresses_or_objects_that_respond_to_email)
|
35
|
+
DeliverTo.new(expected_email_addresses_or_objects_that_respond_to_email.flatten)
|
36
|
+
end
|
37
|
+
|
38
|
+
alias :be_delivered_to :deliver_to
|
39
|
+
|
40
|
+
def have_subject(expected)
|
41
|
+
simple_matcher do |given, matcher|
|
42
|
+
given_subject = given.subject
|
43
|
+
|
44
|
+
if expected.is_a?(String)
|
45
|
+
matcher.description = "have subject of #{expected.inspect}"
|
46
|
+
matcher.failure_message = "expected the subject to be #{expected.inspect} but was #{given_subject.inspect}"
|
47
|
+
matcher.negative_failure_message = "expected the subject not to be #{expected.inspect} but was"
|
48
|
+
|
49
|
+
given_subject == expected
|
50
|
+
else
|
51
|
+
matcher.description = "have subject matching #{expected.inspect}"
|
52
|
+
matcher.failure_message = "expected the subject to match #{expected.inspect}, but did not. Actual subject was: #{given_subject.inspect}"
|
53
|
+
matcher.negative_failure_message = "expected the subject not to match #{expected.inspect} but #{given_subject.inspect} does match it."
|
54
|
+
|
55
|
+
!!(given_subject =~ expected)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def include_email_with_subject(expected)
|
61
|
+
simple_matcher do |given_emails, matcher|
|
62
|
+
|
63
|
+
if expected.is_a?(String)
|
64
|
+
matcher.description = "include email with subject of #{expected.inspect}"
|
65
|
+
matcher.failure_message = "expected at least one email to have the subject #{expected.inspect} but none did. Subjects were #{given_emails.map(&:subject).inspect}"
|
66
|
+
matcher.negative_failure_message = "expected no email with the subject #{expected.inspect} but found at least one. Subjects were #{given_emails.map(&:subject).inspect}"
|
67
|
+
|
68
|
+
given_emails.map(&:subject).include?(expected)
|
69
|
+
else
|
70
|
+
matcher.description = "include email with subject matching #{expected.inspect}"
|
71
|
+
matcher.failure_message = "expected at least one email to have a subject matching #{expected.inspect}, but none did. Subjects were #{given_emails.map(&:subject).inspect}"
|
72
|
+
matcher.negative_failure_message = "expected no email to have a subject matching #{expected.inspect} but found at least one. Subjects were #{given_emails.map(&:subject).inspect}"
|
73
|
+
|
74
|
+
!!(given_emails.any?{ |mail| mail.subject =~ expected })
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def have_body_text(expected)
|
80
|
+
simple_matcher do |given, matcher|
|
81
|
+
|
82
|
+
if expected.is_a?(String)
|
83
|
+
normalized_body = given.body.gsub(/\s+/, " ")
|
84
|
+
normalized_expected = expected.gsub(/\s+/, " ")
|
85
|
+
matcher.description = "have body including #{normalized_expected.inspect}"
|
86
|
+
matcher.failure_message = "expected the body to contain #{normalized_expected.inspect} but was #{normalized_body.inspect}"
|
87
|
+
matcher.negative_failure_message = "expected the body not to contain #{normalized_expected.inspect} but was #{normalized_body.inspect}"
|
88
|
+
|
89
|
+
normalized_body.include?(normalized_expected)
|
90
|
+
else
|
91
|
+
given_body = given.body
|
92
|
+
matcher.description = "have body matching #{expected.inspect}"
|
93
|
+
matcher.failure_message = "expected the body to match #{expected.inspect}, but did not. Actual body was: #{given_body.inspect}"
|
94
|
+
matcher.negative_failure_message = "expected the body not to match #{expected.inspect} but #{given_body.inspect} does match it."
|
95
|
+
|
96
|
+
!!(given_body =~ expected)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def have_header(expected_name, expected_value)
|
102
|
+
simple_matcher do |given, matcher|
|
103
|
+
given_header = given.header
|
104
|
+
|
105
|
+
if expected_value.is_a?(String)
|
106
|
+
matcher.description = "have header #{expected_name}: #{expected_value}"
|
107
|
+
matcher.failure_message = "expected the headers to include '#{expected_name}: #{expected_value}' but they were #{given_header.inspect}"
|
108
|
+
matcher.negative_failure_message = "expected the headers not to include '#{expected_name}: #{expected_value}' but they were #{given_header.inspect}"
|
109
|
+
|
110
|
+
given_header[expected_name].to_s == expected_value
|
111
|
+
else
|
112
|
+
matcher.description = "have header #{expected_name} with value matching #{expected_value.inspect}"
|
113
|
+
matcher.failure_message = "expected the headers to include '#{expected_name}' with a value matching #{expected_value.inspect} but they were #{given_header.inspect}"
|
114
|
+
matcher.negative_failure_message = "expected the headers not to include '#{expected_name}' with a value matching #{expected_value.inspect} but they were #{given_header.inspect}"
|
115
|
+
|
116
|
+
given_header[expected_name].to_s =~ expected_value
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|