rectest/scripts/main.js

377 lines
9.2 KiB
JavaScript
Raw Normal View History

( 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,
}
}
};
} )();