Getting jasminerice & requirejs-rails to play nicely together

Published:

Jasminerice uses an isolated Rails engine to display the Jasmine spec runner. Unfortunately, this means it cannot see requirejs-rails is included in your project. Adding #= require.js to the spec/javascripts/spec.js.coffee file will cause problems because it cannot read your config/requirejs.yml configuration file. Nightmare!

So how do we fix this, whilst maintaining a nice DRY setup where Jasmine is setup with RequireJS using the options you’ve set in the configuration file?

The Jasminerice spec controller attempts to include a helper called Jasminerice::HelperMethods, which doesn’t actually exist, but as Brad has wrapped it in a begin … end block, does not error. We can start by including requirejs by placing the code below in lib/jasminerice/helper_methods.rb:

require "requirejs-rails"

module Jasminerice
  module HelperMethods
    def self.included(base)
      base.class_eval do
        helper RequirejsHelper
      end
    end
  end
end

Note: ensure the lib path is being auto-loaded by Rails (see your config/application.rb).

We can now overwrite the view for the engine by creating the file app/views/jasminerice/spec/index.html.erb with the following contents:

<!doctype html>
<head>
  <title>Jasmine Spec Runner</title>
  <%= stylesheet_link_tag "jasmine", "spec" %>
  <%= requirejs_include_tag %>
  <%= javascript_include_tag "jasminerice", "spec" %>
  <%= csrf_meta_tags %>
</head>
<body>
</body>
</html>

The key line above is the requirejs_include_tag call, which must be above the other JavaScript includes.

Note: with this setup, you do not need to follow the instructions provided by jasminerice, they are designed for vanilla requirejs usage - not usage with the requirejs-rails gem.

You can now write your specs as if they were normal JS or CoffeeScript files using the modules, here’s an example:

require ["app"], (App) ->
  describe "App", ->
    it "should have a method called 'boot'", ->
      app = new App()
      expect(app.boot).toBeDefined()

Whilst this might be a pretty rare setup, it may be of use to some people, and hopefully RequireJS usage and JavaScript testing will become more common in the Rails community.