Testing AJAX with Test::Unit

If you want real end-to-end testing of a page with functioning AJAX, use Selenium. But I was interested in doing just a bit of JS speccing to make sure that the AJAX routes I called worked and that the data that came back fit the JS that I had written.

So, I figured with a little capybara and a little therubyracer, I could test my javascript with real route calls. Let's check it out.

The Javascript I want to test:

var dataObject = {};
var getRemoteData = function() {
  $.getJSON('/remote_path.json', function(data) {
    dataObject = $.parseJSON(data);
  });
}

We will pretend that hitting /remote_path.json returns the following response in JSON:

{ "my_information": "my response data" }

I want to test:

  1. That /remote_path.json is accessible and returns information
  2. That dataObject is populated with a Javascript Object containing the params I pass down

Here is my commented testing code:

test 'get some information via ajax' do
    # Create a new JS Context. :with => self means that
    # the global namespace is the current context
    js = V8::Context.new(:with => self)

    # Load up our JS file
    js.load(File.join(Rails.root, 'public', 'javascripts', 'application.js'))

    # Define a mock method for getting JSON data
    def getJSON(url, callback)
      # When the JS wants some data, get it for real w/ capybara
      visit url
      # And call the JS function passed in (ruby => js)
      callback.call(page.body)
    end

    js.eval %{
      /* Mock out jQuery */
      var $ = {};

      /* Setup the mock in the right place (JS => ruby) */
      $.getJSON = getJSON; 

      /* Mock out jquery parseJSON to call ruby JSON.parse
         Since the args are the same, it is plug and play!
         (JS => ruby) */
      $.parseJSON = JSON.parse;

      /* Trigger our JS */
      getRemoteData();

      /* Assert what we expect (JS => ruby) */
      assert_equal(" ", dataObject.access_key);
    }
  end

This is not an example of an incredibly useful test, but I found the ability to bind back and forth easily between ruby and javascript to be mind-blowingly incredible. I mean, look at that last line, where I call assert and pass a javascript object to it!

Huge thanks to Charles Lowell (cowboyd) for his hard work on therubyracer.

Enjoy the weekend!

Check out our other articles discussing Capybara:

How to Test PDF Content with Capybara

You've successfully subscribed to SmartLogic Blog
Great! Next, complete checkout for full access to SmartLogic Blog
Welcome back! You've successfully signed in.
Unable to sign you in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.