How do I set up a Rails Angular project to test JS?

You can use teaspoon it runs your favorite test suite (default is jasmine) and they have a wiki to integrate with angular. Teaspoon integrates with the asset pipeline, so you can throw all the angular gems in there and require them in the teaspoon generated spec_helper.js.

The other cool thing is: they have a guard plugin available as well.


I feel your pain, it took me a bit of trial and error to get all tests running for my Rails app. I ended up using Guard for developer continuous testing for specs, acceptance, and javascripts. Here are the fruits of my labor.

This is the Gemfile snippet you will need to include. It has the required Gems for Guard, Jasmine, Rspec, and Turnip. This setup will work with MRI and JRuby, we run our tests on both.

group :test, :development do
  # Guard
  gem 'guard-jasmine'
  gem "guard-bundler", ">= 1.0.0"
  gem "guard-rails", ">= 0.4.0"
  gem "guard-rspec", ">= 2.5.2"
  gem "rb-inotify", ">= 0.9.0", :require => false
  gem "rb-fsevent", ">= 0.9.3", :require => false
  gem "rb-fchange", ">= 0.0.6", :require => false

  # Rspec
  gem "rspec-rails", '~> 2.12.2'

  # Jasmine
  gem "jasmine", '~> 1.3.1'
  gem "jasminerice"
end

group :test do
  # Turnip
  gem "turnip", '~> 1.1.0'
  gem "capybara", '~> 2.0.3'
end

This the full Guardfile that watches Rspec, Turnip, and Jasmine to trigger tests:

guard 'rspec' do
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch('spec/spec_helper.rb')  { "spec" }

  # Rails 
  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
  watch(%r{^app/(.*)(\.erb|\.haml)$})                 { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
  watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
  watch('config/routes.rb')                           { "spec/routing" }
  watch('app/controllers/application_controller.rb')  { "spec/controllers" }

  # Turnip features and steps
  watch(%r{^spec/acceptance/(.+)\.feature$})
  watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$})   { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
end

guard :jasmine do
  watch(%r{spec/javascripts/spec\.(js\.coffee|js|coffee)$}) { 'spec/javascripts' }
  watch(%r{spec/javascripts/.+_spec\.(js\.coffee|js|coffee)$})
  watch(%r{spec/javascripts/fixtures/.+$})
  watch(%r{app/assets/javascripts/(.+?)\.(js\.coffee|js|coffee)(?:\.\w+)*$}) { |m| "spec/javascripts/#{ m[1] }_spec.#{ m[2] }" }
end

Now things get a little tricky. To get Jasmine to properly load up AngularJS for tests I downloaded angular-mocks.js 1.0.7 to the directory spec/javascripts/support/angular-mocks.js. This is used by the spec helper and the jasmine config to run the AnguljarJS specs.

For the spec/javascripts/spec_helper.js.coffee, point it at the Rails app javascript, the angular-mocks.js, and all the javascript specs:

#=require ../../app/assets/javascripts/application
#=require ./support/angular-mocks
#=require_tree ./

For the Jasmine config, spec/javascripts/support/jasmine.yml, the config will need to point at the Rails app javascript and the angular-mocks.js. Here is the we use, but with the comments removed for brevity:

src_files:
  - assets/application.js
  - spec/javascripts/support/angular-mocks.js

stylesheets:
  - stylesheets/**/*.css

helpers:
  - helpers/**/*.js

spec_files:
  - '**/*[sS]pec.js'

src_dir:

spec_dir: spec/javascripts

With everything set up, you simply have to run bundle exec guard and all the tests will run and be triggered by development changes.


I've written a blog post about a very simple way to set up AngularJS unit testing on a Rails app using the default Jasmine gem. It took a small code change to get things working smoothly, which has been accepted by the Jasmine team.

http://pivotallabs.com/unit-testing-angularjs-using-jasmine/

In an nutshell:

Add jasmine and angularjs-rails to your Gemfile

gem "angularjs-rails"
gem "jasmine", github: "pivotal/jasmine-gem"

Install the gems and run the Jasmine generator

$ bundle install
$ rails g jasmine:install

Add angular to your application.js, before the rest of your application code

//= require angular
//= require_tree .

Create a file named ./spec/javascripts/helpers/angular_helpers.js and add this line

//= require angular-mocks

Now you can include AngularJS implementation files in your app/assets directory and write tests that use the provided mocks. And when you upgrade the angularjs-rails gem, you will get new versions of angular.js and angular-mocks.js at the same time.