377 lines
9.2 KiB
JavaScript
377 lines
9.2 KiB
JavaScript
|
|
||
|
( function()
|
||
|
{
|
||
|
$( document ).ready( function()
|
||
|
{
|
||
|
var runner = TestRunner( jQuery );
|
||
|
|
||
|
// display js-dependent content
|
||
|
$( '.hasjs' ).removeClass( 'hasjs' );
|
||
|
|
||
|
listCases( rectest.cases, $( '#case' ) );
|
||
|
|
||
|
displayNotice( 'Please configure the test using the form below.' );
|
||
|
|
||
|
$( '#continue' ).click( function()
|
||
|
{
|
||
|
var options = {},
|
||
|
values = [
|
||
|
'case', 'set', 'interval', 'blank', 'samples', 'delay'
|
||
|
],
|
||
|
i = values.length;
|
||
|
|
||
|
while ( i-- )
|
||
|
{
|
||
|
var id = values[ i ];
|
||
|
options[ id ] = $( '#' + id ).val();
|
||
|
}
|
||
|
|
||
|
var testcase = rectest.cases[ options['case'] ].testCase();
|
||
|
|
||
|
$( this ).parent().hide();
|
||
|
runner.run( testcase, options );
|
||
|
} );
|
||
|
|
||
|
function displayNotice( str )
|
||
|
{
|
||
|
$( '.notice' )
|
||
|
.text( str )
|
||
|
.addClass( 'active' );
|
||
|
}
|
||
|
|
||
|
function listCases( presets, $select )
|
||
|
{
|
||
|
for ( var preset in presets )
|
||
|
{
|
||
|
var data = presets[ preset ];
|
||
|
|
||
|
$select.append( $( '<option>' )
|
||
|
.attr( 'value', preset )
|
||
|
.text( data.title )
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
} );
|
||
|
|
||
|
|
||
|
var TestCase = easejs.Interface( 'TestCase',
|
||
|
{
|
||
|
'public getSet': [ 'set_id' ],
|
||
|
|
||
|
'public render': [ 'id', 'element' ]
|
||
|
} );
|
||
|
|
||
|
var TestRun = easejs.Class( 'TestRun',
|
||
|
{
|
||
|
/**
|
||
|
* Test case being executed
|
||
|
* @var {TestCase}
|
||
|
*/
|
||
|
'private _case': null,
|
||
|
|
||
|
/**
|
||
|
* Number of samples remaining
|
||
|
* @var {number}
|
||
|
*/
|
||
|
'private _samplesRemain': 0,
|
||
|
|
||
|
/**
|
||
|
* Set to operate on
|
||
|
* @var {Array.<string>}
|
||
|
*/
|
||
|
'private _set': [],
|
||
|
|
||
|
/**
|
||
|
* Set length
|
||
|
* @var {number}
|
||
|
*/
|
||
|
'private _setLength': 0,
|
||
|
|
||
|
/**
|
||
|
* Current set position
|
||
|
* @var {number}
|
||
|
*/
|
||
|
'private _setPos': 0,
|
||
|
|
||
|
/**
|
||
|
* History of each returned element id
|
||
|
* @var {Array.<string>}
|
||
|
*/
|
||
|
'private _history': [],
|
||
|
|
||
|
|
||
|
__construct: function( test_case, options )
|
||
|
{
|
||
|
this._case = test_case;
|
||
|
this._set = test_case.getSet( options.set );
|
||
|
this._setLength = this._set.length;
|
||
|
this._samplesRemain = +options.samples || -1;
|
||
|
|
||
|
this._reset();
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _repeatSet': function( set, n, s2 )
|
||
|
{
|
||
|
s2 = s2 || [];
|
||
|
|
||
|
var i = set.length;
|
||
|
|
||
|
if ( n === 0 )
|
||
|
{
|
||
|
return s2;
|
||
|
}
|
||
|
|
||
|
// does not matter that we're doing it in reverse, since the set
|
||
|
// will be randomized later
|
||
|
while ( i-- )
|
||
|
{
|
||
|
s2[ i ] = set[ i ];
|
||
|
}
|
||
|
|
||
|
return this._repeatSet( set, --n, s2 );
|
||
|
},
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Randomizes a set using the Fisher-Yates shuffle algorithm
|
||
|
*
|
||
|
* @param {Array} set set to sort
|
||
|
*/
|
||
|
'private _randomizeSet': function( set )
|
||
|
{
|
||
|
var i = set.length;
|
||
|
|
||
|
// simply prevent an infinite loop below
|
||
|
if ( i === 0 )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// simply loop through each element in the set, swapping each with a
|
||
|
// random index
|
||
|
while ( --i )
|
||
|
{
|
||
|
var r = Math.floor( Math.random() * ( i + 1 ) );
|
||
|
set[ i ] = [ set[ r ], ( set[ r ] = set[ i ] ) ][ 0 ];
|
||
|
}
|
||
|
},
|
||
|
|
||
|
|
||
|
'public getNextElement': function()
|
||
|
{
|
||
|
// reset once we're at the end
|
||
|
if ( this._setPos === this._setLength )
|
||
|
{
|
||
|
this._reset();
|
||
|
}
|
||
|
|
||
|
// return null once we have returned all of the requested samples
|
||
|
// (intentionally a 0 check, as this will be negative for an
|
||
|
// infinite number of samples)
|
||
|
if ( this._samplesRemain-- === 0 )
|
||
|
{
|
||
|
console.log( this._history );
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// return element from set (do not shift/pop, since we may need to
|
||
|
// repeatedly iterate through this list)
|
||
|
var val = this._set[ this._setPos++ ];
|
||
|
this._history.push( val );
|
||
|
|
||
|
return val;
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _reset': function()
|
||
|
{
|
||
|
this._setPos = 0;
|
||
|
this._randomizeSet( this._set );
|
||
|
}
|
||
|
} );
|
||
|
|
||
|
|
||
|
var TestRunner = easejs.Class( 'TestRunner',
|
||
|
{
|
||
|
/**
|
||
|
* jQuery instance
|
||
|
* @var {jQuery}
|
||
|
*/
|
||
|
'private _jQuery': null,
|
||
|
|
||
|
/**
|
||
|
* Render destination element
|
||
|
* @var {jQuery}
|
||
|
*/
|
||
|
'private _$dest': '',
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Initialize with jQuery instance
|
||
|
*
|
||
|
* @param {jQuery} jquery jQuery instance
|
||
|
*/
|
||
|
__construct: function( jquery )
|
||
|
{
|
||
|
this._jQuery = jquery;
|
||
|
this._$dest = this._createDestElement();
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _createDestElement': function()
|
||
|
{
|
||
|
return $( '<div>' )
|
||
|
.addClass( 'render' )
|
||
|
.text( 'test' );
|
||
|
},
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Run the provided test case
|
||
|
*
|
||
|
* @param {TestCase} test_case test case to be run
|
||
|
* @param {Object} options configuration options
|
||
|
*
|
||
|
* @return {TestRunner} self
|
||
|
*/
|
||
|
'public run': function( test_case, options )
|
||
|
{
|
||
|
if ( !( easejs.Class.isA( TestCase, test_case ) ) )
|
||
|
{
|
||
|
throw TypeError( "Invalid test case: " + test_case );
|
||
|
}
|
||
|
|
||
|
var _self = this;
|
||
|
|
||
|
// start test after the given delay
|
||
|
setTimeout( function()
|
||
|
{
|
||
|
_self._startInterval(
|
||
|
test_case,
|
||
|
TestRun( test_case, options ),
|
||
|
( parseFloat( options.interval ) * 1000 ),
|
||
|
( parseFloat( options.blank ) * 1000 )
|
||
|
);
|
||
|
}, ( parseFloat( options.delay ) * 1000 ) );
|
||
|
|
||
|
return this;
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _startInterval': function( test_case, run, interval, blank )
|
||
|
{
|
||
|
var _self = this,
|
||
|
render = function( noblank )
|
||
|
{
|
||
|
// blank if a blank period was provided as it was not
|
||
|
// suppressed
|
||
|
if ( blank && !noblank )
|
||
|
{
|
||
|
_self._blank();
|
||
|
|
||
|
setTimeout( function()
|
||
|
{
|
||
|
// render withour blank period
|
||
|
render( true );
|
||
|
}, blank );
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// continuously render so long as we have another element
|
||
|
if ( _self._renderNext( test_case, run ) !== null )
|
||
|
{
|
||
|
setTimeout( function()
|
||
|
{
|
||
|
render();
|
||
|
}, interval );
|
||
|
}
|
||
|
else _self._complete( run );
|
||
|
};
|
||
|
|
||
|
this._showDest();
|
||
|
|
||
|
// begin rendering; we will render the first element immediately and
|
||
|
// all subsequent elements will be subject to to the blank period
|
||
|
// and interval
|
||
|
render( true );
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _blank': function()
|
||
|
{
|
||
|
// clear dest element
|
||
|
this._$dest.html( '' );
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _renderNext': function( test_case, run )
|
||
|
{
|
||
|
var next;
|
||
|
|
||
|
// if there is no next element, then we have retrieved the requested
|
||
|
// number of samples
|
||
|
if ( ( next = run.getNextElement() ) !== null )
|
||
|
{
|
||
|
// render this element
|
||
|
test_case.render( next, this._$dest );
|
||
|
}
|
||
|
|
||
|
return next;
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _complete': function( run )
|
||
|
{
|
||
|
this._hideDest();
|
||
|
console.log( 'done' );
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _showDest': function()
|
||
|
{
|
||
|
$( 'body' ).append( this._$dest );
|
||
|
},
|
||
|
|
||
|
|
||
|
'private _hideDest': function()
|
||
|
{
|
||
|
this._$dest.detach();
|
||
|
this._blank();
|
||
|
}
|
||
|
} );
|
||
|
|
||
|
|
||
|
var ColorTestCase = easejs.Class
|
||
|
.implement( TestCase )
|
||
|
.extend(
|
||
|
{
|
||
|
'private static _sets': [
|
||
|
[ 'red', 'blue', 'green', 'yellow' ],
|
||
|
[ 'white', 'orange', 'black' ],
|
||
|
[ 'purple', 'brown', 'gray' ]
|
||
|
],
|
||
|
|
||
|
'public getSet': function( set_id )
|
||
|
{
|
||
|
return this.__self.$( '_sets' )[ 0 ];
|
||
|
},
|
||
|
|
||
|
'public render': function( id, $element )
|
||
|
{
|
||
|
$element.text( id );
|
||
|
}
|
||
|
} );
|
||
|
|
||
|
|
||
|
var rectest = {
|
||
|
cases: {
|
||
|
colors: {
|
||
|
title: 'Colors',
|
||
|
testCase: ColorTestCase,
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
} )();
|