With the advent of new web-based applications, the ability to dynamically manipulate data, provide interactivity, and be compatible on all devices and browsers has become more important than ever. At the end of the day, the core technologies involved are HTML, CSS, and JavaScript. From these three things, a lot of helping technologies and frameworks evolved. There’s HAML, SASS, and CoffeeScript to name a few. They were all created to make the development cycles shorter, easier, and the code base simplified. However, no matter how much the web technology stack change, there are certain principles that applicable to the engineering and development. In this blog, we will explore certain ways to make JavaScript writing more organized and DRY, especially if your organization decided not to use established frontend frameworks like Angular or React.

function refreshTableSummary() {
  var requestBody = getFormData();
  $.ajax({
    url : "summary",
    type : 'get',
    data : requestBody,
    success : function success(data) {
      $('#body').empty();
      var summaryArray = new Array(data['cost'], data['profit'], data['expenses'], data['netProfit']);
      for (var i = 0; i < summaryArray.length; i++) {
        refreshRow(summaryArray[i], '#summary-table-body');
      }
      $('td:not(.numbertd)').addClass('numbertd');
    }
  }
  });
}

What is the code above and what is wrong with it? It’s a perfectly adequate piece of code. It can be called to execute AJAX, retrieve the data, and use it to fill up some DOM elements. You can add a few more lines of code to guarantee that the old data goes away when you call this function and do some error handling. But here’s the problem (and it’s a question that is asked at any part of software engineering): how can I test it? Your app will be launching in a few weeks or months, and the sense of uncertainty about its stability hasn’t gone away. And that piece of code there is not very unit-testing friendly. It can certainly be integration tested, but can it be unit-tested?

The problem here is tight coupling. The AJAX callback should not need direct access to the DOM manipulation, and should be abstracted to make things modular. The benefit of doing this is that if you ever need to manually add a few new elements to the DOM, you can easily do so without having to query the server for it (for example, if you need to display an ’empty table’ message as a TD element).

So consider the following:


function refreshTableSummary(requestBody) {
  var defer;

  if (!requestBody) {
    defer = $.Deferred();
    defer.resolve([]);
    return defer.promise();
  }
  return $.ajax({
    url : "summary",
    type : 'get',
    data : requestBody
  }).pipe(function( resp ) {
    return resp.results;
  });
}
function fillData (myData){
  $('#body').empty();
  var summaryArray = new Array(data['cost'], data['profit'], data['expenses'], data['netProfit']);
  for (var i = 0; i < summaryArray.length; i++) {
    refreshRow(summaryArray[i], '#summary-table-body');
  }
}

This way, the DOM manipulation is decoupled from the AJAX interaction, and as two “units” they can be tested separately. There are a lot more that are needed to make this work, but at least you get the gist of it.

The basis of this article can be found at: http://alistapart.com/article/writing-testable-javascript

Leave a comment

Your email address will not be published. Required fields are marked *

X