path-email_spec 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. data/History.txt +199 -0
  2. data/MIT-LICENSE.txt +19 -0
  3. data/README.rdoc +137 -0
  4. data/Rakefile +64 -0
  5. data/examples/rails3_root/Gemfile +24 -0
  6. data/examples/rails3_root/README +5 -0
  7. data/examples/rails3_root/Rakefile +11 -0
  8. data/examples/rails3_root/app/controllers/application_controller.rb +3 -0
  9. data/examples/rails3_root/app/controllers/welcome_controller.rb +16 -0
  10. data/examples/rails3_root/app/helpers/application_helper.rb +2 -0
  11. data/examples/rails3_root/app/mailers/user_mailer.rb +39 -0
  12. data/examples/rails3_root/app/models/user.rb +2 -0
  13. data/examples/rails3_root/app/views/user_mailer/attachments.html.erb +6 -0
  14. data/examples/rails3_root/app/views/user_mailer/newsletter.html.erb +8 -0
  15. data/examples/rails3_root/app/views/user_mailer/signup.html.erb +3 -0
  16. data/examples/rails3_root/app/views/welcome/attachments.html.erb +0 -0
  17. data/examples/rails3_root/app/views/welcome/confirm.html.erb +1 -0
  18. data/examples/rails3_root/app/views/welcome/index.html.erb +8 -0
  19. data/examples/rails3_root/app/views/welcome/newsletter.html.erb +0 -0
  20. data/examples/rails3_root/app/views/welcome/signup.html.erb +1 -0
  21. data/examples/rails3_root/attachments/document.pdf +0 -0
  22. data/examples/rails3_root/attachments/image.png +0 -0
  23. data/examples/rails3_root/config.ru +4 -0
  24. data/examples/rails3_root/config/application.rb +43 -0
  25. data/examples/rails3_root/config/boot.rb +14 -0
  26. data/examples/rails3_root/config/cucumber.yml +7 -0
  27. data/examples/rails3_root/config/database.yml +25 -0
  28. data/examples/rails3_root/config/environment.rb +6 -0
  29. data/examples/rails3_root/config/environments/development.rb +19 -0
  30. data/examples/rails3_root/config/environments/production.rb +42 -0
  31. data/examples/rails3_root/config/environments/test.rb +29 -0
  32. data/examples/rails3_root/config/initializers/backtrace_silencers.rb +7 -0
  33. data/examples/rails3_root/config/initializers/cookie_verification_secret.rb +7 -0
  34. data/examples/rails3_root/config/initializers/inflections.rb +10 -0
  35. data/examples/rails3_root/config/initializers/mime_types.rb +5 -0
  36. data/examples/rails3_root/config/initializers/rspec_generator.rb +6 -0
  37. data/examples/rails3_root/config/initializers/session_store.rb +10 -0
  38. data/examples/rails3_root/config/locales/en.yml +5 -0
  39. data/examples/rails3_root/config/routes.rb +7 -0
  40. data/examples/rails3_root/db/migrate/20090125013728_create_users.rb +11 -0
  41. data/examples/rails3_root/db/migrate/20090908054656_create_delayed_jobs.rb +20 -0
  42. data/examples/rails3_root/db/schema.rb +32 -0
  43. data/examples/rails3_root/db/seeds.rb +7 -0
  44. data/examples/rails3_root/doc/README_FOR_APP +2 -0
  45. data/examples/rails3_root/features/attachments.feature +27 -0
  46. data/examples/rails3_root/features/delayed_job.feature +13 -0
  47. data/examples/rails3_root/features/errors.feature +32 -0
  48. data/examples/rails3_root/features/example.feature +62 -0
  49. data/examples/rails3_root/features/step_definitions/user_steps.rb +26 -0
  50. data/examples/rails3_root/features/step_definitions/web_steps.rb +202 -0
  51. data/examples/rails3_root/features/support/env.rb +59 -0
  52. data/examples/rails3_root/features/support/env_ext.rb +2 -0
  53. data/examples/rails3_root/features/support/paths.rb +33 -0
  54. data/examples/rails3_root/lib/tasks/cucumber.rake +47 -0
  55. data/examples/rails3_root/lib/tasks/rspec.rake +69 -0
  56. data/examples/rails3_root/public/404.html +26 -0
  57. data/examples/rails3_root/public/422.html +26 -0
  58. data/examples/rails3_root/public/500.html +26 -0
  59. data/examples/rails3_root/public/favicon.ico +0 -0
  60. data/examples/rails3_root/public/images/rails.png +0 -0
  61. data/examples/rails3_root/public/javascripts/application.js +2 -0
  62. data/examples/rails3_root/public/javascripts/controls.js +965 -0
  63. data/examples/rails3_root/public/javascripts/dragdrop.js +974 -0
  64. data/examples/rails3_root/public/javascripts/effects.js +1123 -0
  65. data/examples/rails3_root/public/javascripts/prototype.js +4874 -0
  66. data/examples/rails3_root/public/javascripts/rails.js +109 -0
  67. data/examples/rails3_root/public/robots.txt +5 -0
  68. data/examples/rails3_root/script/cucumber +10 -0
  69. data/examples/rails3_root/script/rails +9 -0
  70. data/examples/rails3_root/spec/controllers/welcome_controller_spec.rb +18 -0
  71. data/examples/rails3_root/spec/models/user_mailer_spec.rb +47 -0
  72. data/examples/rails3_root/spec/spec.opts +2 -0
  73. data/examples/rails3_root/spec/spec_helper.rb +19 -0
  74. data/examples/rails_root/Rakefile +13 -0
  75. data/examples/rails_root/app/controllers/application_controller.rb +15 -0
  76. data/examples/rails_root/app/controllers/welcome_controller.rb +16 -0
  77. data/examples/rails_root/app/helpers/application_helper.rb +3 -0
  78. data/examples/rails_root/app/helpers/welcome_helper.rb +2 -0
  79. data/examples/rails_root/app/models/user.rb +2 -0
  80. data/examples/rails_root/app/models/user_mailer.rb +39 -0
  81. data/examples/rails_root/app/views/user_mailer/attachments.erb +6 -0
  82. data/examples/rails_root/app/views/user_mailer/newsletter.erb +8 -0
  83. data/examples/rails_root/app/views/user_mailer/signup.erb +3 -0
  84. data/examples/rails_root/app/views/welcome/attachments.html.erb +0 -0
  85. data/examples/rails_root/app/views/welcome/confirm.html.erb +1 -0
  86. data/examples/rails_root/app/views/welcome/index.html.erb +8 -0
  87. data/examples/rails_root/app/views/welcome/newsletter.html.erb +0 -0
  88. data/examples/rails_root/app/views/welcome/signup.html.erb +1 -0
  89. data/examples/rails_root/attachments/document.pdf +0 -0
  90. data/examples/rails_root/attachments/image.png +0 -0
  91. data/examples/rails_root/config/boot.rb +110 -0
  92. data/examples/rails_root/config/cucumber.yml +7 -0
  93. data/examples/rails_root/config/database.yml +25 -0
  94. data/examples/rails_root/config/environment.rb +28 -0
  95. data/examples/rails_root/config/environments/cucumber.rb +29 -0
  96. data/examples/rails_root/config/environments/development.rb +17 -0
  97. data/examples/rails_root/config/environments/production.rb +28 -0
  98. data/examples/rails_root/config/environments/test.rb +28 -0
  99. data/examples/rails_root/config/initializers/inflections.rb +10 -0
  100. data/examples/rails_root/config/initializers/mime_types.rb +5 -0
  101. data/examples/rails_root/config/initializers/new_rails_defaults.rb +17 -0
  102. data/examples/rails_root/config/routes.rb +45 -0
  103. data/examples/rails_root/db/migrate/20090125013728_create_users.rb +11 -0
  104. data/examples/rails_root/db/migrate/20090908054656_create_delayed_jobs.rb +20 -0
  105. data/examples/rails_root/db/schema.rb +32 -0
  106. data/examples/rails_root/doc/README_FOR_APP +5 -0
  107. data/examples/rails_root/features/attachments.feature +27 -0
  108. data/examples/rails_root/features/delayed_job.feature +13 -0
  109. data/examples/rails_root/features/errors.feature +32 -0
  110. data/examples/rails_root/features/example.feature +62 -0
  111. data/examples/rails_root/features/step_definitions/user_steps.rb +26 -0
  112. data/examples/rails_root/features/step_definitions/web_steps.rb +273 -0
  113. data/examples/rails_root/features/support/env.rb +58 -0
  114. data/examples/rails_root/features/support/env_ext.rb +6 -0
  115. data/examples/rails_root/features/support/paths.rb +33 -0
  116. data/examples/rails_root/lib/tasks/cucumber.rake +47 -0
  117. data/examples/rails_root/public/404.html +30 -0
  118. data/examples/rails_root/public/422.html +30 -0
  119. data/examples/rails_root/public/500.html +33 -0
  120. data/examples/rails_root/public/dispatch.rb +10 -0
  121. data/examples/rails_root/public/favicon.ico +0 -0
  122. data/examples/rails_root/public/images/rails.png +0 -0
  123. data/examples/rails_root/public/javascripts/application.js +2 -0
  124. data/examples/rails_root/public/javascripts/controls.js +963 -0
  125. data/examples/rails_root/public/javascripts/dragdrop.js +973 -0
  126. data/examples/rails_root/public/javascripts/effects.js +1128 -0
  127. data/examples/rails_root/public/javascripts/prototype.js +4320 -0
  128. data/examples/rails_root/public/robots.txt +5 -0
  129. data/examples/rails_root/script/about +4 -0
  130. data/examples/rails_root/script/autospec +5 -0
  131. data/examples/rails_root/script/console +3 -0
  132. data/examples/rails_root/script/cucumber +10 -0
  133. data/examples/rails_root/script/dbconsole +3 -0
  134. data/examples/rails_root/script/delayed_job +5 -0
  135. data/examples/rails_root/script/destroy +3 -0
  136. data/examples/rails_root/script/generate +3 -0
  137. data/examples/rails_root/script/performance/benchmarker +3 -0
  138. data/examples/rails_root/script/performance/profiler +3 -0
  139. data/examples/rails_root/script/performance/request +3 -0
  140. data/examples/rails_root/script/plugin +3 -0
  141. data/examples/rails_root/script/process/inspector +3 -0
  142. data/examples/rails_root/script/process/reaper +3 -0
  143. data/examples/rails_root/script/process/spawner +3 -0
  144. data/examples/rails_root/script/runner +3 -0
  145. data/examples/rails_root/script/server +3 -0
  146. data/examples/rails_root/script/spec +5 -0
  147. data/examples/rails_root/script/spec_server +125 -0
  148. data/examples/rails_root/spec/controllers/welcome_controller_spec.rb +15 -0
  149. data/examples/rails_root/spec/model_factory.rb +6 -0
  150. data/examples/rails_root/spec/models/user_mailer_spec.rb +58 -0
  151. data/examples/rails_root/spec/models/user_spec.rb +5 -0
  152. data/examples/rails_root/spec/rcov.opts +2 -0
  153. data/examples/rails_root/spec/spec.opts +4 -0
  154. data/examples/rails_root/spec/spec_helper.rb +51 -0
  155. data/examples/sinatra/app.rb +33 -0
  156. data/examples/sinatra/features/errors.feature +32 -0
  157. data/examples/sinatra/features/example.feature +62 -0
  158. data/examples/sinatra/features/step_definitions/user_steps.rb +26 -0
  159. data/examples/sinatra/features/step_definitions/web_steps.rb +273 -0
  160. data/examples/sinatra/features/support/env.rb +39 -0
  161. data/examples/sinatra/features/support/paths.rb +24 -0
  162. data/install.rb +0 -0
  163. data/lib/email-spec.rb +1 -0
  164. data/lib/email_spec.rb +15 -0
  165. data/lib/email_spec/address_converter.rb +29 -0
  166. data/lib/email_spec/background_processes.rb +45 -0
  167. data/lib/email_spec/cucumber.rb +26 -0
  168. data/lib/email_spec/deliveries.rb +87 -0
  169. data/lib/email_spec/email_viewer.rb +87 -0
  170. data/lib/email_spec/helpers.rb +164 -0
  171. data/lib/email_spec/matchers.rb +225 -0
  172. data/lib/generators/email_spec/steps/USAGE +5 -0
  173. data/lib/generators/email_spec/steps/steps_generator.rb +14 -0
  174. data/lib/generators/email_spec/steps/templates/email_steps.rb +194 -0
  175. data/rails_generators/email_spec/email_spec_generator.rb +17 -0
  176. data/rails_generators/email_spec/templates/email_steps.rb +182 -0
  177. data/spec/email_spec/helpers_spec.rb +21 -0
  178. data/spec/email_spec/matchers_spec.rb +430 -0
  179. data/spec/spec_helper.rb +16 -0
  180. metadata +407 -0
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Creates email_steps.rb in your cucumber step_definitions.
3
+
4
+ Examples:
5
+ `script/rails generate email_spec:steps`
@@ -0,0 +1,14 @@
1
+ # This generator adds email steps to the step definitions directory
2
+ require 'rails/generators'
3
+
4
+ module EmailSpec
5
+ class StepsGenerator < Rails::Generators::Base
6
+ def generate
7
+ copy_file 'email_steps.rb', 'features/step_definitions/email_steps.rb'
8
+ end
9
+
10
+ def self.source_root
11
+ File.join(File.dirname(__FILE__), 'templates')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,194 @@
1
+ # Commonly used email steps
2
+ #
3
+ # To add your own steps make a custom_email_steps.rb
4
+ # The provided methods are:
5
+ #
6
+ # last_email_address
7
+ # reset_mailer
8
+ # open_last_email
9
+ # visit_in_email
10
+ # unread_emails_for
11
+ # mailbox_for
12
+ # current_email
13
+ # open_email
14
+ # read_emails_for
15
+ # find_email
16
+ #
17
+ # General form for email scenarios are:
18
+ # - clear the email queue (done automatically by email_spec)
19
+ # - execute steps that sends an email
20
+ # - check the user received an/no/[0-9] emails
21
+ # - open the email
22
+ # - inspect the email contents
23
+ # - interact with the email (e.g. click links)
24
+ #
25
+ # The Cucumber steps below are setup in this order.
26
+
27
+ module EmailHelpers
28
+ def current_email_address
29
+ # Replace with your a way to find your current email. e.g @current_user.email
30
+ # last_email_address will return the last email address used by email spec to find an email.
31
+ # Note that last_email_address will be reset after each Scenario.
32
+ last_email_address || "example@example.com"
33
+ end
34
+ end
35
+
36
+ World(EmailHelpers)
37
+
38
+ #
39
+ # Reset the e-mail queue within a scenario.
40
+ # This is done automatically before each scenario.
41
+ #
42
+
43
+ Given /^(?:a clear email queue|no emails have been sent)$/ do
44
+ reset_mailer
45
+ end
46
+
47
+ #
48
+ # Check how many emails have been sent/received
49
+ #
50
+
51
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails?$/ do |address, amount|
52
+ unread_emails_for(address).size.should == parse_email_count(amount)
53
+ end
54
+
55
+ Then /^(?:I|they|"([^"]*?)") should have (an|no|\d+) emails?$/ do |address, amount|
56
+ mailbox_for(address).size.should == parse_email_count(amount)
57
+ end
58
+
59
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails? with subject "([^"]*?)"$/ do |address, amount, subject|
60
+ unread_emails_for(address).select { |m| m.subject =~ Regexp.new(subject) }.size.should == parse_email_count(amount)
61
+ end
62
+
63
+ Then /^(?:I|they|"([^"]*?)") should receive an email with the following body:$/ do |address, expected_body|
64
+ open_email(address, :with_text => expected_body)
65
+ end
66
+
67
+ #
68
+ # Accessing emails
69
+ #
70
+
71
+ # Opens the most recently received email
72
+ When /^(?:I|they|"([^"]*?)") opens? the email$/ do |address|
73
+ open_email(address)
74
+ end
75
+
76
+ When /^(?:I|they|"([^"]*?)") opens? the email with subject "([^"]*?)"$/ do |address, subject|
77
+ open_email(address, :with_subject => subject)
78
+ end
79
+
80
+ When /^(?:I|they|"([^"]*?)") opens? the email with text "([^"]*?)"$/ do |address, text|
81
+ open_email(address, :with_text => text)
82
+ end
83
+
84
+ #
85
+ # Inspect the Email Contents
86
+ #
87
+
88
+ Then /^(?:I|they) should see "([^"]*?)" in the email subject$/ do |text|
89
+ current_email.should have_subject(text)
90
+ end
91
+
92
+ Then /^(?:I|they) should see \/([^"]*?)\/ in the email subject$/ do |text|
93
+ current_email.should have_subject(Regexp.new(text))
94
+ end
95
+
96
+ Then /^(?:I|they) should see "([^"]*?)" in the email body$/ do |text|
97
+ current_email.default_part_body.to_s.should include(text)
98
+ end
99
+
100
+ Then /^(?:I|they) should see \/([^"]*?)\/ in the email body$/ do |text|
101
+ current_email.default_part_body.to_s.should =~ Regexp.new(text)
102
+ end
103
+
104
+ Then /^(?:I|they) should see the email delivered from "([^"]*?)"$/ do |text|
105
+ current_email.should be_delivered_from(text)
106
+ end
107
+
108
+ Then /^(?:I|they) should see "([^\"]*)" in the email "([^"]*?)" header$/ do |text, name|
109
+ current_email.should have_header(name, text)
110
+ end
111
+
112
+ Then /^(?:I|they) should see \/([^\"]*)\/ in the email "([^"]*?)" header$/ do |text, name|
113
+ current_email.should have_header(name, Regexp.new(text))
114
+ end
115
+
116
+ Then /^I should see it is a multi\-part email$/ do
117
+ current_email.multipart?.should == true
118
+ end
119
+
120
+ Then /^(?:I|they) should see "([^"]*?)" in the email html part body$/ do |text|
121
+ current_email.html_part.body.to_s.should include(text)
122
+ end
123
+
124
+ Then /^(?:I|they) should see "([^"]*?)" in the email text part body$/ do |text|
125
+ current_email.text_part.body.to_s.should include(text)
126
+ end
127
+
128
+ #
129
+ # Inspect the Email Attachments
130
+ #
131
+
132
+ Then /^(?:I|they) should see (an|no|\d+) attachments? with the email$/ do |amount|
133
+ current_email_attachments.size.should == parse_email_count(amount)
134
+ end
135
+
136
+ Then /^there should be (an|no|\d+) attachments? named "([^"]*?)"$/ do |amount, filename|
137
+ current_email_attachments.select { |a| a.filename == filename }.size.should == parse_email_count(amount)
138
+ end
139
+
140
+ Then /^attachment (\d+) should be named "([^"]*?)"$/ do |index, filename|
141
+ current_email_attachments[(index.to_i - 1)].filename.should == filename
142
+ end
143
+
144
+ Then /^there should be (an|no|\d+) attachments? of type "([^"]*?)"$/ do |amount, content_type|
145
+ current_email_attachments.select { |a| a.content_type.include?(content_type) }.size.should == parse_email_count(amount)
146
+ end
147
+
148
+ Then /^attachment (\d+) should be of type "([^"]*?)"$/ do |index, content_type|
149
+ current_email_attachments[(index.to_i - 1)].content_type.should include(content_type)
150
+ end
151
+
152
+ Then /^all attachments should not be blank$/ do
153
+ current_email_attachments.each do |attachment|
154
+ attachment.read.size.should_not == 0
155
+ end
156
+ end
157
+
158
+ Then /^show me a list of email attachments$/ do
159
+ EmailSpec::EmailViewer::save_and_open_email_attachments_list(current_email)
160
+ end
161
+
162
+ #
163
+ # Interact with Email Contents
164
+ #
165
+
166
+ When /^(?:I|they) follow "([^"]*?)" in the email$/ do |link|
167
+ visit_in_email(link)
168
+ end
169
+
170
+ When /^(?:I|they) click the first link in the email$/ do
171
+ click_first_link_in_email
172
+ end
173
+
174
+ #
175
+ # Debugging
176
+ # These only work with Rails and OSx ATM since EmailViewer uses RAILS_ROOT and OSx's 'open' command.
177
+ # Patches accepted. ;)
178
+ #
179
+
180
+ Then /^save and open current email$/ do
181
+ EmailSpec::EmailViewer::save_and_open_email(current_email)
182
+ end
183
+
184
+ Then /^save and open all text emails$/ do
185
+ EmailSpec::EmailViewer::save_and_open_all_text_emails
186
+ end
187
+
188
+ Then /^save and open all html emails$/ do
189
+ EmailSpec::EmailViewer::save_and_open_all_html_emails
190
+ end
191
+
192
+ Then /^save and open all raw emails$/ do
193
+ EmailSpec::EmailViewer::save_and_open_all_raw_emails
194
+ end
@@ -0,0 +1,17 @@
1
+ # This generator adds email steps to the step definitions directory
2
+ generator_base = defined?(Rails) ? Rails::Generator::Base : RubiGen::Base
3
+ class EmailSpecGenerator < generator_base
4
+ def manifest
5
+ record do |m|
6
+ m.directory 'features/step_definitions'
7
+ m.file 'email_steps.rb', 'features/step_definitions/email_steps.rb'
8
+ end
9
+ end
10
+
11
+ protected
12
+
13
+ def banner
14
+ "Usage: #{$0} email_spec"
15
+ end
16
+
17
+ end
@@ -0,0 +1,182 @@
1
+ # Commonly used email steps
2
+ #
3
+ # To add your own steps make a custom_email_steps.rb
4
+ # The provided methods are:
5
+ #
6
+ # last_email_address
7
+ # reset_mailer
8
+ # open_last_email
9
+ # visit_in_email
10
+ # unread_emails_for
11
+ # mailbox_for
12
+ # current_email
13
+ # open_email
14
+ # read_emails_for
15
+ # find_email
16
+ #
17
+ # General form for email scenarios are:
18
+ # - clear the email queue (done automatically by email_spec)
19
+ # - execute steps that sends an email
20
+ # - check the user received an/no/[0-9] emails
21
+ # - open the email
22
+ # - inspect the email contents
23
+ # - interact with the email (e.g. click links)
24
+ #
25
+ # The Cucumber steps below are setup in this order.
26
+
27
+ module EmailHelpers
28
+ def current_email_address
29
+ # Replace with your a way to find your current email. e.g @current_user.email
30
+ # last_email_address will return the last email address used by email spec to find an email.
31
+ # Note that last_email_address will be reset after each Scenario.
32
+ last_email_address || "example@example.com"
33
+ end
34
+ end
35
+
36
+ World(EmailHelpers)
37
+
38
+ #
39
+ # Reset the e-mail queue within a scenario.
40
+ # This is done automatically before each scenario.
41
+ #
42
+
43
+ Given /^(?:a clear email queue|no emails have been sent)$/ do
44
+ reset_mailer
45
+ end
46
+
47
+ #
48
+ # Check how many emails have been sent/received
49
+ #
50
+
51
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails?$/ do |address, amount|
52
+ unread_emails_for(address).size.should == parse_email_count(amount)
53
+ end
54
+
55
+ Then /^(?:I|they|"([^"]*?)") should have (an|no|\d+) emails?$/ do |address, amount|
56
+ mailbox_for(address).size.should == parse_email_count(amount)
57
+ end
58
+
59
+ Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails? with subject "([^"]*?)"$/ do |address, amount, subject|
60
+ unread_emails_for(address).select { |m| m.subject =~ Regexp.new(subject) }.size.should == parse_email_count(amount)
61
+ end
62
+
63
+ Then /^(?:I|they|"([^"]*?)") should receive an email with the following body:$/ do |address, expected_body|
64
+ open_email(address, :with_text => expected_body)
65
+ end
66
+
67
+ #
68
+ # Accessing emails
69
+ #
70
+
71
+ # Opens the most recently received email
72
+ When /^(?:I|they|"([^"]*?)") opens? the email$/ do |address|
73
+ open_email(address)
74
+ end
75
+
76
+ When /^(?:I|they|"([^"]*?)") opens? the email with subject "([^"]*?)"$/ do |address, subject|
77
+ open_email(address, :with_subject => subject)
78
+ end
79
+
80
+ When /^(?:I|they|"([^"]*?)") opens? the email with text "([^"]*?)"$/ do |address, text|
81
+ open_email(address, :with_text => text)
82
+ end
83
+
84
+ #
85
+ # Inspect the Email Contents
86
+ #
87
+
88
+ Then /^(?:I|they) should see "([^"]*?)" in the email subject$/ do |text|
89
+ current_email.should have_subject(text)
90
+ end
91
+
92
+ Then /^(?:I|they) should see \/([^"]*?)\/ in the email subject$/ do |text|
93
+ current_email.should have_subject(Regexp.new(text))
94
+ end
95
+
96
+ Then /^(?:I|they) should see "([^"]*?)" in the email body$/ do |text|
97
+ current_email.body.should include(text)
98
+ end
99
+
100
+ Then /^(?:I|they) should see \/([^"]*?)\/ in the email body$/ do |text|
101
+ current_email.body.should =~ Regexp.new(text)
102
+ end
103
+
104
+ Then /^(?:I|they) should see the email delivered from "([^"]*?)"$/ do |text|
105
+ current_email.should be_delivered_from(text)
106
+ end
107
+
108
+ Then /^(?:I|they) should see "([^\"]*)" in the email "([^"]*?)" header$/ do |text, name|
109
+ current_email.should have_header(name, text)
110
+ end
111
+
112
+ Then /^(?:I|they) should see \/([^\"]*)\/ in the email "([^"]*?)" header$/ do |text, name|
113
+ current_email.should have_header(name, Regexp.new(text))
114
+ end
115
+
116
+ #
117
+ # Inspect the Email Attachments
118
+ #
119
+
120
+ Then /^(?:I|they) should see (an|no|\d+) attachments? with the email$/ do |amount|
121
+ current_email_attachments.size.should == parse_email_count(amount)
122
+ end
123
+
124
+ Then /^there should be (an|no|\d+) attachments? named "([^"]*?)"$/ do |amount, filename|
125
+ current_email_attachments.select { |a| a.original_filename == filename }.size.should == parse_email_count(amount)
126
+ end
127
+
128
+ Then /^attachment (\d+) should be named "([^"]*?)"$/ do |index, filename|
129
+ current_email_attachments[(index.to_i - 1)].original_filename.should == filename
130
+ end
131
+
132
+ Then /^there should be (an|no|\d+) attachments? of type "([^"]*?)"$/ do |amount, content_type|
133
+ current_email_attachments.select { |a| a.content_type == content_type }.size.should == parse_email_count(amount)
134
+ end
135
+
136
+ Then /^attachment (\d+) should be of type "([^"]*?)"$/ do |index, content_type|
137
+ current_email_attachments[(index.to_i - 1)].content_type.should == content_type
138
+ end
139
+
140
+ Then /^all attachments should not be blank$/ do
141
+ current_email_attachments.each do |attachment|
142
+ attachment.size.should_not == 0
143
+ end
144
+ end
145
+
146
+ Then /^show me a list of email attachments$/ do
147
+ EmailSpec::EmailViewer::save_and_open_email_attachments_list(current_email)
148
+ end
149
+
150
+ #
151
+ # Interact with Email Contents
152
+ #
153
+
154
+ When /^(?:I|they) follow "([^"]*?)" in the email$/ do |link|
155
+ visit_in_email(link)
156
+ end
157
+
158
+ When /^(?:I|they) click the first link in the email$/ do
159
+ click_first_link_in_email
160
+ end
161
+
162
+ #
163
+ # Debugging
164
+ # These only work with Rails and OSx ATM since EmailViewer uses RAILS_ROOT and OSx's 'open' command.
165
+ # Patches accepted. ;)
166
+ #
167
+
168
+ Then /^save and open current email$/ do
169
+ EmailSpec::EmailViewer::save_and_open_email(current_email)
170
+ end
171
+
172
+ Then /^save and open all text emails$/ do
173
+ EmailSpec::EmailViewer::save_and_open_all_text_emails
174
+ end
175
+
176
+ Then /^save and open all html emails$/ do
177
+ EmailSpec::EmailViewer::save_and_open_all_html_emails
178
+ end
179
+
180
+ Then /^save and open all raw emails$/ do
181
+ EmailSpec::EmailViewer::save_and_open_all_raw_emails
182
+ end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe EmailSpec::Helpers do
4
+ include EmailSpec::Helpers
5
+ describe "#parse_email_for_link" do
6
+ it "properly finds links with text" do
7
+ email = Mail.new(:body => %(<a href="/path/to/page">Click Here</a>))
8
+ parse_email_for_link(email, "Click Here").should == "/path/to/page"
9
+ end
10
+
11
+ it "recognizes img alt properties as text" do
12
+ email = Mail.new(:body => %(<a href="/path/to/page"><img src="http://host.com/images/image.gif" alt="an image" /></a>))
13
+ parse_email_for_link(email, "an image").should == "/path/to/page"
14
+ end
15
+
16
+ it "causes a spec to fail if the body doesn't contain the text specified to click" do
17
+ email = Mail.new(:body => "")
18
+ lambda { parse_email_for_link(email, "non-existent text") }.should raise_error( RSpec::Expectations::ExpectationNotMetError)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,430 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe EmailSpec::Matchers do
4
+ include EmailSpec::Matchers
5
+
6
+ class MatcherMatch
7
+ def initialize(object_to_test_match)
8
+ @object_to_test_match = object_to_test_match
9
+ end
10
+
11
+ def description
12
+ "match when provided #{@object_to_test_match.inspect}"
13
+ end
14
+
15
+ def matches?(matcher)
16
+ @matcher = matcher
17
+ matcher.matches?(@object_to_test_match)
18
+ end
19
+
20
+ def failure_message
21
+ "expected #{@matcher.inspect} to match when provided #{@object_to_test_match.inspect}, but it did not"
22
+ end
23
+
24
+ def negative_failure_message
25
+ "expected #{@matcher.inspect} not to match when provided #{@object_to_test_match.inspect}, but it did"
26
+ end
27
+ end
28
+
29
+ def match(object_to_test_match)
30
+ if object_to_test_match.is_a?(Regexp)
31
+ super # delegate to rspec's built in 'match' matcher
32
+ else
33
+ MatcherMatch.new(object_to_test_match)
34
+ end
35
+ end
36
+
37
+ describe "#reply_to" do
38
+ it "should match when the email is set to deliver to the specified address" do
39
+ email = Mail::Message.new(:reply_to => ["test@gmail.com"])
40
+ reply_to("test@gmail.com").should match(email)
41
+ end
42
+
43
+ it "should match given a name and address" do
44
+ email = Mail::Message.new(:reply_to => ["test@gmail.com"])
45
+ reply_to("David Balatero <test@gmail.com>").should match(email)
46
+ end
47
+
48
+ it "should give correct failure message when the email is not set to deliver to the specified address" do
49
+ matcher = reply_to("jimmy_bean@yahoo.com")
50
+ matcher.matches?(Mail::Message.new(:reply_to => ['freddy_noe@yahoo.com']).with_inspect_stub)
51
+ matcher.failure_message.should == %{expected email to reply to "jimmy_bean@yahoo.com", but it replied to "freddy_noe@yahoo.com"}
52
+ end
53
+
54
+ end
55
+
56
+ describe "#deliver_to" do
57
+ it "should match when the email is set to deliver to the specidied address" do
58
+ email = Mail::Message.new(:to => "jimmy_bean@yahoo.com")
59
+
60
+ deliver_to("jimmy_bean@yahoo.com").should match(email)
61
+ end
62
+
63
+ it "should match when a list of emails is exact same as all of the email's recipients" do
64
+ email = Mail::Message.new(:to => ["james@yahoo.com", "karen@yahoo.com"])
65
+
66
+ deliver_to("karen@yahoo.com", "james@yahoo.com").should match(email)
67
+ deliver_to("karen@yahoo.com").should_not match(email)
68
+ end
69
+
70
+ it "should match when an array of emails is exact same as all of the email's recipients" do
71
+ addresses = ["james@yahoo.com", "karen@yahoo.com"]
72
+ email = Mail::Message.new(:to => addresses)
73
+ deliver_to(addresses).should match(email)
74
+ end
75
+
76
+ it "should use the passed in objects :email method if not a string" do
77
+ email = Mail::Message.new(:to => "jimmy_bean@yahoo.com")
78
+ user = mock("user", :email => "jimmy_bean@yahoo.com")
79
+
80
+ deliver_to(user).should match(email)
81
+ end
82
+
83
+ it "should give correct failure message when the email is not set to deliver to the specified address" do
84
+ matcher = deliver_to("jimmy_bean@yahoo.com")
85
+ message = Mail::Message.new(:to => 'freddy_noe@yahoo.com')
86
+ message.stub(:inspect).and_return("email")
87
+ matcher.matches?(message)
88
+ matcher.failure_message.should == %{expected email to deliver to ["jimmy_bean@yahoo.com"], but it delivered to ["freddy_noe@yahoo.com"]}
89
+ end
90
+
91
+ end
92
+
93
+ describe "#deliver_from" do
94
+ it "should match when the email is set to deliver from the specified address" do
95
+ email = Mail::Message.new(:from => "jimmy_bean@yahoo.com")
96
+ deliver_from("jimmy_bean@yahoo.com").should match(email)
97
+ end
98
+
99
+ it "should match when the email is set to deliver from the specified name and address" do
100
+ email = Mail::Message.new(:from => "Jimmy Bean <jimmy_bean@yahoo.com>")
101
+ deliver_from("Jimmy Bean <jimmy_bean@yahoo.com>").should match(email)
102
+ end
103
+
104
+ it "should not match when the email does not have a sender" do
105
+ email = Mail::Message.new(:from => nil)
106
+ deliver_from("jimmy_bean@yahoo.com").should_not match(email)
107
+ end
108
+
109
+ it "should not match when the email addresses match but the names do not" do
110
+ email = Mail::Message.new(:from => "Jimmy Bean <jimmy_bean@yahoo.com>")
111
+ deliver_from("Freddy Noe <jimmy_bean@yahoo.com>").should_not match(email)
112
+ end
113
+
114
+ it "should not match when the names match but the email addresses do not" do
115
+ email = Mail::Message.new(:from => "Jimmy Bean <jimmy_bean@yahoo.com>")
116
+ deliver_from("Jimmy Bean <freddy_noe@yahoo.com>").should_not match(email)
117
+ end
118
+
119
+ it "should not match when the email is not set to deliver from the specified address" do
120
+ email = Mail::Message.new(:from => "freddy_noe@yahoo.com")
121
+ deliver_from("jimmy_bean@yahoo.com").should_not match(email)
122
+ end
123
+
124
+ it "should give correct failure message when the email is not set to deliver from the specified address" do
125
+ matcher = deliver_from("jimmy_bean@yahoo.com")
126
+ matcher.matches?(Mail::Message.new(:from => "freddy_noe@yahoo.com"))
127
+ matcher.failure_message.should =~ /expected .+ to deliver from "jimmy_bean@yahoo\.com", but it delivered from "freddy_noe@yahoo\.com"/
128
+ end
129
+
130
+ end
131
+
132
+ describe "#bcc_to" do
133
+
134
+ it "should match when the email is set to deliver to the specidied address" do
135
+ email = Mail::Message.new(:bcc => "jimmy_bean@yahoo.com")
136
+
137
+ bcc_to("jimmy_bean@yahoo.com").should match(email)
138
+ end
139
+
140
+ it "should match when a list of emails is exact same as all of the email's recipients" do
141
+ email = Mail::Message.new(:bcc => ["james@yahoo.com", "karen@yahoo.com"])
142
+
143
+ bcc_to("karen@yahoo.com", "james@yahoo.com").should match(email)
144
+ bcc_to("karen@yahoo.com").should_not match(email)
145
+ end
146
+
147
+ it "should match when an array of emails is exact same as all of the email's recipients" do
148
+ addresses = ["james@yahoo.com", "karen@yahoo.com"]
149
+ email = Mail::Message.new(:bcc => addresses)
150
+ bcc_to(addresses).should match(email)
151
+ end
152
+
153
+ it "should use the passed in objects :email method if not a string" do
154
+ email = Mail::Message.new(:bcc => "jimmy_bean@yahoo.com")
155
+ user = mock("user", :email => "jimmy_bean@yahoo.com")
156
+
157
+ bcc_to(user).should match(email)
158
+ end
159
+
160
+ end
161
+
162
+ describe "#have_subject" do
163
+
164
+ describe "when regexps are used" do
165
+
166
+ it "should match when the subject matches regexp" do
167
+ email = Mail::Message.new(:subject => ' -- The Subject --')
168
+
169
+ have_subject(/The Subject/).should match(email)
170
+ have_subject(/foo/).should_not match(email)
171
+ end
172
+
173
+ it "should have a helpful description" do
174
+ matcher = have_subject(/foo/)
175
+ matcher.matches?(Mail::Message.new(:subject => "bar"))
176
+
177
+ matcher.description.should == "have subject matching /foo/"
178
+ end
179
+
180
+ it "should offer helpful failing messages" do
181
+ matcher = have_subject(/foo/)
182
+ matcher.matches?(Mail::Message.new(:subject => "bar"))
183
+
184
+ matcher.failure_message.should == 'expected the subject to match /foo/, but did not. Actual subject was: "bar"'
185
+ end
186
+
187
+ it "should offer helpful negative failing messages" do
188
+ matcher = have_subject(/b/)
189
+ matcher.matches?(Mail::Message.new(:subject => "bar"))
190
+
191
+ matcher.negative_failure_message.should == 'expected the subject not to match /b/ but "bar" does match it.'
192
+ end
193
+ end
194
+
195
+ describe "when strings are used" do
196
+ it "should match when the subject equals the passed in string exactly" do
197
+ email = Mail::Message.new(:subject => 'foo')
198
+
199
+ have_subject("foo").should match(email)
200
+ have_subject(" - foo -").should_not match(email)
201
+ end
202
+
203
+ it "should have a helpful description" do
204
+ matcher = have_subject("foo")
205
+ matcher.matches?(Mail::Message.new(:subject => "bar"))
206
+
207
+ matcher.description.should == 'have subject of "foo"'
208
+ end
209
+
210
+ it "should offer helpful failing messages" do
211
+ matcher = have_subject("foo")
212
+ matcher.matches?(Mail::Message.new(:subject => "bar"))
213
+
214
+ matcher.failure_message.should == 'expected the subject to be "foo" but was "bar"'
215
+ end
216
+
217
+ it "should offer helpful negative failing messages" do
218
+ matcher = have_subject("bar")
219
+ matcher.matches?(Mail::Message.new(:subject => "bar"))
220
+
221
+ matcher.negative_failure_message.should == 'expected the subject not to be "bar" but was'
222
+ end
223
+ end
224
+ end
225
+
226
+ describe "#include_email_with_subject" do
227
+
228
+ describe "when regexps are used" do
229
+
230
+ it "should match when any email's subject matches passed in regexp" do
231
+ emails = [Mail::Message.new(:subject => "foobar"), Mail::Message.new(:subject => "bazqux")]
232
+
233
+ include_email_with_subject(/foo/).should match(emails)
234
+ include_email_with_subject(/quux/).should_not match(emails)
235
+ end
236
+
237
+ it "should have a helpful description" do
238
+ matcher = include_email_with_subject(/foo/)
239
+ matcher.matches?([])
240
+
241
+ matcher.description.should == 'include email with subject matching /foo/'
242
+ end
243
+
244
+ it "should offer helpful failing messages" do
245
+ matcher = include_email_with_subject(/foo/)
246
+ matcher.matches?([Mail::Message.new(:subject => "bar")])
247
+
248
+ matcher.failure_message.should == 'expected at least one email to have a subject matching /foo/, but none did. Subjects were ["bar"]'
249
+ end
250
+
251
+ it "should offer helpful negative failing messages" do
252
+ matcher = include_email_with_subject(/foo/)
253
+ matcher.matches?([Mail::Message.new(:subject => "foo")])
254
+
255
+ matcher.negative_failure_message.should == 'expected no email to have a subject matching /foo/ but found at least one. Subjects were ["foo"]'
256
+ end
257
+ end
258
+
259
+ describe "when strings are used" do
260
+ it "should match when any email's subject equals passed in subject exactly" do
261
+ emails = [Mail::Message.new(:subject => "foobar"), Mail::Message.new(:subject => "bazqux")]
262
+
263
+ include_email_with_subject("foobar").should match(emails)
264
+ include_email_with_subject("foo").should_not match(emails)
265
+ end
266
+
267
+ it "should have a helpful description" do
268
+ matcher = include_email_with_subject("foo")
269
+ matcher.matches?([])
270
+
271
+ matcher.description.should == 'include email with subject of "foo"'
272
+ end
273
+
274
+ it "should offer helpful failing messages" do
275
+ matcher = include_email_with_subject("foo")
276
+ matcher.matches?([Mail::Message.new(:subject => "bar")])
277
+
278
+ matcher.failure_message.should == 'expected at least one email to have the subject "foo" but none did. Subjects were ["bar"]'
279
+ end
280
+
281
+ it "should offer helpful negative failing messages" do
282
+ matcher = include_email_with_subject("foo")
283
+ matcher.matches?([Mail::Message.new(:subject => "foo")])
284
+
285
+ matcher.negative_failure_message.should == 'expected no email with the subject "foo" but found at least one. Subjects were ["foo"]'
286
+ end
287
+ end
288
+ end
289
+
290
+ describe "#have_body_text" do
291
+ describe "when regexps are used" do
292
+ it "should match when the body matches regexp" do
293
+ email = Mail::Message.new(:body => 'foo bar baz')
294
+
295
+ have_body_text(/bar/).should match(email)
296
+ have_body_text(/qux/).should_not match(email)
297
+ end
298
+
299
+ it "should have a helpful description" do
300
+ matcher = have_body_text(/qux/)
301
+ matcher.matches?(Mail::Message.new(:body => 'foo bar baz'))
302
+
303
+ matcher.description.should == 'have body matching /qux/'
304
+ end
305
+
306
+ it "should offer helpful failing messages" do
307
+ matcher = have_body_text(/qux/)
308
+ matcher.matches?(Mail::Message.new(:body => 'foo bar baz'))
309
+
310
+ matcher.failure_message.should == 'expected the body to match /qux/, but did not. Actual body was: "foo bar baz"'
311
+ end
312
+
313
+ it "should offer helpful negative failing messages" do
314
+ matcher = have_body_text(/bar/)
315
+ matcher.matches?(Mail::Message.new(:body => 'foo bar baz'))
316
+
317
+ matcher.negative_failure_message.should == 'expected the body not to match /bar/ but "foo bar baz" does match it.'
318
+ end
319
+ end
320
+
321
+ describe "when strings are used" do
322
+ it "should match when the body includes the text" do
323
+ email = Mail::Message.new(:body => 'foo bar baz')
324
+
325
+ have_body_text('bar').should match(email)
326
+ have_body_text('qux').should_not match(email)
327
+ end
328
+
329
+ it "should have a helpful description" do
330
+ matcher = have_body_text('qux')
331
+ matcher.matches?(Mail::Message.new(:body => 'foo bar baz'))
332
+
333
+ matcher.description.should == 'have body including "qux"'
334
+ end
335
+
336
+ it "should offer helpful failing messages" do
337
+ matcher = have_body_text('qux')
338
+ matcher.matches?(Mail::Message.new(:body => 'foo bar baz'))
339
+
340
+ matcher.failure_message.should == 'expected the body to contain "qux" but was "foo bar baz"'
341
+ end
342
+
343
+ it "should offer helpful negative failing messages" do
344
+ matcher = have_body_text('bar')
345
+ matcher.matches?(Mail::Message.new(:body => 'foo bar baz'))
346
+
347
+ matcher.negative_failure_message.should == 'expected the body not to contain "bar" but was "foo bar baz"'
348
+ end
349
+ end
350
+
351
+ describe "when dealing with multipart messages" do
352
+ it "should look at the html part" do
353
+ email = Mail.new do
354
+ text_part do
355
+ body "This is text"
356
+ end
357
+ html_part do
358
+ body "This is html"
359
+ end
360
+ end
361
+ have_body_text(/This is html/).should match(email)
362
+ have_body_text(/This is text/).should_not match(email)
363
+ end
364
+ end
365
+ end
366
+
367
+ describe "#have_header" do
368
+ describe "when regexps are used" do
369
+ it "should match when header matches passed in regexp" do
370
+ email = Mail::Message.new(:content_type => "text/html")
371
+
372
+ have_header(:content_type, /text/).should match(email)
373
+ have_header(:foo, /text/).should_not match(email)
374
+ have_header(:content_type, /bar/).should_not match(email)
375
+ end
376
+
377
+ it "should have a helpful description" do
378
+ matcher = have_header(:content_type, /bar/)
379
+ matcher.matches?(Mail::Message.new(:content_type => "text/html"))
380
+
381
+ matcher.description.should == 'have header content_type with value matching /bar/'
382
+ end
383
+
384
+ it "should offer helpful failing messages" do
385
+ matcher = have_header(:content_type, /bar/)
386
+ matcher.matches?(Mail::Message.new(:content_type => "text/html"))
387
+
388
+ matcher.failure_message.should == 'expected the headers to include \'content_type\' with a value matching /bar/ but they were {"content-type"=>"text/html"}'
389
+ end
390
+
391
+ it "should offer helpful negative failing messages" do
392
+ matcher = have_header(:content_type, /text/)
393
+ matcher.matches?(Mail::Message.new(:content_type => "text/html"))
394
+
395
+ matcher.negative_failure_message.should == 'expected the headers not to include \'content_type\' with a value matching /text/ but they were {"content-type"=>"text/html"}'
396
+ end
397
+ end
398
+
399
+ describe "when strings are used" do
400
+ it "should match when header equals passed in value exactly" do
401
+ email = Mail::Message.new(:content_type => "text/html")
402
+
403
+ have_header(:content_type, 'text/html').should match(email)
404
+ have_header(:foo, 'text/html').should_not match(email)
405
+ have_header(:content_type, 'text').should_not match(email)
406
+ end
407
+
408
+ it "should have a helpful description" do
409
+ matcher = have_header(:content_type, 'text')
410
+ matcher.matches?(Mail::Message.new(:content_type => "text/html"))
411
+
412
+ matcher.description.should == 'have header content_type: text'
413
+ end
414
+
415
+ it "should offer helpful failing messages" do
416
+ matcher = have_header(:content_type, 'text')
417
+ matcher.matches?(Mail::Message.new(:content_type => "text/html"))
418
+
419
+ matcher.failure_message.should == 'expected the headers to include \'content_type: text\' but they were {"content-type"=>"text/html"}'
420
+ end
421
+
422
+ it "should offer helpful negative failing messages" do
423
+ matcher = have_header(:content_type, 'text/html')
424
+ matcher.matches?(Mail::Message.new(:content_type => "text/html"))
425
+
426
+ matcher.negative_failure_message == 'expected the headers not to include \'content_type: text/html\' but they were {:content_type=>"text/html"}'
427
+ end
428
+ end
429
+ end
430
+ end