Unit testing Javascript has quickly become an absolute requirement for building a modern web application. It’s not uncommon for most web applications to have more Javascript code/libraries than serverside logic. There are plenty of frameworks javascript testing frameworks available for unit testing your standalone javascript components (JSUnit, QUnit, etc), but how do you test Javascript responses generated by Rails?
Let’s start by describing problem in a bit more detail. Here are a few snippits of code that you’ll find in pretty much any AJAX heavy Rails application.
Example Rails form for creating a new blog post via AJAX:
# app/views/blogs/new.html.haml
= form_for Blog.new, :remote => true do |f|
= f.text_area :body
= f.submit
Example Rails controller to create blog post:
# app/controllers/blog_controller.rb
class BlogController def create
@blog = Blog.create params[:blog]
respond_with @blog
end
end
Example Rails Javascript ERB response to return new blog post:
# app/views/blogs/create.js.erb
$('#new_blog_form').trigger('reset');
$('body').append('<h2>New Blog Post has been created!</h2>');
$('body').append('<div />');
Now this is a very simple example, but how can you effectively assert that the Javascript response is doing what you expect? Sure, you can use selenium or some other heavyweight testing library to boot up a browser and exercise your Javascript, but there’s got to be a quicker way to get the job done.
With a few simple solutions, you can get a lot of bang for your buck without introducing more complex and finicky end to end testing frameworks.
Move Javascript Logic to Static Component
Refactoring your Javascript response to use the “Fat Component, Skinny Response” pattern is the same pattern we’ve been using for building our controllers, and it moves all of the logic out of your ERB templates and into a standalone (and testable) Javascript component.
Example refactored Javascript response:
# app/views/blogs/create.js.erb
myApp.createBlog();
Example Javascript component:
# public/javascripts/application.js
myApp = {
createBlog: function(data) {
$('#new_blog_form').trigger('reset');
$('body').append('<h2>New Blog Post has been created!</h2>');
var content = $('p').text(data.body);
$('body').append(content);
}
};
Now you can effectively unit test your component using traditional Javascript testing libraries.
JSLint the Rails Response
JSLint is a simple and very effective smoketest to ensure that any Javascript response is valid and without syntax errors. This prevents any extra semi-colons or simple syntax errors from breaking your user’s browser. All “modern” browsers are pretty forgiving when dealing with Javascript errors, but one browser in particular cough IE cough can really freak out if it encounters invalid Javascript
Rspec users can drop this be_lintable helper into there application for a quick sanity check that their JS responses should be operational. Not using RSpec? The JSLint on Rails plugin is pretty simple to integrate into any application.
describe 'xhr post :create' do
before { xhr :post, :create, :blog => {:body => 'test'} }
it { response.body.should be_lintable }
end
Now go forth and test those Javascript Rails responses!