email-spec-1.6.0/0000755000175000017500000000000012766555077012605 5ustar pravipraviemail-spec-1.6.0/README.md0000644000175000017500000002236612766555077014075 0ustar pravipravi [![Build Status](https://secure.travis-ci.org/bmabey/email-spec.png)](http://travis-ci.org/bmabey/email-spec) ## Email Spec A collection of matchers for RSpec/MiniTest and Cucumber steps to make testing emails go smoothly. This library works with ActionMailer and Pony. When using it with ActionMailer it works with DelayedJob, ActiveRecord Mailer, and action_mailer_cache_delivery. If you are testing emails in conjunction with an automated browser solution, like Selenium, you will want to use [action_mailer_cache_delivery](http://rubygems.org/gems/action_mailer_cache_delivery) in your test environment. (This is because your test process and server processes are distinct and therefore need an intermediate store for the emails.) DelayedJob and ActiveRecord Mailer will also work but you generally don't want to include those projects unless you need them in production. ## Setup ```bash script/plugin install git://github.com/bmabey/email-spec.git ``` ### Gem Setup ```ruby gem install email_spec # Gemfile group :test do gem 'email_spec' end ``` ### Cucumber To use the steps in features put the following in your env.rb: ```ruby # Make sure this require is after you require cucumber/rails/world. require 'email_spec' # add this line if you use spork require 'email_spec/cucumber' ``` 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. Then: ```bash rails generate email_spec:steps ``` This will give you a bunch of steps to get started with in step_definitions/email_steps.rb 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: ```gherkin Scenario: A new person signs up Given I am at "/" When I fill in "Email" with "quentin@example.com" And I press "Sign up" And "quentin@example.com" should receive an email # Specify who should receive the email ``` ### RSpec First you need to require email_spec in your spec_helper.rb: ```ruby require "email_spec" ``` You will then need to include EmailSpec::Helpers and EmailSpec::Matchers in your example groups. If you want to have access to the helpers and matchers in all of your examples you can do the following in your spec_helper.rb: ```ruby RSpec.configure do |config| config.include(EmailSpec::Helpers) config.include(EmailSpec::Matchers) end ``` Otherwise, you will need to include them in the example groups you wish to use them: ```ruby describe "Signup Email" do include EmailSpec::Helpers include EmailSpec::Matchers ... end ``` ### MiniTest First you need to require minitest-matchers and email_spec in your test_helper.rb: ```ruby require "minitest-matchers" require "email_spec" ``` You will then need to include EmailSpec::Helpers and EmailSpec::Matchers in your test classes. 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: ```ruby class MiniTest::Unit::TestCase include EmailSpec::Helpers include EmailSpec::Matchers end ``` Otherwise, you will need to include them in the tests where you use them: ```ruby class SignupMailerTest < MiniTest::Unit::TestCase include EmailSpec::Helpers include EmailSpec::Matchers ... end ``` Or, if you are using the MiniTest spec DSL, it would look like this: ```ruby describe SignupMailer do include EmailSpec::Helpers include EmailSpec::Matchers ... end ``` ### Turnip 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/transition/blob/master/spec/support/steps/email_steps.rb). ## Usage ### Cucumber ```gherkin Scenario: A new person signs up Given I am at "/" When I fill in "Email" with "quentin@example.com" And I press "Sign up" And I should receive an email When I open the email Then I should see "confirm" in the email body When I follow "confirm" in the email Then I should see "Confirm your new account" ``` For more examples, check out examples/rails_root in the source for a small example app that implements these steps. ### Cucumber Matchers (Ruby) See RSpec Matchers (they are the same) ### RSpec #### Testing In Isolation 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: Verify that the mailer is used correctly in the controller (this would apply to a model as well): ```ruby describe "POST /signup (#signup)" do it "should deliver the signup email" do # expect UserMailer.should_receive(:deliver_signup).with("email@example.com", "Jimmy Bean") # when post :signup, "Email" => "email@example.com", "Name" => "Jimmy Bean" end end ``` Examples for the #signup method in UserMailer: ```ruby describe "Signup Email" do include EmailSpec::Helpers include EmailSpec::Matchers # include ActionController::UrlWriter - old rails include Rails.application.routes.url_helpers before(:all) do @email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") end it "should be set to be delivered to the email passed in" do @email.should deliver_to("jojo@yahoo.com") end it "should contain the user's message in the mail body" do @email.should have_body_text(/Jojo Binks/) end it "should contain a link to the confirmation link" do @email.should have_body_text(/#{confirm_account_url}/) end it "should have the correct subject" do @email.should have_subject(/Account confirmation/) end end ``` #### RSpec Matchers ##### reply_to(email) alias: `have_reply_to` This checks that the Reply-To header's email address (the bob@example.com of "Bob Saget ") is set to the given string. ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email.should reply_to("support@myapp.com") ``` ##### deliver_to(*email_addresses) alias: `be_delivered_to` This checks that the To header's email addresses (the bob@example.com of "Bob Saget ") are set to the addresses. ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email.should deliver_to("jojo@yahoo.com") ``` ##### deliver_from(email) alias: `be_delivered_from` This checks that the From header's email address (the bob@example.com of "Bob Saget ") is set to the given string. ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email.should deliver_from("sally@yahoo.com") ``` ##### bcc_to(*email_addresses) This checks that the BCC header's email addresses (the bob@example.com of "Bob Saget ") are set to the addresses. ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email.should bcc_to("sue@yahoo.com", "bill@yahoo.com") ``` ##### cc_to(*email_addresses) This checks that the CC header's email addresses (the bob@example.com of "Bob Saget ") are set to the addresses. ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email.should cc_to("sue@yahoo.com", "bill@yahoo.com") ``` ##### have_subject(subject) This checks that the Subject header's value is set to the given subject. ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email.should have_subject("Welcome!") ``` ##### include_email_with_subject(subject) Note: subject can be either a String or a Regexp This checks that one of the given emails' subjects includes the subject. ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email2 = UserMailer.forgot_password("jojo@yahoo.com", "Jojo Binks") [email, email2].should include_email_with_subject("Welcome!") ``` ##### have_body_text(text) Note: text can be either a String or a Regexp This checks that the text of the body has the given body. ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email.should have_body_text(/Hi Jojo Binks,/) ``` ##### have_header(key, value) This checks that the expected key/value pair is in the headers of the email. ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email.should have_header("X-Campaign", "1234abc") ``` #### Using the helpers when not testing in isolation Don't. :) Seriously, if you do just take a look at the helpers and use them as you wish. ### MiniTest 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`: ```ruby email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks") email.must deliver_to("jojo@yahoo.com") ``` Or, you can use the matcher as an expectation: ```ruby email = UserMailer.create_signup "jojo@yahoo.com", "Jojo Binks" email.must_deliver_to "jojo@yahoo.com" ``` And of course you can use the matcher as an assertion: ```ruby email = UserMailer.create_signup "jojo@yahoo.com", "Jojo Binks" assert_must deliver_to("jojo@yahoo.com"), email ``` ## Original Authors Ben Mabey, Aaron Gibralter, Mischa Fierer Please see History.txt for upcoming changsets and other contributors. email-spec-1.6.0/rails_generators/0000755000175000017500000000000012766555077016150 5ustar pravipraviemail-spec-1.6.0/rails_generators/email_spec/0000755000175000017500000000000012766555077020251 5ustar pravipraviemail-spec-1.6.0/rails_generators/email_spec/email_spec_generator.rb0000644000175000017500000000064712766555077024754 0ustar pravipravi# This generator adds email steps to the step definitions directory generator_base = defined?(Rails) ? Rails::Generator::Base : RubiGen::Base class EmailSpecGenerator < generator_base def manifest record do |m| m.directory 'features/step_definitions' m.file 'email_steps.rb', 'features/step_definitions/email_steps.rb' end end protected def banner "Usage: #{$0} email_spec" end end email-spec-1.6.0/rails_generators/email_spec/templates/0000755000175000017500000000000012766555077022247 5ustar pravipraviemail-spec-1.6.0/rails_generators/email_spec/templates/email_steps.rb0000644000175000017500000001351712766555077025110 0ustar pravipravi# Commonly used email steps # # To add your own steps make a custom_email_steps.rb # The provided methods are: # # last_email_address # reset_mailer # open_last_email # visit_in_email # unread_emails_for # mailbox_for # current_email # open_email # read_emails_for # find_email # # General form for email scenarios are: # - clear the email queue (done automatically by email_spec) # - execute steps that sends an email # - check the user received an/no/[0-9] emails # - open the email # - inspect the email contents # - interact with the email (e.g. click links) # # The Cucumber steps below are setup in this order. module EmailHelpers def current_email_address # Replace with your way to find your current email (e.g @current_user.email). # last_email_address will return the last email address used by email spec to find an email. # Note that last_email_address will be reset after each Scenario. last_email_address || "example@example.com" end end World(EmailHelpers) # # Reset the e-mail queue within a scenario. # This is done automatically before each scenario. # Given /^(?:a clear email queue|no emails have been sent)$/ do reset_mailer end # # Check how many emails have been sent/received # Then /^(?:I|they|he|she|"([^"]*?)") should receive (an|no|\d+) emails?$/ do |address, amount| unread_emails_for(address).size.should == parse_email_count(amount) end Then /^(?:I|they|he|she|"([^"]*?)") should have (an|no|\d+) emails?$/ do |address, amount| mailbox_for(address).size.should == parse_email_count(amount) end Then /^(?:I|they|he|she|"([^"]*?)") should receive (an|no|\d+) emails? with subject "([^"]*?)"$/ do |address, amount, subject| unread_emails_for(address).select { |m| m.subject =~ Regexp.new(Regexp.escape(subject)) }.size.should == parse_email_count(amount) end Then /^(?:I|they|he|she|"([^"]*?)") should receive an email with the following body:$/ do |address, expected_body| open_email(address, :with_text => expected_body) end # # Accessing emails # # Opens the most recently received email When /^(?:I|they|he|she|"([^"]*?)") opens? the email$/ do |address| open_email(address) end When /^(?:I|they|he|she|"([^"]*?)") opens? the email with subject "([^"]*?)"$/ do |address, subject| open_email(address, :with_subject => subject) end When /^(?:I|they|he|she|"([^"]*?)") opens? the email with text "([^"]*?)"$/ do |address, text| open_email(address, :with_text => text) end # # Inspect the Email Contents # Then /^(?:I|they|he|she) should see "([^"]*?)" in the email subject$/ do |text| current_email.should have_subject(text) end Then /^(?:I|they|he|she) should see "([^"]*?)" in the email body$/ do |text| if current_email.multipart? Then %(I should see "#{text}" in the html part of the email body) Then %(I should see "#{text}" in the text part of the email body) else current_email.body.should =~ Regexp.new(text) end end Then /^(?:I|they|he|she) should see "([^"]*?)" in the html part of the email body$/ do |text| current_email.html_part.body.should =~ Regexp.new(text) end Then /^(?:I|they|he|she) should see "([^"]*?)" in the text part of the email body$/ do |text| current_email.text_part.body.should =~ Regexp.new(text) end Then /^(?:I|they|he|she) should see "([^"]*?)" in the email body$/ do |text| current_email.body.should include(text) end Then /^(?:I|they|he|she) should see \/([^"]*?)\/ in the email body$/ do |text| current_email.body.should =~ Regexp.new(text) end Then /^(?:I|they|he|she) should see the email delivered from "([^"]*?)"$/ do |text| current_email.should be_delivered_from(text) end Then /^(?:I|they|he|she) should see "([^\"]*)" in the email "([^"]*?)" header$/ do |text, name| current_email.should have_header(name, text) end Then /^(?:I|they|he|she) should see \/([^\"]*)\/ in the email "([^"]*?)" header$/ do |text, name| current_email.should have_header(name, Regexp.new(text)) end # # Inspect the Email Attachments # Then /^(?:I|they|he|she) should see (an|no|\d+) attachments? with the email$/ do |amount| current_email_attachments.size.should == parse_email_count(amount) end Then /^there should be (an|no|\d+) attachments? named "([^"]*?)"$/ do |amount, filename| current_email_attachments.select { |a| a.original_filename == filename }.size.should == parse_email_count(amount) end Then /^attachment (\d+) should be named "([^"]*?)"$/ do |index, filename| current_email_attachments[(index.to_i - 1)].original_filename.should == filename end Then /^there should be (an|no|\d+) attachments? of type "([^"]*?)"$/ do |amount, content_type| current_email_attachments.select { |a| a.content_type == content_type }.size.should == parse_email_count(amount) end Then /^attachment (\d+) should be of type "([^"]*?)"$/ do |index, content_type| current_email_attachments[(index.to_i - 1)].content_type.should == content_type end Then /^all attachments should not be blank$/ do current_email_attachments.each do |attachment| attachment.size.should_not == 0 end end Then /^show me a list of email attachments$/ do EmailSpec::EmailViewer::save_and_open_email_attachments_list(current_email) end # # Interact with Email Contents # When /^(?:I|they|he|she) follow "([^"]*?)" in the email$/ do |link| visit_in_email(link) end When /^(?:I|they|he|she) click the first link in the email$/ do click_first_link_in_email end # # Debugging # These only work with Rails and OSx ATM since EmailViewer uses RAILS_ROOT and OSx's 'open' command. # Patches accepted. ;) # Then /^save and open current email$/ do EmailSpec::EmailViewer::save_and_open_email(current_email) end Then /^save and open all text emails$/ do EmailSpec::EmailViewer::save_and_open_all_text_emails end Then /^save and open all html emails$/ do EmailSpec::EmailViewer::save_and_open_all_html_emails end Then /^save and open all raw emails$/ do EmailSpec::EmailViewer::save_and_open_all_raw_emails end email-spec-1.6.0/lib/0000755000175000017500000000000012766555077013353 5ustar pravipraviemail-spec-1.6.0/lib/email_spec/0000755000175000017500000000000012766555077015454 5ustar pravipraviemail-spec-1.6.0/lib/email_spec/helpers.rb0000644000175000017500000001340412766555077017445 0ustar pravipravirequire 'uri' require 'email_spec/deliveries' module EmailSpec module Helpers include Deliveries def visit_in_email(link_text, address = '') if address.nil? || address.empty? email = current_email else email = find_email!(address) end visit(parse_email_for_link(email, link_text)) end def click_email_link_matching(regex, email = current_email) url = links_in_email(email).detect { |link| link =~ regex } raise "No link found matching #{regex.inspect} in #{email.default_part_body}" unless url visit request_uri(url) end def click_first_link_in_email(email = current_email) link = links_in_email(email).first visit request_uri(link) end def open_email(address, opts={}) set_current_email(find_email!(address, opts)) end alias_method :open_email_for, :open_email def open_last_email set_current_email(last_email_sent) end def open_last_email_for(address) set_current_email(mailbox_for(address).last) end def current_email(address=nil) address = convert_address(address) email = address ? email_spec_hash[:current_emails][address] : email_spec_hash[:current_email] raise RSpec::Expectations::ExpectationNotMetError, "Expected an open email but none was found. Did you forget to call open_email?" unless email email end def current_email_attachments(address=nil) current_email(address).attachments || Array.new end def unread_emails_for(address) mailbox_for(address) - read_emails_for(address) end def read_emails_for(address) email_spec_hash[:read_emails][convert_address(address)] ||= [] end # Should be able to accept String or Regexp options. def find_email(address, opts={}) address = convert_address(address) if opts[:with_subject] expected_subject = (opts[:with_subject].is_a?(String) ? Regexp.escape(opts[:with_subject]) : opts[:with_subject]) mailbox_for(address).find { |m| m.subject =~ Regexp.new(expected_subject) } elsif opts[:with_text] expected_text = (opts[:with_text].is_a?(String) ? Regexp.escape(opts[:with_text]) : opts[:with_text]) mailbox_for(address).find { |m| m.default_part_body =~ Regexp.new(expected_text) } elsif opts[:from] mailbox_for(address).find { |m| m.from.include? opts[:from] } else mailbox_for(address).first end end def links_in_email(email) URI.extract(email.default_part_body.to_s, ['http', 'https']) end private def email_spec_hash @email_spec_hash ||= {:read_emails => {}, :unread_emails => {}, :current_emails => {}, :current_email => nil} end def find_email!(address, opts={}) email = find_email(address, opts) if current_email_address.nil? raise EmailSpec::NoEmailAddressProvided, "No email address has been provided. Make sure current_email_address is returning something." elsif email.nil? error = "#{opts.keys.first.to_s.humanize.downcase unless opts.empty?} #{('"' + opts.values.first.to_s + '"') unless opts.empty?}" raise EmailSpec::CouldNotFindEmailError, "Could not find email #{error} in the mailbox for #{current_email_address}. \n Found the following emails:\n\n #{all_emails.to_s}" end email end def set_current_email(email) return unless email [email.to, email.cc, email.bcc].compact.flatten.each do |to| read_emails_for(to) << email email_spec_hash[:current_emails][to] = email end email_spec_hash[:current_email] = email end def parse_email_for_link(email, text_or_regex) matcher = EmailSpec::Matchers::HaveBodyText.new(text_or_regex) RSpec::Expectations::PositiveExpectationHandler.handle_matcher(email, matcher) url = parse_email_for_explicit_link(email, text_or_regex) url ||= parse_email_for_anchor_text_link(email, text_or_regex) raise "No link found matching #{text_or_regex.inspect} in #{email}" unless url url end def request_uri(link) return unless link url = URI::parse(link) url.fragment ? (url.request_uri + "#" + url.fragment) : url.request_uri end # e.g. confirm in http://confirm def parse_email_for_explicit_link(email, regex) regex = /#{Regexp.escape(regex)}/ unless regex.is_a?(Regexp) url = links_in_email(email).detect { |link| link =~ regex } request_uri(url) end # e.g. Click here in Click here def parse_email_for_anchor_text_link(email, link_text) if textify_images(email.default_part_body) =~ %r{]*href=['"]?([^'"]*)['"]?[^>]*?>[^<]*?#{link_text}[^<]*?} URI.split($1)[5..-1].compact!.join("?").gsub("&", "&") # sub correct ampersand after rails switches it (http://dev.rubyonrails.org/ticket/4002) else return nil end end def textify_images(email_body) email_body.to_s.gsub(%r{]*alt=['"]?([^'"]*)['"]?[^>]*?/>}) { $1 } end def parse_email_count(amount) case amount when "no" 0 when "an" 1 else amount.to_i end end attr_reader :last_email_address def convert_address(address) @last_email_address = (address || current_email_address) AddressConverter.instance.convert(@last_email_address) end # Overwrite this method to set default email address, for example: # last_email_address || @current_user.email def current_email_address last_email_address end def mailbox_for(address) super(convert_address(address)) # super resides in Deliveries end def email_spec_deprecate(text) puts "" puts "DEPRECATION: #{text.split.join(' ')}" puts "" end end end email-spec-1.6.0/lib/email_spec/address_converter.rb0000644000175000017500000000113712766555077021517 0ustar pravipravirequire 'singleton' module EmailSpec class AddressConverter include Singleton attr_accessor :converter # The block provided to conversion should convert to an email # address string or return the input untouched. For example: # # EmailSpec::AddressConverter.instance.conversion do |input| # if input.is_a?(User) # input.email # else # input # end # end # def conversion(&block) self.converter = block end def convert(input) return input unless converter converter.call(input) end end endemail-spec-1.6.0/lib/email_spec/deliveries.rb0000644000175000017500000000337612766555077020145 0ustar pravipravimodule EmailSpec module MailerDeliveries def all_emails deliveries end def last_email_sent deliveries.last || raise("No email has been sent!") end def reset_mailer if defined?(ActionMailer) && ActionMailer::Base.delivery_method == :cache mailer.clear_cache else deliveries.clear end end def mailbox_for(address) deliveries.select { |email| email.destinations.include?(address) } end protected def deliveries if ActionMailer::Base.delivery_method == :cache mailer.cached_deliveries else mailer.deliveries end end end module ARMailerDeliveries def all_emails Email.all.map{ |email| parse_to_mail(email) } end def last_email_sent if email = Email.last parse_to_mail(email) else raise("No email has been sent!") end end def reset_mailer Email.delete_all end def mailbox_for(address) Email.all.select { |email| email.destinations.include?(address) }.map{ |email| parse_to_mail(email) } end def parse_to_mail(email) Mail.read(email.mail) end end if defined?(Pony) module ::Pony def self.deliveries @deliveries ||= [] end def self.mail(options) deliveries << build_mail(options) end end end module Deliveries if defined?(Pony) def deliveries; Pony::deliveries ; end include EmailSpec::MailerDeliveries elsif ActionMailer::Base.delivery_method == :activerecord include EmailSpec::ARMailerDeliveries else def mailer; ActionMailer::Base; end include EmailSpec::MailerDeliveries end include EmailSpec::BackgroundProcesses::Compatibility end end email-spec-1.6.0/lib/email_spec/mail_ext.rb0000644000175000017500000000032312766555077017601 0ustar pravipravimodule EmailSpec::MailExt def default_part @default_part ||= html_part || text_part || self end def default_part_body default_part.body end end Mail::Message.send(:include, EmailSpec::MailExt) email-spec-1.6.0/lib/email_spec/email_viewer.rb0000644000175000017500000000472412766555077020460 0ustar pravipravimodule EmailSpec class EmailViewer extend Deliveries def self.save_and_open_all_raw_emails filename = tmp_email_filename File.open(filename, "w") do |f| all_emails.each do |m| f.write m.to_s f.write "\n" + '='*80 + "\n" end end open_in_text_editor(filename) end def self.save_and_open_all_html_emails all_emails.each_with_index do |m, index| if m.multipart? && html_part = m.parts.detect{ |p| p.content_type.include?('text/html') } filename = tmp_email_filename("-#{index}.html") File.open(filename, "w") do |f| f.write m.parts[1].body end open_in_browser(filename) end end end def self.save_and_open_all_text_emails filename = tmp_email_filename File.open(filename, "w") do |f| all_emails.each do |m| if m.multipart? && text_part = m.parts.detect{ |p| p.content_type.include?('text/plain') } if m.respond_to?(:ordered_each) # Rails 2 / TMail m.ordered_each{|k,v| f.write "#{k}: #{v}\n" } else # Rails 3 / Mail f.write(text_part.header.to_s + "\n") end f.write text_part.body else f.write m.to_s end f.write "\n" + '='*80 + "\n" end end open_in_text_editor(filename) end def self.save_and_open_email(mail) filename = tmp_email_filename File.open(filename, "w") do |f| f.write mail.to_s end open_in_text_editor(filename) end def self.save_and_open_email_attachments_list(mail) filename = tmp_email_filename File.open(filename, "w") do |f| mail.attachments.each_with_index do |attachment, index| info = "#{index + 1}:" info += "\n\tfilename: #{attachment.original_filename}" info += "\n\tcontent type: #{attachment.content_type}" info += "\n\tsize: #{attachment.size}" f.write info + "\n" end end open_in_text_editor(filename) end def self.open_in_text_editor(filename) Launchy.open(URI.parse("file://#{File.expand_path(filename)}"), :application => :editor) end def self.open_in_browser(filename) Launchy.open(URI.parse("file://#{File.expand_path(filename)}")) end def self.tmp_email_filename(extension = '.txt') "#{Rails.root}/tmp/email-#{Time.now.to_i}#{extension}" end end end email-spec-1.6.0/lib/email_spec/background_processes.rb0000644000175000017500000000207012766555077022205 0ustar pravipravimodule EmailSpec module BackgroundProcesses module DelayedJob def all_emails work_off_queue super end def last_email_sent work_off_queue super end def reset_mailer work_off_queue super end def mailbox_for(address) work_off_queue super end private # Later versions of DelayedJob switch from using Delayed::Job to Delayed::Worker # Support both versions for those who haven't upgraded yet def work_off_queue if Delayed::Worker.instance_methods.detect{|iv| iv.to_s == "work_off" } Delayed::Worker.send :public, :work_off worker = Delayed::Worker.new(:max_priority => nil, :min_priority => nil, :quiet => true) worker.work_off else Delayed::Job.work_off end end end module Compatibility if defined?(Delayed) && (defined?(Delayed::Job) || defined?(Delayed::Worker)) include EmailSpec::BackgroundProcesses::DelayedJob end end end end email-spec-1.6.0/lib/email_spec/matchers.rb0000644000175000017500000002777012766555077017624 0ustar pravipravimodule EmailSpec module Matchers class EmailMatcher def address_array if @email.perform_deliveries Array(yield) else [] end end end class ReplyTo def initialize(email) @expected_reply_to = Mail::ReplyToField.new(email).addrs.first end def description "have reply to as #{@expected_reply_to.address}" end def matches?(email) @email = email @actual_reply_to = (email.reply_to || []).first !@actual_reply_to.nil? && @actual_reply_to == @expected_reply_to.address end def failure_message "expected #{@email.inspect} to reply to #{@expected_reply_to.address.inspect}, but it replied to #{@actual_reply_to.inspect}" end def failure_message_when_negated "expected #{@email.inspect} not to deliver to #{@expected_reply_to.address.inspect}, but it did" end alias negative_failure_message failure_message_when_negated end def reply_to(email) ReplyTo.new(email) end alias :have_reply_to :reply_to class DeliverTo < EmailMatcher def initialize(expected_email_addresses_or_objects_that_respond_to_email) emails = expected_email_addresses_or_objects_that_respond_to_email.map do |email_or_object| email_or_object.kind_of?(String) ? email_or_object : email_or_object.email end @expected_recipients = Mail::ToField.new(emails).addrs.map(&:to_s).sort end def description "be delivered to #{@expected_recipients.inspect}" end def matches?(email) @email = email @actual_recipients = address_array{ email.header[:to].addrs }.map(&:to_s).sort @actual_recipients == @expected_recipients end def failure_message "expected #{@email.inspect} to deliver to #{@expected_recipients.inspect}, but it delivered to #{@actual_recipients.inspect}" end def failure_message_when_negated "expected #{@email.inspect} not to deliver to #{@expected_recipients.inspect}, but it did" end alias negative_failure_message failure_message_when_negated end def deliver_to(*expected_email_addresses_or_objects_that_respond_to_email) DeliverTo.new(expected_email_addresses_or_objects_that_respond_to_email.flatten) end alias :be_delivered_to :deliver_to class DeliverFrom < EmailMatcher def initialize(email) @expected_sender = Mail::FromField.new(email).addrs.first end def description "be delivered from #{@expected_sender}" end def matches?(email) @email = email @actual_sender = address_array{ email.header[:from].addrs }.first !@actual_sender.nil? && @actual_sender.to_s == @expected_sender.to_s end def failure_message %(expected #{@email.inspect} to deliver from "#{@expected_sender.to_s}", but it delivered from "#{@actual_sender.to_s}") end def failure_message_when_negated %(expected #{@email.inspect} not to deliver from "#{@expected_sender.to_s}", but it did) end alias negative_failure_message failure_message_when_negated end def deliver_from(email) DeliverFrom.new(email) end alias :be_delivered_from :deliver_from class BccTo < EmailMatcher def initialize(expected_email_addresses_or_objects_that_respond_to_email) emails = expected_email_addresses_or_objects_that_respond_to_email.map do |email_or_object| email_or_object.kind_of?(String) ? email_or_object : email_or_object.email end @expected_email_addresses = emails.sort end def description "be bcc'd to #{@expected_email_addresses.inspect}" end def matches?(email) @email = email @actual_recipients = address_array{ email.bcc }.sort @actual_recipients == @expected_email_addresses end def failure_message "expected #{@email.inspect} to bcc to #{@expected_email_addresses.inspect}, but it was bcc'd to #{@actual_recipients.inspect}" end def failure_message_when_negated "expected #{@email.inspect} not to bcc to #{@expected_email_addresses.inspect}, but it did" end alias negative_failure_message failure_message_when_negated end def bcc_to(*expected_email_addresses_or_objects_that_respond_to_email) BccTo.new(expected_email_addresses_or_objects_that_respond_to_email.flatten) end class CcTo < EmailMatcher def initialize(expected_email_addresses_or_objects_that_respond_to_email) emails = expected_email_addresses_or_objects_that_respond_to_email.map do |email_or_object| email_or_object.kind_of?(String) ? email_or_object : email_or_object.email end @expected_email_addresses = emails.sort end def description "be cc'd to #{@expected_email_addresses.inspect}" end def matches?(email) @email = email @actual_recipients = address_array { email.cc }.sort @actual_recipients == @expected_email_addresses end def failure_message "expected #{@email.inspect} to cc to #{@expected_email_addresses.inspect}, but it was cc'd to #{@actual_recipients.inspect}" end def failure_message_when_negated "expected #{@email.inspect} not to cc to #{@expected_email_addresses.inspect}, but it did" end alias negative_failure_message failure_message_when_negated end def cc_to(*expected_email_addresses_or_objects_that_respond_to_email) CcTo.new(expected_email_addresses_or_objects_that_respond_to_email.flatten) end class HaveSubject def initialize(subject) @expected_subject = subject end def description if @expected_subject.is_a?(String) "have subject of #{@expected_subject.inspect}" else "have subject matching #{@expected_subject.inspect}" end end def matches?(email) @given_subject = email.subject if @expected_subject.is_a?(String) @given_subject == @expected_subject else !!(@given_subject =~ @expected_subject) end end def failure_message if @expected_subject.is_a?(String) "expected the subject to be #{@expected_subject.inspect} but was #{@given_subject.inspect}" else "expected the subject to match #{@expected_subject.inspect}, but did not. Actual subject was: #{@given_subject.inspect}" end end def failure_message_when_negated if @expected_subject.is_a?(String) "expected the subject not to be #{@expected_subject.inspect} but was" else "expected the subject not to match #{@expected_subject.inspect} but #{@given_subject.inspect} does match it." end end alias negative_failure_message failure_message_when_negated end def have_subject(subject) HaveSubject.new(subject) end class IncludeEmailWithSubject def initialize(subject) @expected_subject = subject end def description if @expected_subject.is_a?(String) "include email with subject of #{@expected_subject.inspect}" else "include email with subject matching #{@expected_subject.inspect}" end end def matches?(emails) @given_emails = emails if @expected_subject.is_a?(String) @given_emails.map(&:subject).include?(@expected_subject) else !!(@given_emails.any?{ |mail| mail.subject =~ @expected_subject }) end end def failure_message if @expected_subject.is_a?(String) "expected at least one email to have the subject #{@expected_subject.inspect} but none did. Subjects were #{@given_emails.map(&:subject).inspect}" else "expected at least one email to have a subject matching #{@expected_subject.inspect}, but none did. Subjects were #{@given_emails.map(&:subject).inspect}" end end def failure_message_when_negated if @expected_subject.is_a?(String) "expected no email with the subject #{@expected_subject.inspect} but found at least one. Subjects were #{@given_emails.map(&:subject).inspect}" else "expected no email to have a subject matching #{@expected_subject.inspect} but found at least one. Subjects were #{@given_emails.map(&:subject).inspect}" end end alias negative_failure_message failure_message_when_negated end def include_email_with_subject(*emails) IncludeEmailWithSubject.new(emails.flatten.first) end class HaveBodyText def initialize(text) @expected_text = text end def description if @expected_text.is_a?(String) "have body including #{@expected_text.inspect}" else "have body matching #{@expected_text.inspect}" end end def matches?(email) if @expected_text.is_a?(String) @given_text = email.default_part_body.to_s.gsub(/\s+/, " ") @expected_text = @expected_text.gsub(/\s+/, " ") @given_text.include?(@expected_text) else @given_text = email.default_part_body.to_s !!(@given_text =~ @expected_text) end end def failure_message if @expected_text.is_a?(String) "expected the body to contain #{@expected_text.inspect} but was #{@given_text.inspect}" else "expected the body to match #{@expected_text.inspect}, but did not. Actual body was: #{@given_text.inspect}" end end def failure_message_when_negated if @expected_text.is_a?(String) "expected the body not to contain #{@expected_text.inspect} but was #{@given_text.inspect}" else "expected the body not to match #{@expected_text.inspect} but #{@given_text.inspect} does match it." end end alias negative_failure_message failure_message_when_negated end def have_body_text(text) HaveBodyText.new(text) end class HaveHeader def initialize(name, value) @expected_name, @expected_value = name, value end def description if @expected_value.is_a?(String) "have header #{@expected_name}: #{@expected_value}" else "have header #{@expected_name} with value matching #{@expected_value.inspect}" end end def matches?(email) @given_header = email.header if @expected_value.is_a?(String) @given_header[@expected_name].to_s == @expected_value else @given_header[@expected_name].to_s =~ @expected_value end end def failure_message if @expected_value.is_a?(String) "expected the headers to include '#{@expected_name}: #{@expected_value}' but they were #{mail_headers_hash(@given_header).inspect}" else "expected the headers to include '#{@expected_name}' with a value matching #{@expected_value.inspect} but they were #{mail_headers_hash(@given_header).inspect}" end end def failure_message_when_negated if @expected_value.is_a?(String) "expected the headers not to include '#{@expected_name}: #{@expected_value}' but they were #{mail_headers_hash(@given_header).inspect}" else "expected the headers not to include '#{@expected_name}' with a value matching #{@expected_value.inspect} but they were #{mail_headers_hash(@given_header).inspect}" end end alias negative_failure_message failure_message_when_negated def mail_headers_hash(email_headers) email_headers.fields.inject({}) { |hash, field| hash[field.field.class::FIELD_NAME] = field.to_s; hash } end end def have_header(name, value) HaveHeader.new(name, value) end def self.included base if base.respond_to? :register_matcher instance_methods.each do |name| base.register_matcher name, name end end end end end email-spec-1.6.0/lib/email_spec/test_observer.rb0000644000175000017500000000021412766555077020664 0ustar pravipravimodule EmailSpec class TestObserver def self.delivered_email(message) ActionMailer::Base.deliveries << message end end endemail-spec-1.6.0/lib/email_spec/cucumber.rb0000644000175000017500000000151312766555077017606 0ustar pravipravi# require this in your env.rb file after you require cucumber/rails/world # Global Setup if defined?(ActionMailer) unless [:test, :activerecord, :cache, :file].include?(ActionMailer::Base.delivery_method) ActionMailer::Base.register_observer(EmailSpec::TestObserver) end ActionMailer::Base.perform_deliveries = true Before do # Scenario setup case ActionMailer::Base.delivery_method when :test then ActionMailer::Base.deliveries.clear when :cache then ActionMailer::Base.clear_cache end end end After do EmailSpec::EmailViewer.save_and_open_all_raw_emails if ENV['SHOW_EMAILS'] EmailSpec::EmailViewer.save_and_open_all_html_emails if ENV['SHOW_HTML_EMAILS'] EmailSpec::EmailViewer.save_and_open_all_text_emails if ENV['SHOW_TEXT_EMAILS'] end World(EmailSpec::Helpers) World(EmailSpec::Matchers) email-spec-1.6.0/lib/email_spec/errors.rb0000644000175000017500000000020012766555077017305 0ustar pravipravimodule EmailSpec class CouldNotFindEmailError < StandardError end class NoEmailAddressProvided < StandardError end end email-spec-1.6.0/lib/email_spec.rb0000644000175000017500000000117012766555077016000 0ustar pravipraviunless defined?(Pony) or defined?(ActionMailer) Kernel.warn("Neither Pony nor ActionMailer appear to be loaded so email-spec is requiring ActionMailer.") require 'action_mailer' end $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__))) require 'mail' require 'email_spec/background_processes' require 'email_spec/deliveries' require 'email_spec/address_converter' require 'email_spec/email_viewer' require 'email_spec/helpers' require 'email_spec/matchers' require 'email_spec/mail_ext' require 'email_spec/test_observer' require 'email_spec/errors' email-spec-1.6.0/lib/email-spec.rb0000644000175000017500000000011212766555077015711 0ustar pravipravirequire File.expand_path(File.join(File.dirname(__FILE__), 'email_spec')) email-spec-1.6.0/lib/generators/0000755000175000017500000000000012766555077015524 5ustar pravipraviemail-spec-1.6.0/lib/generators/email_spec/0000755000175000017500000000000012766555077017625 5ustar pravipraviemail-spec-1.6.0/lib/generators/email_spec/steps/0000755000175000017500000000000012766555077020763 5ustar pravipraviemail-spec-1.6.0/lib/generators/email_spec/steps/steps_generator.rb0000644000175000017500000000055012766555077024514 0ustar pravipravi# This generator adds email steps to the step definitions directory require 'rails/generators' module EmailSpec class StepsGenerator < Rails::Generators::Base def generate copy_file 'email_steps.rb', 'features/step_definitions/email_steps.rb' end def self.source_root File.join(File.dirname(__FILE__), 'templates') end end endemail-spec-1.6.0/lib/generators/email_spec/steps/templates/0000755000175000017500000000000012766555077022761 5ustar pravipraviemail-spec-1.6.0/lib/generators/email_spec/steps/templates/email_steps.rb0000644000175000017500000001433412766555077025620 0ustar pravipravi# Commonly used email steps # # To add your own steps make a custom_email_steps.rb # The provided methods are: # # last_email_address # reset_mailer # open_last_email # visit_in_email # unread_emails_for # mailbox_for # current_email # open_email # read_emails_for # find_email # # General form for email scenarios are: # - clear the email queue (done automatically by email_spec) # - execute steps that sends an email # - check the user received an/no/[0-9] emails # - open the email # - inspect the email contents # - interact with the email (e.g. click links) # # The Cucumber steps below are setup in this order. module EmailHelpers def current_email_address # Replace with your a way to find your current email. e.g @current_user.email # last_email_address will return the last email address used by email spec to find an email. # Note that last_email_address will be reset after each Scenario. last_email_address || "example@example.com" end end World(EmailHelpers) # # Reset the e-mail queue within a scenario. # This is done automatically before each scenario. # Given /^(?:a clear email queue|no emails have been sent)$/ do reset_mailer end # # Check how many emails have been sent/received # Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails?$/ do |address, amount| unread_emails_for(address).size.should == parse_email_count(amount) end Then /^(?:I|they|"([^"]*?)") should have (an|no|\d+) emails?$/ do |address, amount| mailbox_for(address).size.should == parse_email_count(amount) end Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails? with subject "([^"]*?)"$/ do |address, amount, subject| unread_emails_for(address).select { |m| m.subject =~ Regexp.new(Regexp.escape(subject)) }.size.should == parse_email_count(amount) end Then /^(?:I|they|"([^"]*?)") should receive (an|no|\d+) emails? with subject \/([^"]*?)\/$/ do |address, amount, subject| unread_emails_for(address).select { |m| m.subject =~ Regexp.new(subject) }.size.should == parse_email_count(amount) end Then /^(?:I|they|"([^"]*?)") should receive an email with the following body:$/ do |address, expected_body| open_email(address, :with_text => expected_body) end # # Accessing emails # # Opens the most recently received email When /^(?:I|they|"([^"]*?)") opens? the email$/ do |address| open_email(address) end When /^(?:I|they|"([^"]*?)") opens? the email with subject "([^"]*?)"$/ do |address, subject| open_email(address, :with_subject => subject) end When /^(?:I|they|"([^"]*?)") opens? the email with subject \/([^"]*?)\/$/ do |address, subject| open_email(address, :with_subject => Regexp.new(subject)) end When /^(?:I|they|"([^"]*?)") opens? the email with text "([^"]*?)"$/ do |address, text| open_email(address, :with_text => text) end When /^(?:I|they|"([^"]*?)") opens? the email with text \/([^"]*?)\/$/ do |address, text| open_email(address, :with_text => Regexp.new(text)) end # # Inspect the Email Contents # Then /^(?:I|they) should see "([^"]*?)" in the email subject$/ do |text| current_email.should have_subject(text) end Then /^(?:I|they) should see \/([^"]*?)\/ in the email subject$/ do |text| current_email.should have_subject(Regexp.new(text)) end Then /^(?:I|they) should see "([^"]*?)" in the email body$/ do |text| current_email.default_part_body.to_s.should include(text) end Then /^(?:I|they) should see \/([^"]*?)\/ in the email body$/ do |text| current_email.default_part_body.to_s.should =~ Regexp.new(text) end Then /^(?:I|they) should see the email delivered from "([^"]*?)"$/ do |text| current_email.should be_delivered_from(text) end Then /^(?:I|they) should see "([^\"]*)" in the email "([^"]*?)" header$/ do |text, name| current_email.should have_header(name, text) end Then /^(?:I|they) should see \/([^\"]*)\/ in the email "([^"]*?)" header$/ do |text, name| current_email.should have_header(name, Regexp.new(text)) end Then /^I should see it is a multi\-part email$/ do current_email.should be_multipart end Then /^(?:I|they) should see "([^"]*?)" in the email html part body$/ do |text| current_email.html_part.body.to_s.should include(text) end Then /^(?:I|they) should see "([^"]*?)" in the email text part body$/ do |text| current_email.text_part.body.to_s.should include(text) end # # Inspect the Email Attachments # Then /^(?:I|they) should see (an|no|\d+) attachments? with the email$/ do |amount| current_email_attachments.size.should == parse_email_count(amount) end Then /^there should be (an|no|\d+) attachments? named "([^"]*?)"$/ do |amount, filename| current_email_attachments.select { |a| a.filename == filename }.size.should == parse_email_count(amount) end Then /^attachment (\d+) should be named "([^"]*?)"$/ do |index, filename| current_email_attachments[(index.to_i - 1)].filename.should == filename end Then /^there should be (an|no|\d+) attachments? of type "([^"]*?)"$/ do |amount, content_type| current_email_attachments.select { |a| a.content_type.include?(content_type) }.size.should == parse_email_count(amount) end Then /^attachment (\d+) should be of type "([^"]*?)"$/ do |index, content_type| current_email_attachments[(index.to_i - 1)].content_type.should include(content_type) end Then /^all attachments should not be blank$/ do current_email_attachments.each do |attachment| attachment.read.size.should_not == 0 end end Then /^show me a list of email attachments$/ do EmailSpec::EmailViewer::save_and_open_email_attachments_list(current_email) end # # Interact with Email Contents # When /^(?:I|they|"([^"]*?)") follows? "([^"]*?)" in the email$/ do |address, link| visit_in_email(link, address) end When /^(?:I|they) click the first link in the email$/ do click_first_link_in_email end # # Debugging # These only work with Rails and OSx ATM since EmailViewer uses RAILS_ROOT and OSx's 'open' command. # Patches accepted. ;) # Then /^save and open current email$/ do EmailSpec::EmailViewer::save_and_open_email(current_email) end Then /^save and open all text emails$/ do EmailSpec::EmailViewer::save_and_open_all_text_emails end Then /^save and open all html emails$/ do EmailSpec::EmailViewer::save_and_open_all_html_emails end Then /^save and open all raw emails$/ do EmailSpec::EmailViewer::save_and_open_all_raw_emails end email-spec-1.6.0/lib/generators/email_spec/steps/USAGE0000644000175000017500000000020612766555077021550 0ustar pravipraviDescription: Creates email_steps.rb in your cucumber step_definitions. Examples: `script/rails generate email_spec:steps`email-spec-1.6.0/History.txt0000644000175000017500000002331312766555077015011 0ustar pravipravi== 1.6.0 2014-05-27 * New RSpec matcher API support (Morton Jonuschat) * Turnip Doc updates (Joshua Muheim) * Use Mail#destination for picking recipients (Lukasz Strzalkowski) * Emails deliver to nobody when perform_deliveries is set to false (Sean Griffin) == 1.5.0 2013-07-22 * Upgraded use of Capybara to avoid deprecation warnings. * Upgraded use of RSpec to deal with new expect API (Thomas Drake-Brockman) === New features * visit_in_email now works for emails that are not the current_email (Ernesto Tagwerker) * emails can be found based on :from field (John Cant) === Bug fixes * Emails that are not found when clicking a link now raise an exception. (Adam Berlin & Alex Kramer) == 1.4.0 2012-10-30 * removed jeweler in favor of just using bundler for all gem management. === New features * MiniTest support! See README for documentation. (Mike Moore) == 1.3.0 2011-04-07 Many thanks to Derek Hammer and George Ardeleanu who both spontaneously cleaned up various parts of the project and helped get the release out the door. Yay opensoruce! === New features * Launchy is now used to open up the email viewer. (Matt Burke) * Email Viewer now works in Rails 3 (Woody Peterson) * Email Viewer now works with UTF-8. (Woody Peterson) * Documentation for email matchers. (Derek Hammer) == 1.2.1 2011-06-20 === Bugfixes * find_email now allows with_subject and with_text to be either a String or Regexp. Issue #67. (Curtis Miller) == 1.2.0 2011-06-16 === New features * [he|she] options for steps. (Dan Croak) * cc_to RSpec matcher. (Arie on github) * Check both html and text parts of multipart emails in Cucumber step. (Charles Barbier) * delivery_method is not set by email_spec to allow for SMTP (e.g. MockSMTP) delivery (Donald Piret) === Bugfixes * delivered_to matcher now compares both sender name and email address. (Jason Garber) * find_email now matches with_subject and with_text containing text with regex sensitive characters. Issue #31. (Curtis Miller) * current_email_address to work outside of the context of Cucumber. (Szymon Przybył) == 1.1.1 2010-12-29 * Require "action_mailer" to avoid deprecation warnings. (Ryan Bigg) * Relaxes pessimistic version dependency on RSpec. (GH-41 Dan Pickett) == 1.1.0 2010-12-20 === Bugfixes * anchor tags are no longer ignored when clicking links in emails (Anders Törnqist and Nicklas Ramhöj) * set_current_email handles cases where To to blank but may contain CC, or BCC recipients (Murray Steele) * Doc fixes (Florent Guilleux) == 1.0 2010-07-31 Rails 3.0 Release This release makes email-spec compatible with Rails 3 and RSpec 2.x. IMPORTANT: As of 1.0 email-spec is no longer backwards compatible wit Rails 2.x. I will be maintaining a 0.6 branch on github/rubygems for Rails 2 compatibility if anyone wants new features backported. This was truly a community effort and I appreciate all of time and effort donated by those involved. Specifically: * Maxim Chernyak for the initial conversion work to Rails 3 * Tim Harper for ironing out various matcher bugs * Patrick Muldoon for doing a fantastic job of cleaning up the features and specs. He also fixed the DelayedJob support and worked through all the bundler issues the project was facing. === Bugfixes * Further checks for older DelayedJob versions to fix compatibility issues. (Andrea Longhi and others) == 0.6.2 2010-03-21 === New features * New reply_to matcher. (David Balatero) == 0.6.1 2010-03-17 === New features * Ability to click image links via the image alt tag. (Tim Harper) == 0.6.0 2010-03-05 === New features * Ability to open a list of attachments on an email (with corresponding steps and EmailViewer support). (Kieran Pilkington) === Bugfixes * Spelling mistake in steps. (Ben Mabey) * Delayed Job background processor fixes * Narrow delayed job collisions with other apps defining Delayed constant. (Kieran Pilkington) * Fix compatibility with earlier versions of DelayedJob (Michael Baumgarten and Kieran Pilkington) === Changes * Deprecated steps were removed. (Kieran Pilkington) === Bugfixes == 0.5.0 2010-02-22 === New features * "should receive emails with subject " step definition (Balint Erdi) * "should receive an email with the following body:" step definition (Ben Mabey) * Debugging steps that tie into EmailViewer: (Ben Mabey) * "save and open current email" * "save and open all text emails" * "save and open all html emails" * "save and open all raw emails" === Bugfixes * Gracefully handle cases where emails do not have a 'to' value. (Kieran Pilkington) === Bugfixes == 0.4.0 2010-01-07 === New features * Added support for action_mailer_cache_delivery plugin. (Dan Dofter) You must use the fork at: http://github.com/liangzan/action_mailer_cache_delivery === Bugfixes * be_delivered_from matcher now compares both sender name and email address. (Dan Dofter) == 0.3.8 2009-12-23 === Bugfixes * Guard against cc and bcc fields being nil for ActionMailer. (Piotr Sarnacki) == 0.3.7 2009-12-17 === New features * Matchers are now Ruby 1.9 compatible. (John Dewey) == 0.3.6 2009-12-16 === New features * Cucumber steps for be_delivered_from, have_header matchers. (Joseph Holsten) * Explicit regular expression steps. i.e. "I should see /foo/ in the email body" (Joseph Holsten) == 0.3.5 2009-09-30 The Pony Release! === New features * Support for Pony mailer library. (Rob Holland) == 0.3.4 2009-09-26 === Bugfixes * Typo and logic fixes for DeliverFrom matcher. (Yury Kotlyarov) == 0.3.3 2009-09-18 === New features * DeliverFrom matcher. i.e. email.should deliver_from(blah) or email.should be_delivered_from(blah) (Diego Carrion) == 0.3.2 2009-09-10 === New features * Support for delayed_job. (Kieran Pilkington) == 0.3.1 2009-08-19 This release is a general refactoring of the steps and helpers. The example rails app was also updated to use the lateset rails and webrat. It also takes advantages and the newer step definistions including the new third-person forms. Some of the generated steps are being removed in favor of some of the newer ones. The older ones will remain until 0.4.0 but will issue deprecation warnings. Big shoutout to Kieran Pilkington who did the majority of work for this release. == 0.3.0 2009-08-13 === New features * New helper #last_email_address which returns the last address used by email-spec for that scenario. (Ben Mabey) * Steps now support third person language. (Kieran P) * "[email] should receive ... " now supports "an" instead of just an integer. (Kieran Pilkington) With these changes, the following is now possible: Then "jack@example.com" should receive an email When they open the email Then they should see "Account has been created" in the subject * Additional default steps (Balint Erdi) * Then /^I should not receive any emails?$/ * When %r{^"([^"]*?)" opens? the email$} do |address| === Bugfixes == 0.2.1 2009-5-29 === New Features * BCC RSpec matcher. (Josh Nichols) === Bugfixes * Include BCCed and CCed messsages in the mailbox. (Jakub Kosiński) == 0.2.0 2009-6-08 No changes. Bumping version for RubyForge release. == 0.1.4 2009-5-29 === Bugfixes * Require deliveries in the helpers so it doesn't blow up with RSpec. (Craig Webster) == 0.1.3 2009-4-15 === Bugfixes * Fixed regular expressions in genertaed steps. (Ben Mabey) * World semantics changed in cucumber (0.2.3.2), email_spec now uses the new API. (Hector Morales) == 0.1.2 2009-4-05 === New features === Bugfixes * Actually added the renamed generators to the gem so people could use it! D'oh! (Ben Mabey) * You can either use "./script generate email_spec" or "rubigen rails email_spec" * Removed Rake tasks from example application to prevent conflicts when used as a plugin. (Ben Mabey) == 0.1.1 2009-3-26 === New features * Switched dir structure over to support rubigen. (Dr. Nic) === Bugfixes == 0.1.0 2009-3-25 === New features * Change Rakefile to run all specs and features, as well as prepare the db (Mischa Fierer) * Allow for array to be passed into deliver_to matcher. (Diego Carrion) * Added matcher for checking if a collision of emails includes an email with a particular subject (Luke Melia, Noah Davis) * Introduced hook to convert objects to email addresses (Luke Melia and Lee Bankewitz) This allows you, in your step matcher, to say something like: maillbox_for(some_user) Use it in your cucumber env.rb like so: EmailSpec::AddressConverter.instance.conversion do |input| if input.is_a?(User) input.email else input end end === Bugfixes * Revert parse_email_for_link helper method to allow for text links as well as explicit link finding. (Mischa Fierer) * Isolated variances between using email-spec with an ARMailer project. (Luke Melia) == 0.0.9 2009-2-15 === New features * have_body_text, have_header matchers (Luke Melia) * EmailViewer - opens all sent emails in a given scenario when the environment variables are set. (Luke Melia) * Added compatibility with using ARMailer in test mode. (Luke Melia) === Bugfixes * set_current_email now works with multiple addresses in To field. (Brian McManus, Ben Mabey) == 0.0.7 2009-1-20 === New features * have_subject matcher (Ben Mabey) == 0.0.6 2008-12-23 === New features * Improved RSpec documentation and refactorings. (Ben Mabey) === Bugfixes * Removed sample app Rake Tasks to have it play nice with environments that use Cucumber as plugin- not gem. (Ben Mabey, Ivor- on github) == 0.0.5 2008-12-18 * Initial release - see this post for full history and contributors: http://www.benmabey.com/2008/12/18/github-rocks/ email-spec-1.6.0/email_spec.gemspec0000644000175000017500000001031412766555077016252 0ustar pravipravi######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: email_spec 1.6.0 ruby lib Gem::Specification.new do |s| s.name = "email_spec" s.version = "1.6.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["Ben Mabey", "Aaron Gibralter", "Mischa Fierer"] s.date = "2014-05-27" s.description = "Easily test email in RSpec, Cucumber, and MiniTest" s.email = "ben@benmabey.com" s.extra_rdoc_files = ["MIT-LICENSE.txt", "README.md"] s.files = ["History.txt", "MIT-LICENSE.txt", "README.md", "Rakefile", "lib/email-spec.rb", "lib/email_spec.rb", "lib/email_spec/address_converter.rb", "lib/email_spec/background_processes.rb", "lib/email_spec/cucumber.rb", "lib/email_spec/deliveries.rb", "lib/email_spec/email_viewer.rb", "lib/email_spec/errors.rb", "lib/email_spec/helpers.rb", "lib/email_spec/mail_ext.rb", "lib/email_spec/matchers.rb", "lib/email_spec/test_observer.rb", "lib/generators/email_spec/steps/USAGE", "lib/generators/email_spec/steps/steps_generator.rb", "lib/generators/email_spec/steps/templates/email_steps.rb", "rails_generators/email_spec/email_spec_generator.rb", "rails_generators/email_spec/templates/email_steps.rb"] s.homepage = "http://github.com/bmabey/email-spec/" s.licenses = ["MIT"] s.rubyforge_project = "email-spec" s.rubygems_version = "2.5.1" s.summary = "Easily test email in rspec and cucumber and minitest" if s.respond_to? :specification_version then s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, ["~> 2.0"]) s.add_runtime_dependency(%q, ["~> 2.1"]) s.add_runtime_dependency(%q, ["~> 2.2"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, ["= 3.0.7"]) s.add_development_dependency(%q, [">= 0.8.7"]) s.add_development_dependency(%q, [">= 2.14.0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, ["~> 2.1"]) s.add_dependency(%q, ["~> 2.2"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, ["= 3.0.7"]) s.add_dependency(%q, [">= 0.8.7"]) s.add_dependency(%q, [">= 2.14.0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, ["~> 2.1"]) s.add_dependency(%q, ["~> 2.2"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, ["= 3.0.7"]) s.add_dependency(%q, [">= 0.8.7"]) s.add_dependency(%q, [">= 2.14.0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end end email-spec-1.6.0/Rakefile0000644000175000017500000000060512766555077014253 0ustar pravipravirequire 'rubygems' require 'bundler' Bundler::GemHelper.install_tasks begin require 'cucumber/rake/task' Cucumber::Rake::Task.new(:features) rescue LoadError task :features do abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber" end end require 'rspec/core/rake_task' RSpec::Core::RakeTask.new task :default => [:features, :spec] email-spec-1.6.0/MIT-LICENSE.txt0000644000175000017500000000204212766555077015055 0ustar pravipraviCopyright (c) 2008-2009 Ben Mabey Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.