Testing AJAX controller requests with different versions of Rails and RSpec

Testing AJAX controller requests with different versions of Rails and RSpec

Recently I got to work on a task that included understanding how to test JavaScript requests with RSpec opens a new window . One thing that I found missing during my time researching solutions was organized and detailed documentation explaining the solutions based on the version of Rails opens a new window and RSpec the application runs on.

What’s AJAX? (Asynchronous Javascript and XML)

AJAX opens a new window (Asynchronous JavaScript and XML) is an approach that combines the use of many different technologies such as HTML or XHTML, CSS, JavaScript, DOM, XML, XSLT, and most importantly the XMLHttpRequest object to provide a better user experience by allowing asynchronous behavior that avoids reloading or rerouting the user.

A request can be made from the client using an asynchronous method such as the fetch API opens a new window to a server.

The server will then respond with some data completing the request-response cycle.

If an application is built using Ruby on Rails, it will come packed with rails-ujs which allows to inject JS behavior and provide dynamic DOM updates simply by adding ‘data’ helpers in the Rails HTML markup.

Find more information about rails-ujs here opens a new window .

Testing AJAX controller requests

Testing AJAX requests is not always straightforward. I’m going to explain the problem I ran into and how I solved it.

The problem

Rails did not extend Cross-site request forgery (CSRF) to GET requests until the release of Rails version 4.1. This meant that an application could be vulnerable to cross-origin embedding that could leak sensitive data opens a new window .

After upgrading from Rails 4.0 to 4.1 opens a new window , any AJAX requests will cause an error with a CSRF opens a new window failure message.

This happens because all requests (now including GET requests) will need to contain the CSRF token in the headers.

This can be solved using the xhr (XmlHttpRequests) method.

Solution

What I have found during this research is that the solution is not so cookie cutter, so let’s discuss what the fix is based on the version your Rails application is currently running on and the version of RSpec used to run the specs.

Rails version < 4.1

No necessary changes are required since the xhr requirement has not yet been introduced when making a GET request.

Rails version 4.1 to 5.0 and RSpec <= 3.1

When making a GET request, the request should be updated to:

Before:


get :index, format: :js

After:


xhr :get, :index

Rails version > 5.0 and RSpec > 3.1

It is important to note that the xhr method was deprecated in Rails 5 opens a new window so the option xhr: true will need to be passed in the request instead:

Before:


get :index, format: :js

- or -

xhr :get, :index

After:


get :index, xhr: true

Conclusion

AJAX is an incredible implementation that improves the user experience and performance of web applications.

In a Rails application, we will want to ensure that AJAX is operating efficiently which means we will need to test our controllers and their subsequent requests.

In order to do so, we want to make sure to follow the patterns and use the methods relative to the version of Rails and RSpec the application is using to include the XMLHttpRequest object and avoid running into any CSRF failures or issues.

Get the book