GithubHelp home page GithubHelp logo

capybara-email's Introduction

CapybaraEmail

Build Status Code Climate

Easily test ActionMailer and Mail messages in your Capybara integration tests

Installation

Add this line to your application's Gemfile:

gem 'capybara-email'

And then execute:

$ bundle

Or install it yourself as:

$ gem install capybara-email

Usage

RSpec

In your spec_helper.rb require capybara/email/rspec.

require 'capybara/email/rspec'

Example:

feature 'Emailer' do
  background do
    # will clear the message queue
    clear_emails
    visit email_trigger_path
    # Will find an email sent to [email protected]
    # and set `current_email`
    open_email('[email protected]')
  end

  scenario 'following a link' do
    current_email.click_link 'your profile'
    expect(page).to have_content 'Profile page'
  end

  scenario 'testing for content' do
    expect(current_email).to have_content 'Hello Joe!'
  end

  scenario 'testing for attachments' do
    expect(current_email.attachments.first.filename).to eq 'filename.csv'
  end

  scenario 'testing for a custom header' do
    expect(current_email.headers).to include 'header-key'
  end

  scenario 'testing for a custom header value' do
    expect(current_email.header('header-key')).to eq 'header_value'
  end

  scenario 'view the email body in your browser' do
    # the `launchy` gem is required
    current_email.save_and_open
  end
end

Cucumber

Require capybara/email in your features/support/env.rb

require 'capybara/email'

Once you have required capybara-email, gaining access to usable methods is easy as adding this module to your Cucumber World:

World(Capybara::Email::DSL)

I recommend adding this to a support file such as features/support/capybara_email.rb

require 'capybara/email'
World(Capybara::Email::DSL)

Example:

Scenario: Email is sent to winning user
  Given "[email protected]" is playing a game
  When that user picks a winning piece
  Then "[email protected]" receives an email with "You've Won!" as the subject

Then /^"([^"]*)" receives an email with "([^"]*)" as the subject$/ do |email_address, subject|
  open_email(email_address)
  expect(current_email.subject).to eq subject
end

Test::Unit

Require capybara/email at the top of test/test_helper.rb

  require 'capybara/email'

Include Capybara::Email::DSL in your test class

class ActionDispatch::IntegrationTest
  include Capybara::Email::DSL
end

Example:

class EmailTriggerControllerTest < ActionDispatch::IntegrationTest
  def setup
    # will clear the message queue
    clear_emails
    visit email_trigger_path

    # Will find an email sent to `[email protected]`
    # and set `current_email`
    open_email('[email protected]')
  end

  test 'testing any email is sent' do
    expect(all_emails).not_to be_empty
  end

  test 'following a link' do
    current_email.click_link 'your profile'
    expect(page).to have_content 'Profile page'
  end

  test 'testing for content' do
    expect(current_email).to have_content 'Hello Joe!'
  end

  test 'testing for a custom header' do
    expect(current_email.headers).to include 'header-key'
  end

  test 'testing for a custom header value' do
    expect(current_email.header('header-key')).to eq 'header_value'
  end

  test 'view the email body in your browser' do
    # the `launchy` gem is required
    current_email.save_and_open
  end
end

CurrentEmail API

The current_email method will delegate all necessary method calls to Mail::Message. So if you need to access the subject of an email:

current_email.subject

Check out API for the mail gem for details on what methods are available.

Setting your test host

When testing, it's common to want to open an email and click through to your application. To do this, you'll probably need to update your test environment, as well as Capybara's configuration.

By default, Capybara's app_host is set to http://example.com. You should update this so that it points to the same host as your test environment. In our example, we'll update both to http://localhost:3001:

# tests/test_helper.rb
ActionDispatch::IntegrationTest do
  Capybara.server_port = 3001
  Capybara.app_host = 'http://localhost:3001'
end

# config/environments/test.rb
config.action_mailer.default_url_options = { host: 'localhost', 
                                             port: 3001 }

Sending Emails with JavaScript

Sending emails asynchronously will cause #open_email to not open the correct email or not find any email at all depending on the state of the email queue. We recommend forcing a sleep prior to trying to read any email after an asynchronous event:

click_link 'Send email'
sleep 0.1
open_email '[email protected]'

Authors

Brian Cardarella

We are very thankful for the many contributors

Versioning

This gem follows Semantic Versioning

Want to help?

Stable branches are created based upon each minor version. Please make pull requests to specific branches rather than master.

Please make sure you include tests!

Don't use tabs to indent, two spaces are the standard.

Legal

DockYard, Inc. © 2014

@dockyard

Licensed under the MIT license

capybara-email's People

Contributors

adamphillips avatar andrewhavens avatar andyw8 avatar bcardarella avatar bebepeng avatar bensheldon avatar brentwheeldon avatar cgunther avatar daniel-xu avatar dcarper avatar doitian avatar duggiefresh avatar gruntruk avatar hasclass avatar iostat avatar jdcalvin avatar kbaum avatar lest avatar livedo avatar maabernethy avatar michaeldupuis-dockyard avatar ngauthier avatar obfuscoder avatar olleolleolle avatar oscardelben avatar rimian avatar schmidt avatar toasterlovin avatar twalpole avatar yui-knk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

capybara-email's Issues

open_email does not appear to work

    background do
      recipient_user = double()
      recipient_user.stub(:name) {'Ash Williams'}
      recipient_user.stub(:email) {'[email protected]'}

      message = mock_model( Message, 
        recipient: recipient_user
      )

      Mailer.sponsored_challenge_promotion(message).deliver!
      open_email('[email protected]')

    end

    scenario 'should say hello to the user' do
      current_email.should have_content "Hello, Ash"
    end

in this scenario, both open_email and current_email return nil

1.0.0 stable branch does not work with capybara-webkit

Getting an error when it tries to navigate on the url. I'll investigate and patch, just putting this here to remind me.

https://github.com/dockyard/capybara-email/blob/1-0-stable/lib/capybara/email/driver.rb#L14

Why is there even a switch there? Maybe to make a full url from a path? But you can just set your test env actionmailer host to match what your driver will use, so your emails have the proper url. I don't think capybara-webkit exposes a Driver#url for us to use.

search for anchor tag within an email

I saw that you have a find function in your code but I am not sure how to use it. I have tried

open_email ('[email protected]')
current_email.find('a')

That doesn't appear to work. I get a NotImplementedError. I don' believe I saw an example of how to use this in the comments so I was wondering if you could tell me the correct way to use it.

Thank you.

typo in doc

See this here

# tests/test_helper.rb
ActionDispatch::IntegrationTest
  Capybara.server_port = 3001
  Capybara.app_host = 'http://localhost:3001'
end

end is unexpected !! please update

Failed to open email which contain non-ascii symbols in "to" field

If I send in my application email to address which contain utf-8 symbols ("antoinette.cormier@oconnell.рф"), then open_email("antoinette.cormier@oconnell.рф") returns nil. It's because email.to in email/dsl.rb:23 returns this address encoded as "=?UTF-8?B?YW50b2luZXR0ZS5jb3JtaWVyQG9jb25uZWxsLtGA0YQ=?=" referenced to RFC 6539

Add async javascript support for open_email and friends

When testing a single page js app with capybara 2 it's finders are smart enough to wait for an element, up to Capybara.default_wait_time. This is important since the elements to be tested are often loaded asynchronously.

The same is true for open_email. For example: Testing password reset form. User fills out a form, hits submit then we want to open email and verify contents. The submit triggers ajax, capybara test moves on and attempts to open email before it has been sent by the server:

fill_in 'Email', :with => '[email protected]'
click_on "Submit"
open_email('[email protected]')
# FAIL!

As a workaround i have done the following:

click_on "Submit"
# Make sure we wait for this confirm before moving on with test!
page.should have_content 'A reset password email has been sent to you.'
open_email('[email protected]')

I've not looked at capybara implementation but perhaps it is possible to applying the same strategy that is used there?

`save_and_open` is using body as filename

Capybara::Session#save_and_open_page takes a file name argument, but Capybara::Node::Email#save_and_open is passing it the body instead. This results in directories and files being created with the content of the email, like so:

$> ls -l tmp/capybara/
total 0
drwxr-xr-x  3 thunt  staff  102 Dec 31 14:17 <!DOCTYPE html>??<html>??  <head>??    <meta content="text

The resulting file is empty.

Undefined local variable or method 'email_trigger_path'

I'm trying to access emails sent with the mail gem and ran 'visit email_trigger_path' before calling 'open_email()'. However, I get an undefined local variable or method error.... I've included capybara, capybara/dsl, capybara/rspec, mail, capybara/email, and capybara/email/rspec in my spec_helper.
I'm using RSpec and Selenium with Capybara.
I'm still learning Rails and couldn't find anything on the internet, so thanks for the help!

Undefined method `find_xpath` for Capybara::Email::Node

I recently updated to capybara 2.1 and to capybara-email 2.1

With previous capybara version (2.0.3) and capybara-email (2.0.3)

The following statement passed:

current_email.should have_link 'Some text', href: 'http://example.com'

After updating my spec is broken:

Failure/Error: current_email.should have_link 'Some text', href: 'http://example.com'
     NoMethodError:
       undefined method `find_xpath' for #<Capybara::Email::Node tag="a">

uninitialized constant Capybara::Email::DSL::Mail

ruby 1.9.2-p290
rails 3.2.2
minitest 2.11.4
capybara 1.1.2
capybara-webkit 0.11.0
capybara-email 0.1.2

The readme doesn't specify how to require capybara-email for minitest, but I'm assuming it's going to be basically the same as test::unit, which says only to include Capybara::Email::DSL in the IntegrationTest class. [I'm using ActionDispatch::IntegrationTest, not ActionController::IntegrationTest. Not sure if that matters.] I've tried require capybara-email two ways:

require 'capybara/email'
require 'capybara-email'

and not requiring it at all. My integration test helper looks like:

require 'test_helper'
require 'capybara/rails'
require 'capybara/email'

Capybara.javascript_driver = :webkit

class ActiveRecord::Base
    mattr_accessor :shared_connection
    @@shared_connection = nil

    def self.connection
        @@shared_connection || retrieve_connection
    end
end

# Forces all threads to share the same connection. This works on
# Capybara because it starts the web server in a thread.
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection

class ActionDispatch::IntegrationTest
    # Make the Capybara DSL available in all integration tests
    include Capybara::DSL
    include Capybara::Email::DSL

    setup do
        clear_emails
    end

    teardown do
        Capybara.reset_sessions!    # Forget the (simulated) browser state
        Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver
    end

    def enable_javascript
        Capybara.current_driver = Capybara.javascript_driver
    end
end

Whenever I run a test, I get

uninitialized constant Capybara::Email::DSL::Mail

I looked through the code and didn't see anything that would prevent me from using this with minitest, but maybe I missed something. Guidance appreciated.

ERB code not being processed

Sorry if this is by design, but not sure how to make erb code available.

Version

3.0.2

Test Case

I have a mailer view with variables that erb successfully processes in development.
When I'm on a test however, that view doesn't take into account any erb code, leaving empty the places where erb code must be rendered.

Steps to reproduce

some_mailer/first_email.html.erb:

My first email.
Hi <%= @name %>

test/integration/some_integration_test.rb:

test "@name is shown" do
  SomeMailer.first_email.deliver_now
  open_email("[email protected]")
  expect(current_email).to have_content 'my_name'
end

app/mailers/some_mailer.rb:

class SomeMailer < ApplicationMailer
  def first_email
    @name = "my_name"
    mail(to: "[email protected]" subject: "my subject")
  end
end

Expected Behavior

I expect the mail to have this content: ''my_name'

Actual Behavior

ERB is not processed and hence 'my_name' is not present.

typo in description

Test you ActionMailer and Mailer messages with Capybara

Should be

Test your ActionMailer and Mailer messages with Capybara

has_content? not implemented

When i try to use has_content? like:

current_email.should have_content "1 view "

It comes back with:

 1) TrafficReportMailer traffic_report traffic goes up from 0 has the total views in the last week
     Failure/Error: current_email.should have_content "1 view "
     NotImplementedError:
       NotImplementedError
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/driver/node.rb:12:in `all_text'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/node/element.rb:59:in `block in text'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/node/base.rb:77:in `synchronize'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/node/element.rb:57:in `text'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/node/document.rb:21:in `text'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/node/matchers.rb:466:in `text_found?'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/node/matchers.rb:219:in `block in has_text?'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/node/base.rb:81:in `synchronize'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/node/matchers.rb:218:in `has_text?'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/capybara-2.1.0/lib/capybara/rspec/matchers.rb:46:in `matches?'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/rspec-expectations-2.12.1/lib/rspec/expectations/handler.rb:23:in `handle_matcher'
     # /Users/karl/.rvm/gems/ruby-2.0.0-p195@viewthespace/gems/rspec-expectations-2.12.1/lib/rspec/expectations/syntax.rb:53:in `should'
     # ./spec/mailers/traffic_report_mailer_spec.rb:93:in `block (4 levels) in <top (required)>

I was able to fix address the issue with this commit:

kbaum@f454a52

But i wasn't able to reproduce the problem within the driver spec. Any idea why i would only be able to reproduce within my own spec?

thx!

Any plans to make this gem work with parallel tests?

Rails 6 has parallel testing enabled by default, each test worker running under its own port.

This means, setting a server_port doesn't work anymore.

Edit: Just realized this Gem is dead :-)

Since I found nothing yet to replace CapybaraEmail, I monkey patched the deliver_later method from with test/application_system_test_case.rb:

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase

  # Monkey patch to always deliver mails immediately, needed for CapybaraEmail to work
  class ActionMailer::MessageDelivery
    def deliver_later
      deliver_now
    end
  end
end

Remove dependency on capybara 2.2

I'd like to use it with new capybara 2.3

Bundler could not find compatible versions for gem "capybara":
In Gemfile:
capybara-email (>= 2.3.0) ruby depends on
capybara (~> 2.2.0) ruby

capybara (2.3.0)

Release current version on Rubygems

Can you please release a new version? 2.5.0 was released February 17, 2016. Looks like there have been a few useful commits since then, especially regarding compatibility to Capybara 3.0.

Release a new version?

Can you please release a new version? 2.4.0 was released July 7, 2014. Looks like there have been a few useful commits since then that would be nice to make public.

Add ability to fetch the next email for a given recipient

Hi!

thanks for capybara-email first!

Today I wanted to fetch the next email received by a given recipient, and ended up doing this as a quick work-around:

    def read_current_email_from_email_box!(recipient)
      self.current_email = emails_sent_to(recipient).first
      # TODO: patch capybara-email to allow to fetch the first email for a given recipient instead of doing this
      # Keeping a guard until we do that
      all_emails[0].to.should == [recipient]
      all_emails.delete_at(0)
    end

If I write something to allow to "remove the next email for a given user, assert it's here, and remove it from the deliveries queue", would you integrate it?

Thanks!

Rspec 3 conflicts

Hello.

I've just upgraded to Rspec 3 and gotr errors:

  3) Signing up having invitation received but registration without it should be confirmed
     Failure/Error: current_email.click_link I18n.t("devise.mailer.confirmation_instructions.confirm_account_link")
     NotImplementedError:
       NotImplementedError
     # ./spec/features/registration_controller_spec.rb:130:in `block (2 levels) in <top (required)>'

  4) Signing up should save with invitation received and followed
     Failure/Error: clear_emails
     NameError:
       undefined local variable or method `clear_emails' for #<RSpec::ExampleGroups::SigningUp:0x0000010f54d278>
     # ./spec/features/registration_controller_spec.rb:10:in `block (2 levels) in <top (required)>'


While test worked fine on rspec 2 with this code:

  background(:each) do
    clear_emails
    @user = FactoryGirl.build(:user)
  end

...
    open_email(@user.email)

    current_email.click_link I18n.t("devise.mailer.confirmation_instructions.confirm_account_link")
    expect(page).to have_content @user.username


....

Do you have any idea how to fix that in a right way? Thank you!

Is this gem still active?

Hi, this looks like a great gem, thanks for the work you put into it.

I wanted to make sure this gem is still being maintained before my team invests in integrating it. I noticed there hasn't been anything merged in about a year, the build status is "error", and the dependencies need updating.

  • Are people still using this on production codebases?
  • Are there any other alternatives (i.e. just getting Capybara to open a rendered email?)

FWIW I'm using Rails 5.1 with ActionMailer.

Thanks again.

all_emails is great but difficult to find (documentation-wise)

I'm testing some functionality that sends multiple emails on an action (order completion) and I was having a really hard time because I only knew about current_email.

Eventually I found myself reading through the specs for the gem and noticed all_emails which is perfect! It would be nice if it was mentioned in the readme 😅

New release?

Hey @andrewhavens or whoever has the power, could you release a new version since there have been a few bugfixes since the last one and it's been a while?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.