PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/README.md

http://github.com/bmabey/email-spec
Markdown | 349 lines | 241 code | 108 blank | 0 comment | 0 complexity | 5513c21e4cce35b58b0c1a69c2f50618 MD5 | raw file
  1. [![Build Status](https://secure.travis-ci.org/email-spec/email-spec.svg)](http://travis-ci.org/email-spec/email-spec)
  2. ## Email Spec
  3. A collection of matchers for `RSpec`, `MiniTest` and `Cucumber` steps to make testing emails go smoothly.
  4. This library works with `ActionMailer` and `Pony`. When using it with ActionMailer it works with ActiveRecord Mailer, and [action_mailer_cache_delivery](https://rubygems.org/gems/action_mailer_cache_delivery).
  5. If you are testing emails in conjunction with an automated browser solution, like Selenium,
  6. you will want to use [action_mailer_cache_delivery](http://rubygems.org/gems/action_mailer_cache_delivery) in your test environment. (This is
  7. because your test process and server processes are distinct and therefore need an
  8. intermediate store for the emails.) ActiveRecord Mailer will also work but
  9. you generally don't want to include those projects unless you need them in production.
  10. ### Gem Setup
  11. ```ruby
  12. # Gemfile
  13. group :test do
  14. gem 'email_spec'
  15. end
  16. ```
  17. ### Cucumber
  18. To use the steps in features put the following in your env.rb:
  19. ```ruby
  20. # Make sure this require is after you require cucumber/rails/world.
  21. require 'email_spec' # add this line if you use spork
  22. require 'email_spec/cucumber'
  23. ```
  24. This will load all the helpers that the steps rely on. It will also add a `Before` hook for `Cucumber` so that emails are cleared at the start of each scenario.
  25. Then:
  26. ```bash
  27. rails generate email_spec:steps
  28. ```
  29. This will give you a bunch of steps to get started with in `step_definitions/email_steps.rb`
  30. By default, the generated file will look for email to example@example.com. You can either change this by editing the `current_email_address` method in `email_steps.rb`, or by simply specifying the target email in your features:
  31. ```gherkin
  32. Scenario: A new person signs up
  33. Given I am at "/"
  34. When I fill in "Email" with "quentin@example.com"
  35. And I press "Sign up"
  36. Then "quentin@example.com" should receive an email # Specify who should receive the email
  37. ```
  38. ### Spinach
  39. To use the helpers and matchers in your Spinach steps, add this to your env.rb:
  40. ```ruby
  41. require 'email_spec/spinach'
  42. ```
  43. Creating shared steps (as for Cucumber above) doesn't fit so well with the Spinach ethos of very compartmentalized steps, so there is no generator for Spinach. It's easy to use the helpers/matchers in your steps. For example:
  44. ```ruby
  45. step 'the last email sent should welcome the user' do
  46. expect(last_email_sent).to have_subject('Welcome')
  47. end
  48. ```
  49. ### RSpec (3.1+)
  50. First you need to require `email_spec` in your `spec_helper.rb`:
  51. ```ruby
  52. require "email_spec"
  53. require "email_spec/rspec"
  54. ```
  55. This will load all the helpers that the scenarios can count on. It will also add a `before(:each)` hook so that emails are cleared at the start of each scenario.
  56. If you are upgrading to Rails 5, make sure your `rails_helper.rb` requires `spec_helper` **after** loading the environment. For example:
  57. ```ruby
  58. require File.expand_path('../../config/environment', __FILE__)
  59. require 'spec_helper'
  60. ```
  61. ### MiniTest
  62. First you need to require minitest-matchers and email_spec in your test_helper.rb:
  63. ```ruby
  64. require "minitest-matchers"
  65. require "email_spec"
  66. ```
  67. You will then need to include EmailSpec::Helpers and EmailSpec::Matchers in your test classes.
  68. If you want to have access to the helpers and matchers in all of your tests you can do the following in your test_helper.rb:
  69. ```ruby
  70. class MiniTest::Unit::TestCase
  71. include EmailSpec::Helpers
  72. include EmailSpec::Matchers
  73. end
  74. ```
  75. Otherwise, you will need to include them in the tests where you use them:
  76. ```ruby
  77. class SignupMailerTest < MiniTest::Unit::TestCase
  78. include EmailSpec::Helpers
  79. include EmailSpec::Matchers
  80. ...
  81. end
  82. ```
  83. Or, if you are using the MiniTest spec DSL, it would look like this:
  84. ```ruby
  85. describe SignupMailer do
  86. include EmailSpec::Helpers
  87. include EmailSpec::Matchers
  88. ...
  89. end
  90. ```
  91. ### Turnip
  92. If you're using [Turnip](https://github.com/jnicklas/turnip), you might be interested in this [conversion of the Cucumber steps into Turnip steps](https://github.com/jmuheim/base/blob/7708873e77165993c2c962894c756621be1b15cc/spec/steps/email_steps.rb).
  93. ## Background Jobs
  94. If you are using a background job, you might need to use a step to process the jobs. Another alternative is to use an inline statement for your scenario.
  95. For example, for DelayedJob:
  96. ```ruby
  97. Delayed::Worker.delay_jobs = false
  98. ```
  99. ## Usage
  100. ### Cucumber
  101. ```gherkin
  102. Scenario: A new person signs up
  103. Given I am at "/"
  104. When I fill in "Email" with "quentin@example.com"
  105. And I press "Sign up"
  106. And I should receive an email
  107. When I open the email
  108. Then I should see "confirm" in the email body
  109. When I follow "confirm" in the email
  110. Then I should see "Confirm your new account"
  111. ```
  112. For more examples, check out examples/rails_root in the source for a small example app that implements these steps.
  113. ### Cucumber Matchers (Ruby)
  114. See RSpec Matchers (they are the same)
  115. ### RSpec
  116. #### Testing In Isolation
  117. It is often useful to test your mailers in isolation. You can accomplish this by using mocks to verify that the mailer is being called in the correct place and then write focused examples for the actual mailer. This is a simple example from the sample app found in the gem:
  118. Verify that the mailer is used correctly in the controller (this would apply to a model as well):
  119. ```ruby
  120. describe "POST /signup (#signup)" do
  121. it "should deliver the signup email" do
  122. # expect
  123. expect(UserMailer).to(receive(:deliver_signup).with("email@example.com", "Jimmy Bean"))
  124. # when
  125. post :signup, "Email" => "email@example.com", "Name" => "Jimmy Bean"
  126. end
  127. end
  128. ```
  129. Examples for the #signup method in UserMailer:
  130. ```ruby
  131. describe "Signup Email" do
  132. include EmailSpec::Helpers
  133. include EmailSpec::Matchers
  134. # include ActionController::UrlWriter - old rails
  135. include Rails.application.routes.url_helpers
  136. before(:all) do
  137. @email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  138. end
  139. it "should be set to be delivered to the email passed in" do
  140. expect(@email).to deliver_to("jojo@yahoo.com")
  141. end
  142. it "should contain the user's message in the mail body" do
  143. expect(@email).to have_body_text(/Jojo Binks/)
  144. end
  145. it "should contain a link to the confirmation link" do
  146. expect(@email).to have_body_text(/#{confirm_account_url}/)
  147. end
  148. it "should have the correct subject" do
  149. expect(@email).to have_subject(/Account confirmation/)
  150. end
  151. end
  152. ```
  153. #### RSpec Matchers
  154. ##### reply_to(email)
  155. alias: `have_reply_to`
  156. This checks that the Reply-To header's email address (the bob@example.com of
  157. "Bob Saget <bob@example.com>") is set to the given string.
  158. ```ruby
  159. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  160. expect(email).to reply_to("support@myapp.com")
  161. ```
  162. ##### deliver_to(\*email_addresses)
  163. alias: `be_delivered_to`
  164. This checks that the To header's email addresses (the bob@example.com of
  165. "Bob Saget <bob@example.com>") are set to the addresses.
  166. ```ruby
  167. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  168. expect(email).to deliver_to("jojo@yahoo.com")
  169. ```
  170. ##### deliver_from(email)
  171. alias: `be_delivered_from`
  172. This checks that the From header's email address (the bob@example.com of
  173. "Bob Saget <bob@example.com>") is set to the given string.
  174. ```ruby
  175. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  176. expect(email).to deliver_from("sally@yahoo.com")
  177. ```
  178. ##### bcc_to(\*email_addresses)
  179. This checks that the BCC header's email addresses (the bob@example.com of
  180. "Bob Saget <bob@example.com>") are set to the addresses.
  181. ```ruby
  182. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  183. expect(email).to bcc_to("sue@yahoo.com", "bill@yahoo.com")
  184. ```
  185. ##### cc_to(\*email_addresses)
  186. This checks that the CC header's email addresses (the bob@example.com of
  187. "Bob Saget <bob@example.com>") are set to the addresses.
  188. ```ruby
  189. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  190. expect(email).to cc_to("sue@yahoo.com", "bill@yahoo.com")
  191. ```
  192. ##### have_subject(subject)
  193. This checks that the Subject header's value is set to the given subject.
  194. ```ruby
  195. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  196. expect(email).to have_subject("Welcome!")
  197. ```
  198. ##### include_email_with_subject(subject)
  199. Note: subject can be either a String or a Regexp
  200. This checks that one of the given emails' subjects includes the subject.
  201. ```ruby
  202. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  203. email2 = UserMailer.forgot_password("jojo@yahoo.com", "Jojo Binks")
  204. expect([email, email2]).to include_email_with_subject("Welcome!")
  205. ```
  206. ##### have_body_text(text)
  207. Note: text can be either a String or a Regexp
  208. This checks that the text of the body has the given body.
  209. ```ruby
  210. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  211. expect(email).to have_body_text(/Hi Jojo Binks,/)
  212. ```
  213. ##### have_header(key, value)
  214. This checks that the expected key/value pair is in the headers of the email.
  215. ```ruby
  216. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  217. expect(email).to have_header("X-Campaign", "1234abc")
  218. ```
  219. #### Using the helpers when not testing in isolation
  220. Don't. :) Seriously, if you do just take a look at the helpers and use them as you wish.
  221. ### MiniTest
  222. You will use EmailSpec in your tests the same way you use it in your specs. The only difference is the use of MiniTest's `must` instead of Rspec's `should`:
  223. ```ruby
  224. email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")
  225. email.must deliver_to("jojo@yahoo.com")
  226. ```
  227. Or, you can use the matcher as an expectation:
  228. ```ruby
  229. email = UserMailer.create_signup "jojo@yahoo.com", "Jojo Binks"
  230. email.must_deliver_to "jojo@yahoo.com"
  231. ```
  232. And of course you can use the matcher as an assertion:
  233. ```ruby
  234. email = UserMailer.create_signup "jojo@yahoo.com", "Jojo Binks"
  235. assert_must deliver_to("jojo@yahoo.com"), email
  236. ```
  237. ## Issue triage [![Open Source Helpers](https://www.codetriage.com/email-spec/email-spec/badges/users.svg)](https://www.codetriage.com/email-spec/email-spec)
  238. You can contribute by triaging issues which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to email-spec on CodeTriage](https://www.codetriage.com/email-spec/email-spec).
  239. ## Original Authors
  240. Ben Mabey, Aaron Gibralter, Mischa Fierer
  241. Please see [Changelog.md](Changelog.md) for upcoming changes and other contributors.