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.