Merge pull request #834 from prijutme4ty/fix_tests

Make tests more stable and independent
This commit is contained in:
Ilya Vorontsov 2015-03-01 11:56:46 +03:00
commit 3f553c10d7
3 changed files with 1007 additions and 1004 deletions

File diff suppressed because it is too large Load Diff

View File

@ -41,14 +41,12 @@ EVENTS:
*/ */
$(function(){ $(function(){
module('Widgets'); module('Widgets', {
beforeEach: function(assert) {
var ts = $.tablesorter, this.ts = $.tablesorter;
callback = {},
callbackName = 'init',
// filter widget table // filter widget table
$table = $('#testblock').html('<table class="tablesorter">' + this.$table = $('#testblock').html('<table class="tablesorter">' +
'<thead><tr>' + '<thead><tr>' +
'<th class="rank">Rank</th>' + '<th class="rank">Rank</th>' +
'<th class="first filter-match">First Name</th>' + '<th class="first filter-match">First Name</th>' +
@ -72,277 +70,13 @@ $(function(){
'<tr><td>100</td><td>Brenda Dexter</td><td>McMasters</td><td>18</td><td>$55.20</td><td>15%</td><td>Feb 12, 2010 7:23 PM</td><td>McMasters</td></tr>' + '<tr><td>100</td><td>Brenda Dexter</td><td>McMasters</td><td>18</td><td>$55.20</td><td>15%</td><td>Feb 12, 2010 7:23 PM</td><td>McMasters</td></tr>' +
'<tr><td>55</td><td>Dennis</td><td>Bronson</td><td>65</td><td>$123.00</td><td>32%</td><td>Jan 20, 2001 1:12 PM</td><td>Bronson</td></tr>' + '<tr><td>55</td><td>Dennis</td><td>Bronson</td><td>65</td><td>$123.00</td><td>32%</td><td>Jan 20, 2001 1:12 PM</td><td>Bronson</td></tr>' +
'<tr><td>9</td><td>Martha</td><td>delFuego</td><td>25</td><td>$22.09</td><td>17%</td><td>Jun 11, 2011 10:55 AM</td><td>delFuego</td></tr>' + '<tr><td>9</td><td>Martha</td><td>delFuego</td><td>25</td><td>$22.09</td><td>17%</td><td>Jun 11, 2011 10:55 AM</td><td>delFuego</td></tr>' +
'</tbody></table>').find('table'), '</tbody></table>').find('table');
table = $table[0], this.table = this.$table[0];
this.init = false;
/************************************************ var self = this;
Filter widget var initTablesort = function(){
************************************************/ self.$table.tablesorter({
init = false,
runFilterTests = function(){
var c = table.config,
wo = c.widgetOptions;
test( 'Filter: init', function() {
expect(6);
equal( init, true, 'Init event' );
equal( $table.hasClass('hasFilters'), true, '`hasFilters` class applied' );
equal( ts.filter.regex.child.test( c.cssChildRow ), true, 'child row regex check' );
equal( ts.filter.regex.filtered.test( wo.filter_filteredRow ), true, 'filtered row regex check' );
// this includes check of headers option & referencing column by class
equal ( c.$table.find('.tablesorter-filter').eq(0).hasClass('disabled'), true, 'filter disabled & headers class name working' );
tester.cacheCompare( table, 3, [ 12, 18, 13, 18 ], 'starting filter value on age column', true );
});
asyncTest( 'Filter searches', function() {
expect(27);
callbackName = 'regular';
callback.regular = function(){
tester.cacheCompare( table, 1, ['Peter', 'Bruce', 'Alex', 'Bruce Lee', 'Brenda Dexter', 'Dennis'], 'search regular', true );
};
ts.setFilters( table, ['', 'e'], true );
stop();
callbackName = 'fuzzy1';
callback.fuzzy1 = function(){
tester.cacheCompare( table, 1, ['Bruce Lee', 'Brenda Dexter'], 'search fuzzy', true );
};
ts.setFilters( table, ['', '~bee'], true );
stop();
callbackName = 'fuzzy2';
callback.fuzzy2 = function(){
tester.cacheCompare( table, 1, ['Philip Aaron Wong'], 'search fuzzy2', true );
};
ts.setFilters( table, ['', '~piano'], true );
stop();
callbackName = 'exact';
callback.exact = function(){
tester.cacheCompare( table, 1, ['John'], 'search exact', true );
};
ts.setFilters( table, ['', 'john='], true );
stop();
callbackName = 'wildcard1';
callback.wildcard1 = function(){
tester.cacheCompare( table, 2, ['Dumass', 'Evans'], 'search wildcard, one character (?)', true );
};
ts.setFilters( table, ['', '', 'a?s'], true );
stop();
callbackName = 'wildcard2';
callback.wildcard2 = function(){
tester.cacheCompare( table, 2, ['Dumass', 'Evans', 'McMasters'], 'search wildcard, multiple characters (*)', true );
};
ts.setFilters( table, ['', '', 'a*s'], true );
stop();
callbackName = 'regex';
callback.regex = function(){
tester.cacheCompare( table, 1, ['Peter', 'Brenda Dexter'], 'search regex', true );
};
ts.setFilters( table, ['', '/r$/'], true );
stop();
callbackName = 'operator';
callback.operator = function(){
tester.cacheCompare( table, 4, [42.29, 19.99, 15.89, 153.19, 14.19, 13.19, 55.2, 123, 22.09], 'search operator (>10)', true );
};
ts.setFilters( table, ['', '', '', '', '>10'], true );
stop();
callbackName = 'operator1';
callback.operator1 = function(){
tester.cacheCompare( table, 4, [153.19, 123], 'search operator (>100); ensure search filtered gets cleared', true );
};
ts.setFilters( table, ['', '', '', '', '>100'], true );
stop();
callbackName = 'operator2';
callback.operator2 = function(){
tester.cacheCompare( table, 5, [22, 20, 25, 44, 44, 32], 'search operator (>=)', true );
};
ts.setFilters( table, ['', '', '', '', '', '>=20'], true );
stop();
callbackName = 'operator3';
callback.operator3 = function(){
tester.cacheCompare( table, 5, [5, 4], 'search operator (<10)', true );
};
ts.setFilters( table, ['', '', '', '', '', '<10'], true );
stop();
callbackName = 'operator4';
callback.operator4 = function(){
tester.cacheCompare( table, 5, [22, 5, 18, 20, 25, 44, 44, 4, 14, 11, 15, 32, 17], 'search operator (<100); ensure search filtered gets cleared', true );
};
ts.setFilters( table, ['', '', '', '', '', '<100'], true );
stop();
callbackName = 'operator5';
callback.operator5 = function(){
tester.cacheCompare( table, 5, [5, 18, 20, 4, 14, 11, 15, 17], 'search operator (<=)', true );
};
ts.setFilters( table, ['', '', '', '', '', '<=20'], true );
stop();
callbackName = 'notMatch';
callback.notMatch = function(){
tester.cacheCompare( table, 1, ['Peter', 'John', 'Bruce', 'Jim', 'Bruce Lee', 'Dennis'], 'search not match', true );
};
ts.setFilters( table, ['', '!a'], true );
stop();
callbackName = 'notMatch2';
callback.notMatch2 = function(){
tester.cacheCompare( table, 1, ['Brandon Clark', 'Peter', 'John', 'Clark', 'Bruce', 'Alex', 'Jim', 'Bruce Lee', 'Brenda Dexter', 'Dennis', 'Martha'], 'search not match; ensure search filtered gets cleared', true );
};
ts.setFilters( table, ['', '!aa'], true );
stop();
callbackName = 'operatorAnd';
callback.operatorAnd = function(){
tester.cacheCompare( table, 1, ['Brandon Clark', 'Bruce', 'Bruce Lee'], 'search and match', true );
};
ts.setFilters( table, ['', 'br && c'], true );
stop();
callbackName = 'operatorAnd2';
callback.operatorAnd2 = function(){
tester.cacheCompare( table, 1, ['Brandon Clark'], 'search and match; ensure search filtered gets cleared', true );
};
ts.setFilters( table, ['', 'br && cl'], true );
stop();
callbackName = 'operatorOr';
callback.operatorOr = function(){
tester.cacheCompare( table, 1, ['Brandon Clark', 'Bruce', 'Alex', 'Bruce Lee', 'Brenda Dexter'], 'search OR match', true );
};
ts.setFilters( table, ['', 'alex|br*'], true );
stop();
callbackName = 'range';
callback.range = function(){
tester.cacheCompare( table, 4, [5.95, 9.99, 5.29], 'search range', true );
};
ts.setFilters( table, ['', '', '', '', '5 - 10'], true );
stop();
callbackName = 'range2';
callback.range2 = function(){
tester.cacheCompare( table, 4, [5.95, 42.29, 9.99, 19.99, 15.89, 5.29, 14.19, 13.19, 55.2, 22.09], 'search range; ensure search filtered gets cleared', true );
};
ts.setFilters( table, ['', '', '', '', '5 - 100'], true );
stop();
// test filter_startsWith (false by default)
wo.filter_startsWith = false;
callbackName = 'startsWith';
callback.startsWith = function(){
tester.cacheCompare( table, 1, ['Philip Aaron Wong', 'Aaron'], 'search - filter_startsWith : false', true );
};
ts.setFilters( table, ['', 'aa'], true );
stop();
// test filter_startsWith (false by default)
wo.filter_startsWith = true;
callbackName = 'startsWith2';
callback.startsWith2 = function(){
tester.cacheCompare( table, 1, ['Aaron'], 'search - filter_startsWith : true', true );
wo.filter_startsWith = false;
};
c.$table.trigger('search', false);
stop();
// test filter_ignoreCase (true by default)
wo.filter_ignoreCase = false;
callbackName = 'ignoreCase1';
callback.ignoreCase1 = function(){
tester.cacheCompare( table, 1, [], 'search - filter_ignoreCase : false', true );
wo.filter_ignoreCase = true;
};
c.$table.trigger('search', false);
stop();
// test filter-match class (added in the example code)
callbackName = 'filterMatch';
callback.filterMatch = function(){
tester.cacheCompare( table, 1, ['Brandon Clark', 'Clark', 'Bruce', 'Alex', 'Bruce Lee', 'Brenda Dexter'], 'search - filter-match', true );
};
ts.setFilters( table, ['', 'alex|br*|c'], true );
stop();
// test filter-match class
c.$table.find('.tablesorter-header').eq(1).removeClass('filter-match');
callbackName = 'notFilterMatch';
callback.notFilterMatch = function(){
tester.cacheCompare( table, 1, ['Bruce', 'Alex'], 'search - filter-match removed', true );
};
c.$table.trigger('search', false);
stop();
// filter reset
callbackName = 'filterReset';
callback.filterReset = function(){
tester.cacheCompare( table, 5, [22, 5, 18, 20, 25, 44, 44, 4, 14, 11, 15, 32, 17], 'filterReset', true );
};
c.$table.trigger('filterReset');
stop();
// filter parsed class
wo.filter_startsWith = false;
callbackName = 'filterParsed';
callback.filterParsed = function(){
tester.cacheCompare( table, 6, [ new Date('Oct 13, 2000 1:15 PM').getTime() ], 'search - filter-parsed', true );
};
ts.setFilters( table, ['', '', '', '', '', '', '< 1/1/2001'], true );
});
test( 'Filter: function & selectSource', function() {
expect(3);
var $t, opts = [];
$t = c.$table.find('.tablesorter-filter-row select:last');
equal ( $t.length !== 0, true, 'filter_functions: true working' );
c.$table.find('.tablesorter-filter-row select:first option').each(function(){
opts.push( $.trim( $(this).text() ) );
});
equal ( opts.length === 3 && opts.join('') === '< 10> 10', true, 'filter_functions set' );
opts = [];
$t.find('option').each(function(){
opts.push( $.trim( $(this).text() ) );
});
equal ( opts.length === 4 && opts.join('') === 'abcdefzyx', true, 'filter_selectSource set' );
});
$table.on('filterEnd', function(){
start();
if (callbackName !== '' && callback[callbackName]) {
callback[callbackName]();
}
callbackName = '';
});
};
$table
.on('filterInit', function(){
init = true;
runFilterTests();
})
.tablesorter({
ignoreCase: false, ignoreCase: false,
widgets: ['zebra', 'filter'], widgets: ['zebra', 'filter'],
headers: { headers: {
@ -365,5 +99,185 @@ $(function(){
} }
} }
}); });
};
var onEventCallback = function(){
self.init = true;
self.c = self.table.config,
self.wo = self.c.widgetOptions;
};
return QUnit.SequentialRunner().next(
QUnit.assertOnEvent(
self.$table,
'filterInit',
initTablesort,
onEventCallback
)
).promise();
},
afterEach: function(assert) {
var done = assert.async();
this.$table.trigger('destroy', [false, done]);
}
});
/************************************************
Filter widget
************************************************/
QUnit.test( 'Filter: init', function(assert) {
expect(6);
assert.equal( this.init, true, 'Init event' );
assert.equal( this.$table.hasClass('hasFilters'), true, '`hasFilters` class applied' );
assert.equal( this.ts.filter.regex.child.test( this.c.cssChildRow ), true, 'child row regex check' );
assert.equal( this.ts.filter.regex.filtered.test( this.wo.filter_filteredRow ), true, 'filtered row regex check' );
// this includes check of headers option & referencing column by class
assert.equal ( this.c.$table.find('.tablesorter-filter').eq(0).hasClass('disabled'), true, 'filter disabled & headers class name working' );
assert.cacheCompare( this.table, 3, [ 12, 18, 13, 18 ], 'starting filter value on age column', true );
});
QUnit.test( 'Filter searches', function(assert) {
var ts = this.ts,
c = this.c,
wo = this.wo,
$table = this.$table,
table = this.table;
expect(27);
return QUnit.SequentialRunner(
function(actions, assertions) {
return QUnit.assertOnEvent($table, 'filterEnd', actions, assertions);
}
).nextTask(
function(){ ts.setFilters( table, ['', 'e'], true ); },
function(){ assert.cacheCompare( table, 1, ['Peter', 'Bruce', 'Alex', 'Bruce Lee', 'Brenda Dexter', 'Dennis'], 'search regular', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '~bee'], true ); },
function(){ assert.cacheCompare( table, 1, ['Bruce Lee', 'Brenda Dexter'], 'search fuzzy', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '~piano'], true ); },
function(){ assert.cacheCompare( table, 1, ['Philip Aaron Wong'], 'search fuzzy2', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', 'john='], true ); },
function(){ assert.cacheCompare( table, 1, ['John'], 'search exact', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', 'a?s'], true ); },
function(){ assert.cacheCompare( table, 2, ['Dumass', 'Evans'], 'search wildcard, one character (?)', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', 'a*s'], true ); },
function(){ assert.cacheCompare( table, 2, ['Dumass', 'Evans', 'McMasters'], 'search wildcard, multiple characters (*)', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '/r$/'], true ); },
function(){ assert.cacheCompare( table, 1, ['Peter', 'Brenda Dexter'], 'search regex', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', '', '', '>10'], true ); },
function(){ assert.cacheCompare( table, 4, [42.29, 19.99, 15.89, 153.19, 14.19, 13.19, 55.2, 123, 22.09], 'search operator (>10)', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', '', '', '>100'], true ); },
function(){ assert.cacheCompare( table, 4, [153.19, 123], 'search operator (>100); ensure search filtered gets cleared', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', '', '', '', '>=20'], true ); },
function(){ assert.cacheCompare( table, 5, [22, 20, 25, 44, 44, 32], 'search operator (>=)', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', '', '', '', '<10'], true ); },
function(){ assert.cacheCompare( table, 5, [5, 4], 'search operator (<10)', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', '', '', '', '<100'], true ); },
function(){ assert.cacheCompare( table, 5, [22, 5, 18, 20, 25, 44, 44, 4, 14, 11, 15, 32, 17], 'search operator (<100); ensure search filtered gets cleared', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', '', '', '', '<=20'], true ); },
function(){ assert.cacheCompare( table, 5, [5, 18, 20, 4, 14, 11, 15, 17], 'search operator (<=)', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '!a'], true ); },
function(){ assert.cacheCompare( table, 1, ['Peter', 'John', 'Bruce', 'Jim', 'Bruce Lee', 'Dennis'], 'search not match', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '!aa'], true ); },
function(){ assert.cacheCompare( table, 1, ['Brandon Clark', 'Peter', 'John', 'Clark', 'Bruce', 'Alex', 'Jim', 'Bruce Lee', 'Brenda Dexter', 'Dennis', 'Martha'], 'search not match; ensure search filtered gets cleared', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', 'br && c'], true ); },
function(){ assert.cacheCompare( table, 1, ['Brandon Clark', 'Bruce', 'Bruce Lee'], 'search and match', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', 'br && cl'], true ); },
function(){ assert.cacheCompare( table, 1, ['Brandon Clark'], 'search and match; ensure search filtered gets cleared', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', 'alex|br*'], true ); },
function(){ assert.cacheCompare( table, 1, ['Brandon Clark', 'Bruce', 'Alex', 'Bruce Lee', 'Brenda Dexter'], 'search OR match', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', '', '', '5 - 10'], true ); },
function(){ assert.cacheCompare( table, 4, [5.95, 9.99, 5.29], 'search range', true ); }
).nextTask(
function(){ ts.setFilters( table, ['', '', '', '', '5 - 100'], true ); },
function(){ assert.cacheCompare( table, 4, [5.95, 42.29, 9.99, 19.99, 15.89, 5.29, 14.19, 13.19, 55.2, 22.09], 'search range; ensure search filtered gets cleared', true ); }
).nextTask( // test filter_startsWith (false by default)
function(){
wo.filter_startsWith = false;
ts.setFilters( table, ['', 'aa'], true );
},
function(){ assert.cacheCompare( table, 1, ['Philip Aaron Wong', 'Aaron'], 'search - filter_startsWith : false', true ); }
).nextTask( // test filter_startsWith (false by default)
function(){
wo.filter_startsWith = true;
c.$table.trigger('search', false);
},
function(){
assert.cacheCompare( table, 1, ['Aaron'], 'search - filter_startsWith : true', true );
wo.filter_startsWith = false;
}
).nextTask( // test filter_ignoreCase (true by default)
function(){
wo.filter_ignoreCase = false;
c.$table.trigger('search', false);
},
function(){
assert.cacheCompare( table, 1, [], 'search - filter_ignoreCase : false', true );
wo.filter_ignoreCase = true;
}
).nextTask( // test filter-match class (added in the example code)
function(){ ts.setFilters( table, ['', 'alex|br*|c'], true ); },
function(){ assert.cacheCompare( table, 1, ['Brandon Clark', 'Clark', 'Bruce', 'Alex', 'Bruce Lee', 'Brenda Dexter'], 'search - filter-match', true ); }
).nextTask( // test filter-match class
function(){
c.$table.find('.tablesorter-header').eq(1).removeClass('filter-match');
c.$table.trigger('search', false);
},
function(){ assert.cacheCompare( table, 1, ['Bruce', 'Alex'], 'search - filter-match removed', true ); }
).nextTask( // filter reset
function(){ c.$table.trigger('filterReset'); },
function(){ assert.cacheCompare( table, 5, [22, 5, 18, 20, 25, 44, 44, 4, 14, 11, 15, 32, 17], 'filterReset', true ); }
).nextTask( // filter parsed class
function(){
wo.filter_startsWith = false;
ts.setFilters( table, ['', '', '', '', '', '', '< 1/1/2001'], true );
},
function(){ assert.cacheCompare( table, 6, [ new Date('Oct 13, 2000 1:15 PM').getTime() ], 'search - filter-parsed', true ); }
).promise();
});
QUnit.test( 'Filter: function & selectSource', function(assert) {
expect(3);
var $t, opts = [];
$t = this.c.$table.find('.tablesorter-filter-row select:last');
assert.equal ( $t.length !== 0, true, 'filter_functions: true working' );
this.c.$table.find('.tablesorter-filter-row select:first option').each(function(){
opts.push( $.trim( $(this).text() ) );
});
assert.equal ( opts.length === 3 && opts.join('') === '< 10> 10', true, 'filter_functions set' );
opts = [];
$t.find('option').each(function(){
opts.push( $.trim( $(this).text() ) );
});
assert.equal ( opts.length === 4 && opts.join('') === 'abcdefzyx', true, 'filter_selectSource set' );
});
}); });

View File

@ -11,7 +11,7 @@
http://stackoverflow.com/q/13748129/145346 http://stackoverflow.com/q/13748129/145346
************************************************/ ************************************************/
QUnit.testSkip = function( testName, callback ) { QUnit.testSkip = function( testName, callback ) {
QUnit.test(testName + ' (SKIPPED)', function() { QUnit.test(testName + ' (SKIPPED)', function(assert) {
if (typeof callback === "function") { if (typeof callback === "function") {
callback(); callback();
} }
@ -22,8 +22,94 @@ QUnit.testSkip = function( testName, callback ) {
}); });
}; };
var tester = { // Accepts a function with a single argument -- deferred object, which should be resolved at some point in a function.
// Returns a promise, wrapping this function call.
QUnit.deferredCallback = function(func) {
return function(){
var defer = $.Deferred();
func(defer);
return defer.promise();
};
};
// SequentialRunner is an object to build and run a list of asynchronous calls in a sequential way.
// It wraps a deferred object; initially it's resolved, but .next and .nextTask calls add runners to be invoked.
// Underlying promise can be obtained by .promise() call.
// Each runner should accept deferred object and resolve it at some point when it's safe to invoke the next runner.
//
// Its constructor has an optional argument runnerCreator -- function which accepts task arguments
// and returns a runner (i.e. another function). If runnerCreator supplied, SequentialRunner object gets
// an additional method #nextTask(<task arguments>...) that is useful when you run lots of similar tasks.
//
// Example:
//
// QUnit.SequentialRunner(function(buttonSelector){
// return function(defer){ // each task is to wait until specified button is clicked
// $(buttonSelector).click(function(){
// defer.resolve()
// })
// };
// })
// .nextTask('#login').nextTask('#demo').nextTask('button')
// .promise()
// .then(function(){ console.log('Login, demo and any other button were clicked in that order.') });
//
QUnit.SequentialRunner = function(runnerCreator){
var result = {
defer: $.Deferred().resolve(),
promise: function(){
return this.defer.promise();
},
next: function(runner) {
this.defer = this.defer.then( QUnit.deferredCallback(runner) );
return this;
},
};
if (runnerCreator) {
result.nextTask = function(args) { // any argument list
var deferredRunner = QUnit.deferredCallback( runnerCreator.apply(this, arguments) );
this.defer = this.defer.then(deferredRunner);
return this;
};
}
return result;
};
// Returns an runner which runs some actions and wait for an event to be triggered.
// When an event is triggered assertions block is called and defer is resolved (independent on assertion result).
// This runner is useful when you want to check some conditions which should be met after an event was triggered.
//
// Example:
// QUnit.test('tablesorter initialization', function(assert){
// return QUnit.SequentialRunner()
// .next(
// QUnit.assertOnEvent(
// $('table'),
// 'tablesorter-initialized',
// function() {
// $('table').tablesorter( {sortList: [[0,0]]} );
// },
// function() {
// QUnit.assert.deepEqual($('table')[0].config.sortList, [[0,0]], 'sortList should be present in config');
// }
// )
// ).promise();
// });
//
QUnit.assertOnEvent = function($element, eventType, actions, assertions) {
return function(defer){
$element
.off(eventType)
.on(eventType, function() {
$element.off(eventType);
assertions();
defer && defer.resolve();
});
actions();
};
};
QUnit.extend(QUnit.assert, {
/************************************************ /************************************************
test table data cache test table data cache
************************************************/ ************************************************/
@ -50,10 +136,9 @@ var tester = {
} }
} }
} }
deepEqual( result, expected, 'testing parser cache: ' + txt); QUnit.assert.deepEqual( result, expected, 'testing parser cache: ' + txt);
} }
});
};
/* /*
Core plugin tested Core plugin tested
@ -164,11 +249,11 @@ $(function(){
/************************************************ /************************************************
Initialization Initialization
************************************************/ ************************************************/
test( "tablesorter loaded & initialized", function() { QUnit.test( "tablesorter loaded & initialized", function(assert) {
expect(3); assert.expect(3);
equal( typeof ts, 'object', "tablesorter loaded"); assert.equal( typeof ts, 'object', "tablesorter loaded");
equal( table1.hasInitialized, true, "tablesorter initialized flag"); assert.equal( table1.hasInitialized, true, "tablesorter initialized flag");
equal( init, true, "tablesorter initialized event"); assert.equal( init, true, "tablesorter initialized event");
}); });
c1 = table1.config; c1 = table1.config;
@ -180,24 +265,24 @@ $(function(){
Test column numbering Test column numbering
************************************************/ ************************************************/
// later: include a table header with colspan & rowspan // later: include a table header with colspan & rowspan
test( "column numbering", function() { QUnit.test( "column numbering", function(assert) {
expect(2); assert.expect(2);
var internalColumn = true, var internalColumn = true,
dataColumn = true; dataColumn = true;
$table4.find('thead th').each(function(i){ $table4.find('thead th').each(function(i){
internalColumn = internalColumn && this.column === i; internalColumn = internalColumn && this.column === i;
dataColumn = dataColumn && $(this).attr('data-column') == i; dataColumn = dataColumn && $(this).attr('data-column') == i;
}); });
equal( internalColumn, true, "Correct internal column numbering" ); assert.equal( internalColumn, true, "Correct internal column numbering" );
equal( dataColumn, true, "Correct data-column attribute numbering" ); assert.equal( dataColumn, true, "Correct data-column attribute numbering" );
}); });
/************************************************ /************************************************
check isDigit function check isDigit function
************************************************/ ************************************************/
var d = ts.isDigit; var d = ts.isDigit;
test( "isDigit", function() { QUnit.test( "isDigit", function(assert) {
expect(17); assert.expect(17);
ok( d('-1'), "allow negative (-1)"); ok( d('-1'), "allow negative (-1)");
ok( d('+1'), "allow plus (+1)"); ok( d('+1'), "allow plus (+1)");
ok( d('(1)'), "allow parenthesis (1)"); ok( d('(1)'), "allow parenthesis (1)");
@ -223,32 +308,32 @@ $(function(){
var ff = function(str) { var ff = function(str) {
return ts.formatFloat(str, table1); return ts.formatFloat(str, table1);
}; };
test( "formatFloat", function() { QUnit.test( "formatFloat", function(assert) {
expect(18); assert.expect(18);
strictEqual( ff(''), '', 'returns empty string' ); assert.strictEqual( ff(''), '', 'returns empty string' );
strictEqual( ff(5), 5, 'returns numerical values'); assert.strictEqual( ff(5), 5, 'returns numerical values');
c1.usNumberFormat = false; c1.usNumberFormat = false;
strictEqual( ts.formatFloat('1,234,567.89'), 1234567.89, 'use format float without including table - defaults to US number format'); assert.strictEqual( ts.formatFloat('1,234,567.89'), 1234567.89, 'use format float without including table - defaults to US number format');
strictEqual( ff('1 234,56'), 1234.56, 'parse non-U.S. (French) number format'); assert.strictEqual( ff('1 234,56'), 1234.56, 'parse non-U.S. (French) number format');
strictEqual( ff('1.234,56'), 1234.56, 'parse non-U.S. (German) number format'); assert.strictEqual( ff('1.234,56'), 1234.56, 'parse non-U.S. (German) number format');
strictEqual( ff('-32,32'), -32.32, 'negative non-U.S. signed numbers'); assert.strictEqual( ff('-32,32'), -32.32, 'negative non-U.S. signed numbers');
strictEqual( ff('-1.234,56'), -1234.56, 'negative non-U.S. signed numbers'); assert.strictEqual( ff('-1.234,56'), -1234.56, 'negative non-U.S. signed numbers');
strictEqual( ff('(32,32)'), -32.32, 'parenthesis wrapped non-U.S. negative number'); assert.strictEqual( ff('(32,32)'), -32.32, 'parenthesis wrapped non-U.S. negative number');
strictEqual( ff(' (32,32) '), -32.32, 'space + parenthesis wrapped non-U.S. negative number'); assert.strictEqual( ff(' (32,32) '), -32.32, 'space + parenthesis wrapped non-U.S. negative number');
c1.usNumberFormat = true; c1.usNumberFormat = true;
strictEqual( ff('1,234.56'), 1234.56, 'parse U.S. number format'); assert.strictEqual( ff('1,234.56'), 1234.56, 'parse U.S. number format');
strictEqual( ff('-32.32'), -32.32, 'negative U.S. signed numbers'); assert.strictEqual( ff('-32.32'), -32.32, 'negative U.S. signed numbers');
strictEqual( ff('(32.32)'), -32.32, 'parenthesis wrapped U.S. negative number'); assert.strictEqual( ff('(32.32)'), -32.32, 'parenthesis wrapped U.S. negative number');
strictEqual( ff(' (32.32)'), -32.32, 'space + parenthesis wrapped U.S. negative number'); assert.strictEqual( ff(' (32.32)'), -32.32, 'space + parenthesis wrapped U.S. negative number');
strictEqual( ff('fred'), 'fred', 'return string if not a number'); assert.strictEqual( ff('fred'), 'fred', 'return string if not a number');
strictEqual( ff(' fred '), 'fred', 'return trimmed string if not a number'); assert.strictEqual( ff(' fred '), 'fred', 'return trimmed string if not a number');
strictEqual( ff('fred 12'), 'fred 12', 'return string if number not at beginning'); assert.strictEqual( ff('fred 12'), 'fred 12', 'return string if number not at beginning');
strictEqual( ff('12fred'), 12, 'parse number + string into number only'); assert.strictEqual( ff('12fred'), 12, 'parse number + string into number only');
strictEqual( ff('(fred)'), '(fred)', 'leave parenthesis intact on strings'); assert.strictEqual( ff('(fred)'), '(fred)', 'leave parenthesis intact on strings');
}); });
@ -259,32 +344,33 @@ $(function(){
return ts.getData( c2.$headers[n], c2.headers[n], 'sorter' ); return ts.getData( c2.$headers[n], c2.headers[n], 'sorter' );
}; };
test( "getData", function() { QUnit.test( "getData", function(assert) {
expect(4); assert.expect(4);
var txt = [ 'jQuery data', 'meta data', 'headers option', 'header class name' ]; var txt = [ 'jQuery data', 'meta data', 'headers option', 'header class name' ];
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
equal( gd(i), 'false', txt[i]); // all columns have sorter false set assert.equal( gd(i), 'false', txt[i]); // all columns have sorter false set
} }
}); });
/************************************************ /************************************************
character equivalent replacement character equivalent replacement
************************************************/ ************************************************/
test( "replace accents", function() { QUnit.test( "replace accents", function(assert) {
expect(6); assert.expect(6);
strictEqual( ts.replaceAccents('\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5'), 'aaaaaaaAAAAAAA', "replaced a's"); assert.strictEqual( ts.replaceAccents('\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5'), 'aaaaaaaAAAAAAA', "replaced a's");
strictEqual( ts.replaceAccents('\u00e9\u00e8\u00ea\u00eb\u011b\u0119\u00c9\u00c8\u00ca\u00cb\u011a\u0118'), 'eeeeeeEEEEEE', "replaced e's"); assert.strictEqual( ts.replaceAccents('\u00e9\u00e8\u00ea\u00eb\u011b\u0119\u00c9\u00c8\u00ca\u00cb\u011a\u0118'), 'eeeeeeEEEEEE', "replaced e's");
strictEqual( ts.replaceAccents('\u00ed\u00ec\u0130\u00ee\u00ef\u0131\u00cd\u00cc\u0130\u00ce\u00cf'), 'iiiiiiIIiII', "replaced i's"); assert.strictEqual( ts.replaceAccents('\u00ed\u00ec\u0130\u00ee\u00ef\u0131\u00cd\u00cc\u0130\u00ce\u00cf'), 'iiiiiiIIiII', "replaced i's");
strictEqual( ts.replaceAccents('\u00f3\u00f2\u00f4\u00f5\u00f6\u00d3\u00d2\u00d4\u00d5\u00d6'), 'oooooOOOOO', "replaced o's"); assert.strictEqual( ts.replaceAccents('\u00f3\u00f2\u00f4\u00f5\u00f6\u00d3\u00d2\u00d4\u00d5\u00d6'), 'oooooOOOOO', "replaced o's");
strictEqual( ts.replaceAccents('\u00fa\u00f9\u00fb\u00fc\u016f\u00da\u00d9\u00db\u00dc\u016e'), 'uuuuuUUUUU', "replaced u's"); assert.strictEqual( ts.replaceAccents('\u00fa\u00f9\u00fb\u00fc\u016f\u00da\u00d9\u00db\u00dc\u016e'), 'uuuuuUUUUU', "replaced u's");
strictEqual( ts.replaceAccents('\u00e7\u0107\u010d\u00c7\u0106\u010c\u00df\u1e9e'), 'cccCCCssSS', "replaced c & s sharp"); assert.strictEqual( ts.replaceAccents('\u00e7\u0107\u010d\u00c7\u0106\u010c\u00df\u1e9e'), 'cccCCCssSS', "replaced c & s sharp");
}); });
/************************************************ /************************************************
detect parsers detect parsers
************************************************/ ************************************************/
asyncTest( "detect parsers", function() { QUnit.test( "detect parsers", function(assert) {
expect(2); var done = assert.async();
assert.expect(2);
$('#testblock2').html('<table class="tablesorter"><thead>' + $('#testblock2').html('<table class="tablesorter"><thead>' +
'<tr><th class="col-off" colspan="2">Info</th><th class="col-off" colspan="4">Details</th></tr>' + '<tr><th class="col-off" colspan="2">Info</th><th class="col-off" colspan="4">Details</th></tr>' +
'<tr>' + '<tr>' +
@ -310,7 +396,6 @@ $(function(){
3 : { sorter: 'digit' } // 3 sets the 4th column, not the 3rd header cell now 3 : { sorter: 'digit' } // 3 sets the 4th column, not the 3rd header cell now
}, },
initialized: function(table){ initialized: function(table){
start();
var i, var i,
result = true, result = true,
parsers = [ 'text', 'digit', 'digit', 'currency', 'percent', 'usLongDate' ], parsers = [ 'text', 'digit', 'digit', 'currency', 'percent', 'usLongDate' ],
@ -318,8 +403,7 @@ $(function(){
for (i = 0; i < c.columns; i++){ for (i = 0; i < c.columns; i++){
result = result && c.parsers[i].id === parsers[i]; result = result && c.parsers[i].id === parsers[i];
} }
equal( result, true, 'detect parsers by header index' ); assert.equal( result, true, 'detect parsers by header index' );
stop();
// table inception! // table inception!
$(table) $(table)
.trigger('destroy') .trigger('destroy')
@ -340,8 +424,8 @@ $(function(){
for (i = 0; i < c.columns; i++){ for (i = 0; i < c.columns; i++){
result = result && c.parsers[i].id === parsers[i]; result = result && c.parsers[i].id === parsers[i];
} }
equal( result, true, 'detect parsers by class/id' ); assert.equal( result, true, 'detect parsers by class/id' );
start(); done();
} }
}); });
} }
@ -378,7 +462,7 @@ $(function(){
sample3 = { sample3 = {
'shortDate' : { '2001/1/2': returnTime('1/2/2001'), '2001-1/2': returnTime('1/2/2001'), '2001,1.2': returnTime('1/2/2001') } 'shortDate' : { '2001/1/2': returnTime('1/2/2001'), '2001-1/2': returnTime('1/2/2001'), '2001,1.2': returnTime('1/2/2001') }
}, },
report = function(s) { report = function(assert, s) {
for (i = 0; i < p.length; i++) { for (i = 0; i < p.length; i++) {
t = p[i].id; t = p[i].id;
if (s.hasOwnProperty(t)) { if (s.hasOwnProperty(t)) {
@ -386,150 +470,149 @@ $(function(){
$.each(s[t], function(k,v){ $.each(s[t], function(k,v){
// check "is" and "format" functions // check "is" and "format" functions
if (p[i].is(k)) { if (p[i].is(k)) {
equal( p[i].format(k, table1, th0, 0), v, t + ' parser: "' + k + '" parsed to ' + v ); assert.equal( p[i].format(k, table1, th0, 0), v, t + ' parser: "' + k + '" parsed to ' + v );
} else { } else {
equal( p[i].format(k, table1, th0, 0), v, t + ' parser **NOT DETECTED**: "' + k + '", but returns ' + v ); assert.equal( p[i].format(k, table1, th0, 0), v, t + ' parser **NOT DETECTED**: "' + k + '", but returns ' + v );
} }
}); });
// test for undefined & null - probably overkill // test for undefined & null - probably overkill
strictEqual( p[i].format(undef, table1, th0, 0), undef, t + ' parser: will return undefined values properly' ); assert.strictEqual( p[i].format(undef, table1, th0, 0), undef, t + ' parser: will return undefined values properly' );
strictEqual( p[i].format(null, table1, th0, 0), null, t + ' parser: will return null values properly' ); assert.strictEqual( p[i].format(null, table1, th0, 0), null, t + ' parser: will return null values properly' );
} }
} }
}; };
test( "testing parsers", function() { QUnit.test( "testing parsers", function(assert) {
expect(parserTests); assert.expect(parserTests);
report(sample1); report(assert, sample1);
c1.sortLocaleCompare = true; c1.sortLocaleCompare = true;
c1.ignoreCase = false; c1.ignoreCase = false;
c1.usNumberFormat = false; c1.usNumberFormat = false;
th0.dateFormat = c1.dateFormat = "ddmmyyyy"; th0.dateFormat = c1.dateFormat = "ddmmyyyy";
report(sample2); report(assert, sample2);
c1.usNumberFormat = true; c1.usNumberFormat = true;
th0.dateFormat = c1.dateFormat = "yyyymmdd"; th0.dateFormat = c1.dateFormat = "yyyymmdd";
report(sample3); report(assert, sample3);
// undocumented sortValue // undocumented sortValue
equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'zzz', 'metadata parser found sortValue'); assert.equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'zzz', 'metadata parser found sortValue');
c1.parserMetadataName = 'poe'; c1.parserMetadataName = 'poe';
equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'nevermore', 'metadata parser found poe'); assert.equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'nevermore', 'metadata parser found poe');
}); });
test( "textExtraction Method", function() { QUnit.test( "textExtraction Method", function(assert) {
expect(4); assert.expect(4);
$table1.trigger('sorton', [[[ 0,0 ]]]); $table1.trigger('sorton', [[[ 0,0 ]]]);
tester.cacheCompare( table1, 0, [ 'test1', 'test2', 'test3', assert.cacheCompare( table1, 0, [ 'test1', 'test2', 'test3',
'testa', 'testb', 'testc' ], 'from data-attribute' ); 'testa', 'testb', 'testc' ], 'from data-attribute' );
$table3.trigger('sorton', [[[ 0,1 ]]]); $table3.trigger('sorton', [[[ 0,1 ]]]);
tester.cacheCompare( table3, 0, [ '', 'a255', 'a102', 'a87', 'a55', 'a43', 'a33', 'a10', 'a02', 'a1' ], 'ignore data-attribute' ); assert.cacheCompare( table3, 0, [ '', 'a255', 'a102', 'a87', 'a55', 'a43', 'a33', 'a10', 'a02', 'a1' ], 'ignore data-attribute' );
tester.cacheCompare( table4, 1, [ 'f11', 'f11', 'f12', 'f12', 'f12', 'f12', 'f12', 'f13', 'f13', 'f13' ], 'extract using class name' ); assert.cacheCompare( table4, 1, [ 'f11', 'f11', 'f12', 'f12', 'f12', 'f12', 'f12', 'f13', 'f13', 'f13' ], 'extract using class name' );
tester.cacheCompare( table4, 2, [ 'a21', 'a21', 'a23', 'a23', 'a23', 'a22', 'a22', 'a23', 'a24', 'a24' ], 'extract using column index' ); assert.cacheCompare( table4, 2, [ 'a21', 'a21', 'a23', 'a23', 'a23', 'a22', 'a22', 'a23', 'a24', 'a24' ], 'extract using column index' );
}); });
/************************************************ /************************************************
test parser cache test parser cache
************************************************/ ************************************************/
test( "parser cache; sorton methods; empty & string", function() { QUnit.test( "parser cache; sorton methods; empty & string", function(assert) {
expect(18); assert.expect(18);
$table1.trigger('sortReset'); $table1.trigger('sortReset');
// lower case because table was parsed before c1.ignoreCase was changed // lower case because table was parsed before c1.ignoreCase was changed
tester.cacheCompare( table1, 'all', [ 'test2', 'x2', 'test1', 'x3', 'test3', 'x1', assert.cacheCompare( table1, 'all', [ 'test2', 'x2', 'test1', 'x3', 'test3', 'x1',
'testb', 'x5', 'testc', 'x4', 'testa', 'x6' ], 'unsorted' ); 'testb', 'x5', 'testc', 'x4', 'testa', 'x6' ], 'unsorted' );
$table1.trigger('sorton', [[[ 0,0 ]]]); $table1.trigger('sorton', [[[ 0,0 ]]]);
tester.cacheCompare( table1, 'all', [ 'test1', 'x3', 'test2', 'x2', 'test3', 'x1', assert.cacheCompare( table1, 'all', [ 'test1', 'x3', 'test2', 'x2', 'test3', 'x1',
'testa', 'x6', 'testb', 'x5', 'testc', 'x4' ], 'ascending sort' ); 'testa', 'x6', 'testb', 'x5', 'testc', 'x4' ], 'ascending sort' );
$table1.trigger('sorton', [[[ 0,1 ]]]); $table1.trigger('sorton', [[[ 0,1 ]]]);
tester.cacheCompare( table1, 'all', [ 'test3', 'x1', 'test2', 'x2', 'test1', 'x3', assert.cacheCompare( table1, 'all', [ 'test3', 'x1', 'test2', 'x2', 'test1', 'x3',
'testc', 'x4', 'testb', 'x5', 'testa', 'x6' ], 'descending sort' ); 'testc', 'x4', 'testb', 'x5', 'testa', 'x6' ], 'descending sort' );
// empty cell position // empty cell position
$table3.trigger('sorton', [[[ 0,0 ]]]); $table3.trigger('sorton', [[[ 0,0 ]]]);
tester.cacheCompare( table3, 0, [ '', 'a1', 'a02', 'a10', 'a33', 'a43', 'a55', 'a87', 'a102', 'a255' ], 'asc sort; empty to top' ); assert.cacheCompare( table3, 0, [ '', 'a1', 'a02', 'a10', 'a33', 'a43', 'a55', 'a87', 'a102', 'a255' ], 'asc sort; empty to top' );
$table3.trigger('sorton', [[[ 0,1 ]]]); $table3.trigger('sorton', [[[ 0,1 ]]]);
tester.cacheCompare( table3, 0, [ '', 'a255', 'a102', 'a87', 'a55', 'a43', 'a33', 'a10', 'a02', 'a1' ], 'desc sort; empty to top' ); assert.cacheCompare( table3, 0, [ '', 'a255', 'a102', 'a87', 'a55', 'a43', 'a33', 'a10', 'a02', 'a1' ], 'desc sort; empty to top' );
// string position within number column // string position within number column
$table3.trigger('sorton', [[[ 1,0 ]]]); $table3.trigger('sorton', [[[ 1,0 ]]]);
tester.cacheCompare( table3, 1, [ -35, -5, -1, 1, 2, 4, 33, 44, 'nr', '' ], 'asc sort; empty to bottom; string to max' ); assert.cacheCompare( table3, 1, [ -35, -5, -1, 1, 2, 4, 33, 44, 'nr', '' ], 'asc sort; empty to bottom; string to max' );
$table3.trigger('sorton', [[[ 1,1 ]]]); $table3.trigger('sorton', [[[ 1,1 ]]]);
tester.cacheCompare( table3, 1, [ 'nr', 44, 33, 4, 2, 1, -1, -5, -35, '' ], 'desc sort; empty to bottom; string to max' ); assert.cacheCompare( table3, 1, [ 'nr', 44, 33, 4, 2, 1, -1, -5, -35, '' ], 'desc sort; empty to bottom; string to max' );
$table3.trigger('sorton', [[[ 2,0 ]]]); $table3.trigger('sorton', [[[ 2,0 ]]]);
tester.cacheCompare( table3, 2, [ 'nr', 'nr', 1, 2, 3, 4, 5, 6, 7, '' ], 'asc sort; empty to bottom; string to min' ); assert.cacheCompare( table3, 2, [ 'nr', 'nr', 1, 2, 3, 4, 5, 6, 7, '' ], 'asc sort; empty to bottom; string to min' );
$table3.trigger('sorton', [[[ 2,1 ]]]); $table3.trigger('sorton', [[[ 2,1 ]]]);
tester.cacheCompare( table3, 2, [ 7, 6, 5, 4, 3, 2, 1, 'nr', 'nr', '' ], 'desc sort; empty to bottom; string to min' ); assert.cacheCompare( table3, 2, [ 7, 6, 5, 4, 3, 2, 1, 'nr', 'nr', '' ], 'desc sort; empty to bottom; string to min' );
$table3.trigger('sorton', [[[ 3,0 ]]]); $table3.trigger('sorton', [[[ 3,0 ]]]);
tester.cacheCompare( table3, 3, [ 'n/a #2', 'n/a #1', -8.4, -2.2, -0.1, '', 5.2, 11.4, 23.6, 97.4 ], 'asc sort; empty to zero; string to top' ); assert.cacheCompare( table3, 3, [ 'n/a #2', 'n/a #1', -8.4, -2.2, -0.1, '', 5.2, 11.4, 23.6, 97.4 ], 'asc sort; empty to zero; string to top' );
$table3.trigger('sorton', [[[ 3,1 ]]]); $table3.trigger('sorton', [[[ 3,1 ]]]);
tester.cacheCompare( table3, 3, [ 'n/a #2', 'n/a #1', 97.4, 23.6, 11.4, 5.2, '', -0.1, -2.2, -8.4 ], 'desc sort; empty to zero; string to top' ); assert.cacheCompare( table3, 3, [ 'n/a #2', 'n/a #1', 97.4, 23.6, 11.4, 5.2, '', -0.1, -2.2, -8.4 ], 'desc sort; empty to zero; string to top' );
$table3.find('th:eq(3)').data('string', 'bottom'); $table3.find('th:eq(3)').data('string', 'bottom');
$table3.trigger('update'); $table3.trigger('update');
tester.cacheCompare( table3, 3, [ 97.4, 23.6, 11.4, 5.2, '', -0.1, -2.2, -8.4, 'n/a #1', 'n/a #2' ], 'desc sort; empty to zero; string to bottom' ); assert.cacheCompare( table3, 3, [ 97.4, 23.6, 11.4, 5.2, '', -0.1, -2.2, -8.4, 'n/a #1', 'n/a #2' ], 'desc sort; empty to zero; string to bottom' );
$table3.trigger('sorton', [[[ 3,0 ]]]); $table3.trigger('sorton', [[[ 3,0 ]]]);
tester.cacheCompare( table3, 3, [ -8.4, -2.2, -0.1, '', 5.2, 11.4, 23.6, 97.4, 'n/a #1', 'n/a #2' ], 'asc sort; empty to zero; string to bottom' ); assert.cacheCompare( table3, 3, [ -8.4, -2.2, -0.1, '', 5.2, 11.4, 23.6, 97.4, 'n/a #1', 'n/a #2' ], 'asc sort; empty to zero; string to bottom' );
$table3.find('th:eq(3)').data('string', 'none'); $table3.find('th:eq(3)').data('string', 'none');
c3.headers[3].empty = "bottom"; c3.headers[3].empty = "bottom";
c3.sortList = [[ 3, 1 ]]; // added to test sortList c3.sortList = [[ 3, 1 ]]; // added to test sortList
$table3.trigger('update'); $table3.trigger('update');
tester.cacheCompare( table3, 3, [ 97.4, 23.6, 11.4, 5.2, 'n/a #1', 'n/a #2', -0.1, -2.2, -8.4, '' ], 'desc sort; empty to zero; string to none/zero' ); assert.cacheCompare( table3, 3, [ 97.4, 23.6, 11.4, 5.2, 'n/a #1', 'n/a #2', -0.1, -2.2, -8.4, '' ], 'desc sort; empty to zero; string to none/zero' );
$table3.trigger('sorton', [[[ 3,0 ]]]); $table3.trigger('sorton', [[[ 3,0 ]]]);
tester.cacheCompare( table3, 3, [ -8.4, -2.2, -0.1, 'n/a #1', 'n/a #2', 5.2, 11.4, 23.6, 97.4, '' ], 'asc sort; empty to zero; string to none/zero' ); assert.cacheCompare( table3, 3, [ -8.4, -2.2, -0.1, 'n/a #1', 'n/a #2', 5.2, 11.4, 23.6, 97.4, '' ], 'asc sort; empty to zero; string to none/zero' );
t = [ 'x', 'X', 'y', 'Y', 'z', 'Z', 'a', 'A', 'b', 'B', 'c', 'C' ]; t = [ 'x', 'X', 'y', 'Y', 'z', 'Z', 'a', 'A', 'b', 'B', 'c', 'C' ];
deepEqual( t.sort($.tablesorter.sortText), [ 'A', 'B', 'C', 'X', 'Y', 'Z', 'a', 'b', 'c', 'x', 'y', 'z' ], 'test sortText function directly' ); assert.deepEqual( t.sort($.tablesorter.sortText), [ 'A', 'B', 'C', 'X', 'Y', 'Z', 'a', 'b', 'c', 'x', 'y', 'z' ], 'test sortText function directly' );
t = [ 'a02', 'a10', 'a43', 'a255', 'a102', 'a33', '', 'a1', 'a55', 'a87' ]; t = [ 'a02', 'a10', 'a43', 'a255', 'a102', 'a33', '', 'a1', 'a55', 'a87' ];
deepEqual( t.sort($.tablesorter.sortNatural), [ '', 'a1', 'a02', 'a10', 'a33', 'a43', 'a55', 'a87', 'a102', 'a255' ], 'test sortNatural function directly' ); assert.deepEqual( t.sort($.tablesorter.sortNatural), [ '', 'a1', 'a02', 'a10', 'a33', 'a43', 'a55', 'a87', 'a102', 'a255' ], 'test sortNatural function directly' );
tester.cacheCompare( table4, 6, [ '', '', '', '', '', '', '', '', '', '' ], 'parser-false does not extract text' ); assert.cacheCompare( table4, 6, [ '', '', '', '', '', '', '', '', '', '' ], 'parser-false does not extract text' );
}); });
test( "sorton methods", function(){ QUnit.test( "sorton methods", function(assert) {
expect(6); assert.expect(6);
$table3.trigger('sorton', [[[ 0,'d' ]]]); $table3.trigger('sorton', [[[ 0,'d' ]]]);
equal( c3.sortList + '', '0,1', 'sorton desc [0,"d"]' ); assert.equal( c3.sortList + '', '0,1', 'sorton desc [0,"d"]' );
$table3.trigger('sorton', [[[ 0,'a' ]]]); $table3.trigger('sorton', [[[ 0,'a' ]]]);
equal( c3.sortList + '', '0,0', 'sorton asc [0,"a"]' ); assert.equal( c3.sortList + '', '0,0', 'sorton asc [0,"a"]' );
$table3.trigger('sorton', [[[ 0,'n' ]]]); $table3.trigger('sorton', [[[ 0,'n' ]]]);
equal( c3.sortList + '', '0,1', 'sorton next [0,"n"]' ); assert.equal( c3.sortList + '', '0,1', 'sorton next [0,"n"]' );
$table3.trigger('sorton', [[[ 0,'n' ]]]); $table3.trigger('sorton', [[[ 0,'n' ]]]);
equal( c3.sortList + '', '0,0', 'sorton next [0,"n"]' ); assert.equal( c3.sortList + '', '0,0', 'sorton next [0,"n"]' );
$table3.trigger('sorton', [[ [ 0,'n'], [1,'o'], [2,'s'] ]]); $table3.trigger('sorton', [[ [ 0,'n'], [1,'o'], [2,'s'] ]]);
equal( c3.sortList + '', '0,1,1,0,2,1', 'sorton next/opposite/same [0,"n"],[1,"o"],[2,"s"]' ); assert.equal( c3.sortList + '', '0,1,1,0,2,1', 'sorton next/opposite/same [0,"n"],[1,"o"],[2,"s"]' );
$table3.trigger('sorton', [[ [ 0,'n'], [1,'o'], [2,'s'] ]]); $table3.trigger('sorton', [[ [ 0,'n'], [1,'o'], [2,'s'] ]]);
equal( c3.sortList + '', '0,0,1,1,2,0', 'sorton next/opposite/same [0,"n"],[1,"o"],[2,"s"]' ); assert.equal( c3.sortList + '', '0,0,1,1,2,0', 'sorton next/opposite/same [0,"n"],[1,"o"],[2,"s"]' );
}); });
test( "sort Events", function(){ QUnit.test( "sort Events", function(assert) {
expect(1); assert.expect(1);
$table1.add($table5).bind( events.join('.testing '), function(e){ $table1.add($table5).bind( events.join('.testing '), function(e){
if (e.type === events[sortIndx%3]) { if (e.type === events[sortIndx%3]) {
@ -546,14 +629,14 @@ $(function(){
$table1.add($table5).unbind( events.join('.testing ') ); $table1.add($table5).unbind( events.join('.testing ') );
// table1 sorted twice in the above test; sortIndx = 9 then empty table5 x1 (total = 3 events x 3) // table1 sorted twice in the above test; sortIndx = 9 then empty table5 x1 (total = 3 events x 3)
equal( sortIndx, 9, 'sortStart, sortBegin & sortEnd fired in order x2; including empty table' ); assert.equal( sortIndx, 9, 'sortStart, sortBegin & sortEnd fired in order x2; including empty table' );
}); });
/************************************************ /************************************************
test update methods test update methods
************************************************/ ************************************************/
test( "parser cache; update methods & callbacks", function() { QUnit.test( "parser cache; update methods & callbacks", function(assert) {
expect(10); assert.expect(10);
var oldColMax; var oldColMax;
c1.ignoreCase = true; c1.ignoreCase = true;
// updateAll // updateAll
@ -572,8 +655,8 @@ $(function(){
hd = c1.$headers[1] === nw, hd = c1.$headers[1] === nw,
hl = c1.headerList[1] === nw, hl = c1.headerList[1] === nw,
p1 = c1.parsers[1].id === 'digit'; p1 = c1.parsers[1].id === 'digit';
equal(hc && hd && hl && p1, true, 'testing header cache: updateAll - thead'); assert.equal(hc && hd && hl && p1, true, 'testing header cache: updateAll - thead');
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, assert.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3,
'testc', 4, 'testb', 5, 'testa', 6 ], 'updateAll - tbody' ); 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateAll - tbody' );
}]); }]);
@ -583,8 +666,8 @@ $(function(){
oldColMax = c1.cache[1].colMax[1]; oldColMax = c1.cache[1].colMax[1];
$table1.trigger('addRows', [t, true, function(){ $table1.trigger('addRows', [t, true, function(){
updateCallback++; updateCallback++;
equal( oldColMax === 6 && c1.cache[1].colMax[1] === 7, true, 'addRows includes updating colMax value'); assert.equal( oldColMax === 6 && c1.cache[1].colMax[1] === 7, true, 'addRows includes updating colMax value');
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, assert.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3,
'testd', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'addRows method' ); 'testd', 7, 'testc', 4, 'testb', 5, 'testa', 6 ], 'addRows method' );
}]); }]);
@ -594,8 +677,8 @@ $(function(){
oldColMax = c1.cache[1].colMax[1]; oldColMax = c1.cache[1].colMax[1];
$table1.trigger('updateCell', [t[0], true, function(){ $table1.trigger('updateCell', [t[0], true, function(){
updateCallback++; updateCallback++;
equal( oldColMax === 7 && c1.cache[1].colMax[1] === 8, true, 'updateCell includes updating colMax value'); assert.equal( oldColMax === 7 && c1.cache[1].colMax[1] === 8, true, 'updateCell includes updating colMax value');
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, assert.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3,
'testd', -8, 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateCell method' ); 'testd', -8, 'testc', 4, 'testb', 5, 'testa', 6 ], 'updateCell method' );
}]); }]);
@ -604,8 +687,8 @@ $(function(){
oldColMax = c1.cache[1].colMax[1]; oldColMax = c1.cache[1].colMax[1];
$table1.trigger('update', [true, function(){ $table1.trigger('update', [true, function(){
updateCallback++; updateCallback++;
equal( oldColMax === 8 && c1.cache[1].colMax[1] === 6, true, 'update includes updating colMax value'); assert.equal( oldColMax === 8 && c1.cache[1].colMax[1] === 6, true, 'update includes updating colMax value');
tester.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3, assert.cacheCompare( table1, 'all', [ 'test3', 1, 'test2', 2, 'test1', 3,
'testc', 4, 'testb', 5, 'testa', 6 ], 'update method' ); 'testc', 4, 'testb', 5, 'testa', 6 ], 'update method' );
}]); }]);
@ -613,62 +696,64 @@ $(function(){
.bind('updateComplete.testing', function(){ updateIndx++; }) .bind('updateComplete.testing', function(){ updateIndx++; })
.trigger('update', [true, function(){ .trigger('update', [true, function(){
updateCallback++; updateCallback++;
tester.cacheCompare( table5, 'all', [], 'update method on empty table' ); assert.cacheCompare( table5, 'all', [], 'update method on empty table' );
}]); }]);
$table1.add($table5).unbind('updateComplete.testing'); $table1.add($table5).unbind('updateComplete.testing');
// table1 updated 4x in the above test // table1 updated 4x in the above test
// table5 updated 1x // table5 updated 1x
equal( updateIndx, updateCallback, 'updatedComplete and update callback functions working properly' ); assert.equal( updateIndx, updateCallback, 'updatedComplete and update callback functions working properly' );
}); });
/************************************************ /************************************************
test sortForce, sortAppend, sortMultiSortKey and sortResetKey options test sortForce, sortAppend, sortMultiSortKey and sortResetKey options
************************************************/ ************************************************/
asyncTest( "sortForce, sortAppend, sortMultiSortKey & sortResetKey; and numberSorter option", function(){ QUnit.test( "sortForce, sortAppend, sortMultiSortKey & sortResetKey; and numberSorter option", function(assert){
expect(3); assert.expect(3);
var count = 0;
tester.cacheCompare( table4, 3, [ 2, 1, 7, 6, 5, 3, 4, 8, 9, 10 ], 'force x2 + sorted x2 + append x2, ascending' ); assert.cacheCompare( table4, 3, [ 2, 1, 7, 6, 5, 3, 4, 8, 9, 10 ], 'force x2 + sorted x2 + append x2, ascending' );
$table4.on('sortEnd', function(){
count++; return QUnit.SequentialRunner(
if (count === 1) { function(actions, assertions){
tester.cacheCompare( table4, 3, [ 2, 1, 6, 7, 5, 4, 3, 8, 10, 9 ], 'force x2 + sorted x2 + append x2, descending' ); return QUnit.assertOnEvent($table4, 'sortEnd', actions, assertions);
c4.sortResetKey = 'shiftKey';
var e = $.Event('sort');
e.which = 1;
e.shiftKey = true; // testing sortResetKey
c4.$headers.eq(0).trigger(e);
} else {
tester.cacheCompare( table4, 3, [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], 'sortResetKey' );
$table4.off('sortEnd');
// start();
} }
}); ).nextTask(
var e = $.Event('sort'); function(){
c4.sortMultiSortKey = 'altKey'; c4.sortMultiSortKey = 'altKey';
e.which = 1; c4.$headers.eq(5).trigger( $.Event('sort', { which: 1, altKey: true }) );
e.altKey = true; // testing sortMultiSortKey },
c4.$headers.eq(5).trigger(e); function(){
assert.cacheCompare( table4, 3, [ 2, 1, 6, 7, 5, 4, 3, 8, 10, 9 ], 'force x2 + sorted x2 + append x2, descending' );
}
).nextTask(
function() {
c4.sortResetKey = 'shiftKey';
c4.$headers.eq(0).trigger( $.Event('sort', {which: 1, shiftKey: true}) );
},
function() {
assert.cacheCompare( table4, 3, [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], 'sortResetKey' );
}
).promise();
}); });
/************************************************ /************************************************
check header css check header css
************************************************/ ************************************************/
test( "testing header css & sortReset method", function(){ QUnit.test( "testing header css & sortReset method", function(assert) {
expect(7); assert.expect(7);
t = $(th0); t = $(th0);
equal( $table1.hasClass(ts.css.table), true, 'table class applied'); assert.equal( $table1.hasClass(ts.css.table), true, 'table class applied');
equal( t.hasClass(ts.css.header), true, 'Header class present' ); assert.equal( t.hasClass(ts.css.header), true, 'Header class present' );
equal( t.parent().hasClass(ts.css.headerRow), true, 'Header row class present' ); assert.equal( t.parent().hasClass(ts.css.headerRow), true, 'Header row class present' );
equal( $table1.find('tbody:eq(1)').hasClass(c1.cssInfoBlock), true, 'Tbody info block class present' ); assert.equal( $table1.find('tbody:eq(1)').hasClass(c1.cssInfoBlock), true, 'Tbody info block class present' );
$table1.trigger('sorton', [[[ 0,1 ]]] ); $table1.trigger('sorton', [[[ 0,1 ]]] );
equal( t.hasClass(ts.css.sortDesc), true, 'Descending class present' ); assert.equal( t.hasClass(ts.css.sortDesc), true, 'Descending class present' );
$table1.trigger('sorton', [[[ 0,0 ]]] ); $table1.trigger('sorton', [[[ 0,0 ]]] );
equal( t.hasClass(ts.css.sortAsc), true, 'Ascending class present' ); assert.equal( t.hasClass(ts.css.sortAsc), true, 'Ascending class present' );
$table1.trigger('sortReset'); $table1.trigger('sortReset');
equal( t.hasClass(ts.css.sortAsc) || t.hasClass(ts.css.sortDesc), false, 'Testing sortReset' ); assert.equal( t.hasClass(ts.css.sortAsc) || t.hasClass(ts.css.sortDesc), false, 'Testing sortReset' );
}); });
/************************************************ /************************************************
@ -683,34 +768,34 @@ $(function(){
return t; return t;
}; };
test( "apply zebra widget", function(){ QUnit.test( "apply zebra widget", function(assert) {
expect(3); assert.expect(3);
equal( zebra(), false, 'zebra not applied' ); assert.equal( zebra(), false, 'zebra not applied' );
c2.widgets = [ 'zebra' ]; c2.widgets = [ 'zebra' ];
$table2.trigger('applyWidgets'); $table2.trigger('applyWidgets');
equal( zebra(), true, 'zebra is applied' ); assert.equal( zebra(), true, 'zebra is applied' );
$table2 $table2
.append('<tr><td>s</td><td>t</td><td>u</td><td>v</td></tr>') .append('<tr><td>s</td><td>t</td><td>u</td><td>v</td></tr>')
.trigger('update'); .trigger('update');
equal( zebra(), true, 'zebra is applied after update' ); assert.equal( zebra(), true, 'zebra is applied after update' );
}); });
/************************************************ /************************************************
check destroy method check destroy method
************************************************/ ************************************************/
test("testing destroy method", function(){ QUnit.test("testing destroy method", function(assert) {
$table2.trigger('sorton', [[[ 0,1 ]]] ); $table2.trigger('sorton', [[[ 0,1 ]]] );
$table2.trigger('destroy'); $table2.trigger('destroy');
expect(7); assert.expect(7);
t = $table2.find('th:first'); t = $table2.find('th:first');
e = jQuery._data(table2, 'events'); // get a list of all bound events e = jQuery._data(table2, 'events'); // get a list of all bound events
equal( $.isEmptyObject(e), true, 'no events applied' ); assert.equal( $.isEmptyObject(e), true, 'no events applied' );
equal( $table2.data().hasOwnProperty('tablesorter'), false, 'Data removed' ); assert.equal( $table2.data().hasOwnProperty('tablesorter'), false, 'Data removed' );
equal( $table2.attr('class'), 'tester', 'All table classes removed' ); assert.equal( $table2.attr('class'), 'tester', 'All table classes removed' );
equal( $table2.find('tr:first').attr('class'), '', 'Header row class removed' ); assert.equal( $table2.find('tr:first').attr('class'), '', 'Header row class removed' );
equal( t.attr('class').match('tablesorter'), null, 'Header classes removed' ); assert.equal( t.attr('class').match('tablesorter'), null, 'Header classes removed' );
equal( t.children().length, 0, 'Inner wrapper removed' ); assert.equal( t.children().length, 0, 'Inner wrapper removed' );
equal( typeof (t.data().column) , 'undefined', 'data-column removed'); assert.equal( typeof (t.data().column) , 'undefined', 'data-column removed');
$table2.tablesorter(); $table2.tablesorter();
}); });