5 * Description: Unit test framework
6 * Author: Allan Jardine (www.sprymedia.co.uk)
7 * Created: Sun Mar 8 22:02:49 GMT 2009
8 * Modified: $Date$ by $Author$
10 * License: GPL v2 or BSD 3 point style
12 * Contact: allan.jardine@sprymedia.co.uk
14 * Copyright 2009 Allan Jardine, all rights reserved.
17 * This is a javascript library suitable for use as a unit testing framework. Employing a queuing
18 * mechanisim to take account of async events in javascript, this library will communicates with
19 * a controller frame (to report individual test status).
25 /* Block further tests from occuring - might be end of tests or due to async wait */
28 /* Number of times to try retesting for a blocking test */
31 /* Amount of time to wait between trying for an async test */
34 /* End tests - external control */
37 /* Internal variables */
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
44 * Recommened public functions
49 * Purpose: Add a test to the queue
51 * Inputs: string:sMessage - name of the test
52 * function:fnTest - function which will be evaludated to get the test result
54 "fnTest": function ( sMessage, fnSetup, fnTest )
66 * Function: fnWaitTest
67 * Purpose: Add a test to the queue which has a re-test cycle
69 * Inputs: string:sMessage - name of the test
70 * function:fnTest - function which will be evaludated to get the test result
72 "fnWaitTest": function ( sMessage, fnSetup, fnTest )
85 * Purpose: Indicate that this is a new unit and what it is testing (message to end user)
87 * Inputs: string:sMessage - message to give to the user about this unit
89 "fnStart": function ( sMessage )
91 window.parent.controller.fnStartMessage( sMessage );
95 * Function: fnComplete
96 * Purpose: Tell the controller that we are all done here
100 "fnComplete": function ()
102 this._bFinished = true;
107 * Function: fnCookieDestroy
108 * Purpose: Destroy a cookie of a given name
112 "fnCookieDestroy": function ( oTable )
114 var sName = oTable.fnSettings().sCookiePrefix+oTable.fnSettings().sInstance;
115 var aParts = window.location.pathname.split('/');
116 var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase();
117 document.cookie = sNameFile+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+
118 aParts.join('/') + "/";
123 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
128 "_fnReTest": function ( oTestInfo )
130 var bResult = oTestInfo.fnTest( );
133 /* Test passed on retry */
134 this._fnResult( true );
139 if ( this._iReTest < this.iReTestLimit )
142 setTimeout( function() {
143 oTest._fnReTest( oTestInfo );
144 }, this.iReTestDelay );
148 this._fnResult( false );
153 "_fnNext": function ()
160 if ( !this.bBlock && this._aoQueue.length > 0 )
162 var oNextTest = this._aoQueue.shift();
163 window.parent.controller.fnTestStart( oNextTest.sMessage );
166 if ( typeof oNextTest.fnSetup == 'function' )
168 oNextTest.fnSetup( );
170 var bResult = oNextTest.fnTest( );
173 if ( oNextTest.bPoll )
177 this._fnResult( true );
183 setTimeout( function() {
184 oTest._fnReTest( oNextTest );
185 }, this.iReTestDelay );
190 this._fnResult( bResult );
194 else if ( !this.bBlock && this._aoQueue.length == 0 && this._bFinished )
196 window.parent.controller.fnUnitComplete( );
200 "_fnResult": function ( b )
202 window.parent.controller.fnTestResult( b );
213 "click": function ( nNode, oSpecial )
215 var evt = this.fnCreateEvent( 'click', nNode, oSpecial );
216 if ( nNode.dispatchEvent )
217 nNode.dispatchEvent(evt);
219 nNode.fireEvent('onclick', evt);
222 "change": function ( nNode )
224 var evt = this.fnCreateEvent( 'change', nNode );
225 if ( nNode.dispatchEvent )
226 nNode.dispatchEvent(evt);
228 nNode.fireEvent('onchange', evt);
233 * Function: fnCreateEvent
234 * Purpose: Create an event oject based on the type to trigger an event - x-platform
236 * Inputs: string:sType - type of event
237 * node:nTarget - target node of the event
239 fnCreateEvent: function( sType, nTarget, oSpecial )
242 var oTargetPos = this._fnGetPos( nTarget );
243 var sTypeGroup = this._fnEventTypeGroup( sType );
244 if ( typeof oSpecial == 'undefined' )
251 var shiftKey = (typeof oSpecial.shift != 'undefined') ? oSpecial.shift : false;
255 if ( document.createEvent )
257 switch ( sTypeGroup )
260 evt = document.createEvent( "MouseEvents" );
261 evt.initMouseEvent( sType, true, true, window, 0, oTargetPos[0], oTargetPos[1],
262 oTargetPos[0], oTargetPos[1], ctrlKey, altKey, shiftKey,
263 metaKey, button, null );
267 evt = document.createEvent( "HTMLEvents" );
268 evt.initEvent( sType, true, true );
272 evt = document.createEvent( "UIEvents" );
273 evt.initUIEvent( sType, true, true, window, 0 );
280 else if ( document.createEventObject )
282 switch ( sTypeGroup )
285 evt = document.createEventObject();
286 evt.screenX = oTargetPos[0];
287 evt.screenX = oTargetPos[1];
288 evt.clientX = oTargetPos[0];
289 evt.clientY = oTargetPos[1];
290 evt.ctrlKey = ctrlKey;
292 evt.shiftKey = shiftKey;
293 evt.metaKey = metaKey;
295 evt.relatedTarget = null;
299 /* fall through to basic event object */
302 evt = document.createEventObject();
314 * Function: DesignCore.fnGetPos
315 * Purpose: Get the position of an element on the page
316 * Returns: array[ 0-int:left, 1-int:top ]
317 * Inputs: node:obj - node to analyse
319 _fnGetPos: function ( obj )
324 if (obj.offsetParent)
326 curleft = obj.offsetLeft;
327 curtop = obj.offsetTop;
328 while (obj = obj.offsetParent )
330 curleft += obj.offsetLeft;
331 curtop += obj.offsetTop;
334 return [curleft,curtop];
339 * Function: _fnEventTypeGroup
340 * Purpose: Group the event types as per w3c groupings
342 * Inputs: string:sType
344 _fnEventTypeGroup: function ( sType )
383 this.nTable = document.getElementById('demo').cloneNode(true);
386 fnRestore: function ()
388 while( $.fn.dataTableSettings.length > 0 )
391 $.fn.dataTableSettings[0].oInstance.fnDestroy();
393 $.fn.dataTableSettings.splice( 0, 1 );
396 //$.fn.dataTableSettings.splice( 0, $.fn.dataTableSettings.length );
397 var nDemo = document.getElementById('demo');
398 nDemo.innerHTML = "";
399 for ( var i=0, iLen=this.nTable.childNodes.length ; i<iLen ; i++ )
401 nDemo.appendChild( this.nTable.childNodes[0] );
407 $(document).ready( function () {