Brief Description
Resetting a test server to a known state causes my tests to fail due to Ajax requests launched by DataTables instances being ongoing at the time the server is reset. I’d like to prevent this by stopping the DataTables requests before the server is reset.
Detailed Description
I have an application in which I use DataTables on some pages. These DataTables all perform server-side queries to populate their tables.
When I perform system testing, sometimes there is a race condition that can happen:
The test runner starts the test server.
The test runner loads in a test browser a page with a DataTable instance somewhere on it.
The test runner runs the test, which performs its checks and ends.
The test runner resets the test server to a known state for the next test.
An alert shows up on the page, saying that DataTables experienced an Ajax error. The alert says:
DataTables warning: table id=[some id] – Ajax error. For more information about this error, please see http://datatables.net/tn/7
- My testing system, which is not expecting the alert, is confused and registers a failure even though the test was in fact successful. (Or in some cases, it crashes.)
I know this happens because the server abruptly interrupted an Ajax request. What I am looking for is a way to prevent the alert from coming up in the first place. I’d like to stop all ongoing DataTables requests before the server is reset.
Solutions already rejected
Tell the DataTables instances not to use alerts: I want my tests to fail louldly if a DataTables instance runs into an issue that is not related to resetting the test server.
Modifying the test server: I prefer to keep the server simple and not worry there about requests that may go unanswered.
Wait client-side for all requests to be over: this can slow down tests considerably, especially when this wait is repeated for dozens of tests.
Direct the test browser to a new page, without DataTables on it, as this will interrupt the current requests: again this will hurt test performance.
Advertisement
Answer
Solution
Have the software that drives the browser execute the following code in the browser after a test has completed all its checks. (This would be in some sort of “tear down” code run after the test.)
if (typeof $ !== "undefined" && $.fn.dataTable) { var all_settings = $($.fn.dataTable.tables()).DataTable().settings(); for (var i = 0, settings; (settings = all_settings[i]); ++i) { if (settings.jqXHR) settings.jqXHR.abort(); } }
Explanation
The code is written to work even when executed on pages that don’t have jQuery loaded or don’t have DataTables loaded. So it first checks whether they are loaded, and does not do anything if they are not loaded. Then it fetches the settings objects for all DataTable instances. In each settings objects, it checks for the presence of jqXHR
, which is populated with a jQuery jqXHR
object when an Ajax request has been made. It will call the abort()
method on it, thus aborting the request.
The code above works with DataTables 1.10 whether the tables use the 1.10 API or the 1.9 API. However, note that the jqXHR
field is not formally part of the public API. At the same time, one of the devs speaks about it without caveat on DataTables forum, so this is probably not the riskiest part of the private API to rely on. And a solution that relies purely on the public API would be much more cumbersome as all DataTable instances would have to be modified to track the events that mark the start of an Ajax transaction and its end or have customized Ajax handlers, etc. This would have to be done not only for the code proper to the project being tested but any 3rd party library that provides HTML widgets that happen to use DataTables.
Note that the code above does not prevent DataTables instances from initiating new requests. But this is not a concern I have.