Background:
I'm coming from Java background so not too familiar with Javascript.
We are planning to introduce JavaScript unit testing to both our existing (legacy) code and future work. We are a java shop (Spring, Weblogic etc) mainly.
We are looking at options that give us good integration with IDE (IntelliJ idea) and sonar, as well as being able to run them as part of continuous integration.
JsTestDriver seems to tick all the boxes.
Question:
A lot of our existing javascript code is a)embeded within JSPs and b)utilises jQuery to interact with page elements directly.
How should we go about testing a function that is heavily reliant on the DOM. Here's some code examples of functions that I'm talking about:
function enableOccupationDetailsText (){
$( "#fldOccupation" ).val("Unknown");
$( "#fldOccupation_Details" ).attr("disabled", "");
$( "#fldOccupation_Details" ).val("");
$( "#fldOccupation_Details" ).focus();
}
or
jQuery(document).ready(function(){
var oTable = $('#policies').dataTable( {
"sDom" : 'frplitip',
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "xxxx.do",
"sPaginationType": "full_numbers",
"aaSorting": [[ 1, "asc" ]],
"oLanguage": {
"sProcessing": "Processing...",
"sLengthMenu": "Show _MENU_ policies",
"sZeroRecords": "No matching policies found",
"sInfo": "Showing _START_ to _END_ of _TOTAL_ policies",
"sInfoEmpty": "Showing 0 to 0 of 0 policies",
"sInfoFiltered": "(filtered from _MAX_ total policies)",
"sInfoPostFix": "",
"sSearch": "Search:",
"sUrl": "",
"oPaginate": {
"sFirst": "First",
"sPrevious": "Previous",
"sNext": "Next",
"sLast": "Last"
}
},
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
$('td:eq(0)', nRow).html( "<a href='/ole/policy/general_details.do?policy_id="+aData[0]+"'>"+aData[0]+"</a>" );
return nRow;
},
"fnServerData" : function ( url, data, callback, settings ) {
settings.jqXHR = $.ajax( {
"url": url,
"data": data,
"success": function (json) {
if (json.errorMessage != null) {
var an = settings.aanFeatures.r;
an[0].style.fontSize="18px";
an[0].style.backgroundColor="red";
an[0].style.height="70px";
an[0].innerHTML=json.errorMessage;
setTimeout('window.location="/xxxx"',1000);
//window.location="/xxxxx";
} else {
$(settings.oInstance).trigger('xhr', settings);
callback( json );
}
},
"dataType": "json",
"cache": false,
"error": function (xhr, error, thrown) {
if ( error == "parsererror" ) {
alert( "Unexpected error, please contact system administrator. Press OK to be redirected to home page." );
window.location="/xxxx";
}
}
} );
}
} );
$("#policies_filter :text").attr('id', 'fldKeywordSearch');
$("#policies_length :input").attr('id', 'fldNumberOfRows');
$("body").find("span > span").css("border","3px solid red");
oTable.fnSetFilteringDelay(500);
oTable.fnSearchHighlighting();
$("#fldKeywordSearch").focus();
}
);
In the latter case, my approach would be that the function in question is way too large and should be broken to smaller (units) so that it can be tested. But all the interaction points with DOM, jQuery, datatables, ajax etc makes it really complicated to refactor things in the way we do in Java world to make it more testable.
So, any suggestions for the above to sample cases would be greatly appreciated!
To test the following code:
function enableOccupationDetailsText (){
$( "#fldOccupation" ).val("Unknown");
$( "#fldOccupation_Details" ).attr("disabled", "");
$( "#fldOccupation_Details" ).val("");
$( "#fldOccupation_Details" ).focus();
}
You could use the following code:
// First, create the elements
$( '<input>', { id: 'fldOccupation' } ).appendTo( document.body );
$( '<input>', { disabled: true, id: 'fldOccupation_Details' } )
.appendTo( document.body );
// Then, run the function to test
enableOccupationDetailsText();
// And test
assert( $( '#fldOccupation' ).val(), 'Unknown' );
assert( $( '#fldOccupation_Details' ).prop( 'disabled' ), false );
As you see, it's just the classical setup > run > assert
pattern.
maybe Selenium/SeleniumGrid is usefull for you: http://seleniumhq.org/
It is not a "UnitTest" per definition, but you can write selenium tests with java or python (and many more...) as unit tests. Seleniumtests starts web tests in real browsers, and is quiet good for testing frontends (and dom manipulations).
Edit: today i stumbled upon this site describing different ways for unit-testing especially in a jQuery background: http://addyosmani.com/blog/jquery-testing-tools/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With