javascriptjqueryajaxdatatablessystem-testing

How can I stop all the currently ongoing Ajax queries that DataTables instance have started?


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:

  1. The test runner starts the test server.

  2. The test runner loads in a test browser a page with a DataTable instance somewhere on it.

  3. The test runner runs the test, which performs its checks and ends.

  4. The test runner resets the test server to a known state for the next test.

  5. 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

  1. 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


Solution

  • 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.