I made the title of this article a mouthful to show how many libraries you have to use to do some Javascript testing. I did what I’m about to do in this article recently in order to figure out where my Javascript tests were going wrong in a more complicated project.
What You Need to Have Installed In Your Rails Application
- Cucumber gem
- Capybara gem
- Poltergeist gem
- Twitter bootstrap (see http://railsapps.github.com/twitter-bootstrap-rails.html for a good resource on how to configure your app with bootstrap)
- PhantomJS installed on your system (I talk about how to install it on Ubuntu Linux here; in addition, there’s some nice installation instructions at the main PhantomJS site).
A Small Shortcut To Help You Get Up and Running
You can fork a copy of the application over at https://github.com/treble37/rails3-poltergeist-rspec-cucumber-capybara-devise-example.
The bootstrap-modal-dialog-test branch (not the master) has all the code I’m going to talk about in this upcoming tutorial. You may want to start on the master branch instead if you want to implement the changes yourself. Please note that I forked this application from someone else’s application skeleton in order to quickly prototype this test. Hooray for open source! Then install the required gems in your gemset (I’m assuming you’re using rvm) via the bundle install command.
What I actually changed in my forked repository
Change app/features/support/env.rb to use the poltergeist driver
require 'cucumber/rails' require 'capybara/poltergeist' : Capybara.javascript_driver=:poltergeist
Assets
Daniel’s tutorial tells you to do it, but you need to remember to include Bootstrap’s javascript via the require directive in your application.js file as follows:
//= require jquery //= require jquery_ujs //= require bootstrap //= require_tree .
Bootstrap stuff
After pasting in the code from Daniel Kehoe’s tutorial into app/views/layouts/_navigation.html.erb, I changed the “Login” and “Logout” links to “Sign in” and “Sign out” so they would be compatible with the Cucumber/Capybara integration tests.
Adding the Bootstrap Modal Dialog HTML Code
I just copied the “Launch demo modal” code from the Bootstrap site at http://twitter.github.com/bootstrap/javascript.html#modals and pasted it into application.html.erb. One thing I did do was encapsulate it into a Boostrap container class:
<div class="container">
<div class="content">
<div class="row">
<div class="span12">
<!-- Button to trigger modal -->
<a href="#myModal" role="button" class="btn" data-toggle="modal"
>Launch demo modal</a
>
<!-- Modal -->
</div>
</div>
</div>
</div>
<!--! end of .container -->
Cucumber Scenario
Since I forked a skeleton application with cucumber scenarios built in I only had to add the following scenario:
Scenario: modal dialog test Given homepage When I click the 'Launch demo modal' link And I click the 'Close' button Then I should see the homepage content
Cucumber Step(s)
I just added a simple step to make sure the user could see the home page content after the modal dialog box was closed:
Then /^I should see the homepage content$/ do page.should have_content("Listing posts") end
Time to run the tests
At the command line, type bundle exec cucumber features/.
Hmm...an error..."undefined_method"
node_name' for nil:NilClass (NoMethodError)...
The hack
After some Googling, it seems that Capybara likes to have its input elements (like buttons and links) clicked inside a form element. So I then encapsulated the modal html code in a form tag as follows:
<!-- Button to trigger modal -->
<a class="btn" href="#myModal" data-toggle="modal">Launch demo modal</a>
<!-- Modal -->
And now all your tests should be green.
Another Cucumber Scenario
Scenario: show post in modal dialog Given a post has been created Given homepage When I click the 'Show' link Then I should see a popup with the post information And I click the 'google' link Then I should see the google home page
Cucumber Step(s)
Then /^I should see a popup with the post information$/ do page.should have_content("Post Title: Post X Title") end Then /^I should see the google home page$/ do current_url.should == "http://www.google.com/" end
Add show.js.erb view
$('#myModalLabel').html('Post Title: <%=j @post.title %>'); $('#myModal .modal-body').html('Post Body: <%=j @post.body %>google'); $('#myModal').modal('show');
Time to run the tests
At the command line, type _bundle exec cucumber features/_.
Hmm…an error…(RSpec::Expectations::ExpectationNotMetError)
It turns out we need to add an @javascript
tag before our scenario. This tells
Capybara to use the poltergeist javascript driver so it can find the popup box
that has a Javascript generated link to Google.com
@javascript Scenario: show post in modal dialog Given a post has been created Given homepage :
Now our tests pass.