mirror of
https://github.com/DataTables/DataTables.git
synced 2024-12-02 14:24:11 +01:00
468390c337
Dev: Removed the "fast lookup" function for data get and set as they weren't really that useful in terms of speed and would require more code to be added to copy with the above change to the error handling for missing objects. Smaller code and virtually no difference in speed. Sold.
410 lines
8.7 KiB
JavaScript
410 lines
8.7 KiB
JavaScript
/*
|
|
* File: unit_test.js
|
|
* Version: 0.0.1
|
|
* CVS: $Id$
|
|
* Description: Unit test framework
|
|
* Author: Allan Jardine (www.sprymedia.co.uk)
|
|
* Created: Sun Mar 8 22:02:49 GMT 2009
|
|
* Modified: $Date$ by $Author$
|
|
* Language: Javascript
|
|
* License: GPL v2 or BSD 3 point style
|
|
* Project: DataTables
|
|
* Contact: allan.jardine@sprymedia.co.uk
|
|
*
|
|
* Copyright 2009 Allan Jardine, all rights reserved.
|
|
*
|
|
* Description:
|
|
* This is a javascript library suitable for use as a unit testing framework. Employing a queuing
|
|
* mechanisim to take account of async events in javascript, this library will communicates with
|
|
* a controller frame (to report individual test status).
|
|
*
|
|
*/
|
|
|
|
|
|
var oTest = {
|
|
/* Block further tests from occuring - might be end of tests or due to async wait */
|
|
bBlock: false,
|
|
|
|
/* Number of times to try retesting for a blocking test */
|
|
iReTestLimit: 20,
|
|
|
|
/* Amount of time to wait between trying for an async test */
|
|
iReTestDelay: 150,
|
|
|
|
/* End tests - external control */
|
|
bEnd: false,
|
|
|
|
/* Internal variables */
|
|
_aoQueue: [],
|
|
_iReTest: 0,
|
|
_bFinished: false,
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Recommened public functions
|
|
*/
|
|
|
|
/*
|
|
* Function: fnTest
|
|
* Purpose: Add a test to the queue
|
|
* Returns: -
|
|
* Inputs: string:sMessage - name of the test
|
|
* function:fnTest - function which will be evaludated to get the test result
|
|
*/
|
|
"fnTest": function ( sMessage, fnSetup, fnTest )
|
|
{
|
|
this._aoQueue.push( {
|
|
"sMessage": sMessage,
|
|
"fnSetup": fnSetup,
|
|
"fnTest": fnTest,
|
|
"bPoll": false
|
|
} );
|
|
this._fnNext();
|
|
},
|
|
|
|
/*
|
|
* Function: fnWaitTest
|
|
* Purpose: Add a test to the queue which has a re-test cycle
|
|
* Returns: -
|
|
* Inputs: string:sMessage - name of the test
|
|
* function:fnTest - function which will be evaludated to get the test result
|
|
*/
|
|
"fnWaitTest": function ( sMessage, fnSetup, fnTest )
|
|
{
|
|
this._aoQueue.push( {
|
|
"sMessage": sMessage,
|
|
"fnSetup": fnSetup,
|
|
"fnTest": fnTest,
|
|
"bPoll": true
|
|
} );
|
|
this._fnNext();
|
|
},
|
|
|
|
/*
|
|
* Function: fnStart
|
|
* Purpose: Indicate that this is a new unit and what it is testing (message to end user)
|
|
* Returns: -
|
|
* Inputs: string:sMessage - message to give to the user about this unit
|
|
*/
|
|
"fnStart": function ( sMessage )
|
|
{
|
|
window.parent.controller.fnStartMessage( sMessage );
|
|
},
|
|
|
|
/*
|
|
* Function: fnComplete
|
|
* Purpose: Tell the controller that we are all done here
|
|
* Returns: -
|
|
* Inputs: -
|
|
*/
|
|
"fnComplete": function ()
|
|
{
|
|
this._bFinished = true;
|
|
this._fnNext();
|
|
},
|
|
|
|
/*
|
|
* Function: fnCookieDestroy
|
|
* Purpose: Destroy a cookie of a given name
|
|
* Returns: -
|
|
* Inputs: -
|
|
*/
|
|
"fnCookieDestroy": function ( oTable )
|
|
{
|
|
var sName = oTable.fnSettings().sCookiePrefix+oTable.fnSettings().sInstance;
|
|
var aParts = window.location.pathname.split('/');
|
|
var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase();
|
|
document.cookie = sNameFile+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+
|
|
aParts.join('/') + "/";
|
|
},
|
|
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Internal functions
|
|
*/
|
|
|
|
|
|
"_fnReTest": function ( oTestInfo )
|
|
{
|
|
var bResult = oTestInfo.fnTest( );
|
|
if ( bResult )
|
|
{
|
|
/* Test passed on retry */
|
|
this._fnResult( true );
|
|
this._fnNext();
|
|
}
|
|
else
|
|
{
|
|
if ( this._iReTest < this.iReTestLimit )
|
|
{
|
|
this._iReTest++;
|
|
setTimeout( function() {
|
|
oTest._fnReTest( oTestInfo );
|
|
}, this.iReTestDelay );
|
|
}
|
|
else
|
|
{
|
|
this._fnResult( false );
|
|
}
|
|
}
|
|
},
|
|
|
|
"_fnNext": function ()
|
|
{
|
|
if ( this.bEnd )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( !this.bBlock && this._aoQueue.length > 0 )
|
|
{
|
|
var oNextTest = this._aoQueue.shift();
|
|
window.parent.controller.fnTestStart( oNextTest.sMessage );
|
|
this.bBlock = true;
|
|
|
|
if ( typeof oNextTest.fnSetup == 'function' )
|
|
{
|
|
oNextTest.fnSetup( );
|
|
}
|
|
var bResult = oNextTest.fnTest( );
|
|
//bResult = false;
|
|
|
|
if ( oNextTest.bPoll )
|
|
{
|
|
if ( bResult )
|
|
{
|
|
this._fnResult( true );
|
|
this._fnNext();
|
|
}
|
|
else
|
|
{
|
|
_iReTest = 0;
|
|
setTimeout( function() {
|
|
oTest._fnReTest( oNextTest );
|
|
}, this.iReTestDelay );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this._fnResult( bResult );
|
|
this._fnNext();
|
|
}
|
|
}
|
|
else if ( !this.bBlock && this._aoQueue.length == 0 && this._bFinished )
|
|
{
|
|
window.parent.controller.fnUnitComplete( );
|
|
}
|
|
},
|
|
|
|
"_fnResult": function ( b )
|
|
{
|
|
window.parent.controller.fnTestResult( b );
|
|
this.bBlock = false;
|
|
if ( !b )
|
|
{
|
|
this.bEnd = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
var oDispacher = {
|
|
"click": function ( nNode, oSpecial )
|
|
{
|
|
var evt = this.fnCreateEvent( 'click', nNode, oSpecial );
|
|
if ( nNode.dispatchEvent )
|
|
nNode.dispatchEvent(evt);
|
|
else
|
|
nNode.fireEvent('onclick', evt);
|
|
},
|
|
|
|
"change": function ( nNode )
|
|
{
|
|
var evt = this.fnCreateEvent( 'change', nNode );
|
|
if ( nNode.dispatchEvent )
|
|
nNode.dispatchEvent(evt);
|
|
else
|
|
nNode.fireEvent('onchange', evt);
|
|
},
|
|
|
|
|
|
/*
|
|
* Function: fnCreateEvent
|
|
* Purpose: Create an event oject based on the type to trigger an event - x-platform
|
|
* Returns: event:evt
|
|
* Inputs: string:sType - type of event
|
|
* node:nTarget - target node of the event
|
|
*/
|
|
fnCreateEvent: function( sType, nTarget, oSpecial )
|
|
{
|
|
var evt = null;
|
|
var oTargetPos = this._fnGetPos( nTarget );
|
|
var sTypeGroup = this._fnEventTypeGroup( sType );
|
|
if ( typeof oSpecial == 'undefined' )
|
|
{
|
|
oSpecial = {};
|
|
}
|
|
|
|
var ctrlKey = false;
|
|
var altKey = false;
|
|
var shiftKey = (typeof oSpecial.shift != 'undefined') ? oSpecial.shift : false;
|
|
var metaKey = false;
|
|
var button = false;
|
|
|
|
if ( document.createEvent )
|
|
{
|
|
switch ( sTypeGroup )
|
|
{
|
|
case 'mouse':
|
|
evt = document.createEvent( "MouseEvents" );
|
|
evt.initMouseEvent( sType, true, true, window, 0, oTargetPos[0], oTargetPos[1],
|
|
oTargetPos[0], oTargetPos[1], ctrlKey, altKey, shiftKey,
|
|
metaKey, button, null );
|
|
break;
|
|
|
|
case 'html':
|
|
evt = document.createEvent( "HTMLEvents" );
|
|
evt.initEvent( sType, true, true );
|
|
break;
|
|
|
|
case 'ui':
|
|
evt = document.createEvent( "UIEvents" );
|
|
evt.initUIEvent( sType, true, true, window, 0 );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if ( document.createEventObject )
|
|
{
|
|
switch ( sTypeGroup )
|
|
{
|
|
case 'mouse':
|
|
evt = document.createEventObject();
|
|
evt.screenX = oTargetPos[0];
|
|
evt.screenX = oTargetPos[1];
|
|
evt.clientX = oTargetPos[0];
|
|
evt.clientY = oTargetPos[1];
|
|
evt.ctrlKey = ctrlKey;
|
|
evt.altKey = altKey;
|
|
evt.shiftKey = shiftKey;
|
|
evt.metaKey = metaKey;
|
|
evt.button = button;
|
|
evt.relatedTarget = null;
|
|
break;
|
|
|
|
case 'html':
|
|
/* fall through to basic event object */
|
|
|
|
case 'ui':
|
|
evt = document.createEventObject();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return evt;
|
|
},
|
|
|
|
/*
|
|
* Function: DesignCore.fnGetPos
|
|
* Purpose: Get the position of an element on the page
|
|
* Returns: array[ 0-int:left, 1-int:top ]
|
|
* Inputs: node:obj - node to analyse
|
|
*/
|
|
_fnGetPos: function ( obj )
|
|
{
|
|
var curleft = 0;
|
|
var curtop = 0;
|
|
|
|
if (obj.offsetParent)
|
|
{
|
|
curleft = obj.offsetLeft;
|
|
curtop = obj.offsetTop;
|
|
while (obj = obj.offsetParent )
|
|
{
|
|
curleft += obj.offsetLeft;
|
|
curtop += obj.offsetTop;
|
|
}
|
|
}
|
|
return [curleft,curtop];
|
|
},
|
|
|
|
|
|
/*
|
|
* Function: _fnEventTypeGroup
|
|
* Purpose: Group the event types as per w3c groupings
|
|
* Returns: -
|
|
* Inputs: string:sType
|
|
*/
|
|
_fnEventTypeGroup: function ( sType )
|
|
{
|
|
switch ( sType )
|
|
{
|
|
case 'click':
|
|
case 'dblclick':
|
|
case 'mousedown':
|
|
case 'mousemove':
|
|
case 'mouseout':
|
|
case 'mouseover':
|
|
case 'mouseup':
|
|
return 'mouse';
|
|
|
|
case 'change':
|
|
case 'focus':
|
|
case 'blur':
|
|
case 'select':
|
|
case 'submit':
|
|
return 'html';
|
|
|
|
case 'keydown':
|
|
case 'keypress':
|
|
case 'keyup':
|
|
case 'load':
|
|
case 'unload':
|
|
return 'ui';
|
|
|
|
default:
|
|
return 'custom';
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
var oSession = {
|
|
nTable: null,
|
|
|
|
fnCache: function ()
|
|
{
|
|
this.nTable = document.getElementById('demo').cloneNode(true);
|
|
},
|
|
|
|
fnRestore: function ()
|
|
{
|
|
while( $.fn.dataTableSettings.length > 0 )
|
|
{
|
|
try {
|
|
$.fn.dataTableSettings[0].oInstance.fnDestroy();
|
|
} catch (e) {
|
|
$.fn.dataTableSettings.splice( 0, 1 );
|
|
}
|
|
}
|
|
//$.fn.dataTableSettings.splice( 0, $.fn.dataTableSettings.length );
|
|
var nDemo = document.getElementById('demo');
|
|
nDemo.innerHTML = "";
|
|
for ( var i=0, iLen=this.nTable.childNodes.length ; i<iLen ; i++ )
|
|
{
|
|
nDemo.appendChild( this.nTable.childNodes[0] );
|
|
}
|
|
this.fnCache();
|
|
}
|
|
}
|
|
|
|
$(document).ready( function () {
|
|
oSession.fnCache();
|
|
} );
|