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 . 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 and RSpec the application runs on.
What’s AJAX? (Asynchronous Javascript and XML)
AJAX (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 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 .
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 .
After upgrading from Rails 4.0 to 4.1 , any AJAX requests will cause an error with a CSRF 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
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.