485 lines
16 KiB
HTML
485 lines
16 KiB
HTML
|
<!doctype html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<title>Underscore Test Suite</title>
|
||
|
<link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css">
|
||
|
</head>
|
||
|
<body>
|
||
|
<div id="qunit"></div>
|
||
|
<script>
|
||
|
// Avoid reporting tests to Sauce Labs when script errors occur.
|
||
|
if (location.port == '9001') {
|
||
|
window.onerror = function(message) {
|
||
|
if (window.QUnit) {
|
||
|
QUnit.config.done.length = 0;
|
||
|
}
|
||
|
global_test_results = { 'message': message };
|
||
|
};
|
||
|
}
|
||
|
</script>
|
||
|
<script src="../node_modules/qunitjs/qunit/qunit.js"></script>
|
||
|
<script src="../node_modules/qunit-extras/qunit-extras.js"></script>
|
||
|
<script src="../node_modules/jquery/dist/jquery.js"></script>
|
||
|
<script src="../node_modules/platform/platform.js"></script>
|
||
|
<script src="./asset/test-ui.js"></script>
|
||
|
<script src="../lodash.js"></script>
|
||
|
<script>
|
||
|
QUnit.config.asyncRetries = 10;
|
||
|
QUnit.config.hidepassed = true;
|
||
|
QUnit.config.excused = {
|
||
|
'Arrays': {
|
||
|
'chunk': [
|
||
|
'defaults to empty array (chunk size 0)'
|
||
|
],
|
||
|
'difference': [
|
||
|
'can perform an OO-style difference'
|
||
|
],
|
||
|
'drop': [
|
||
|
'is an alias for rest'
|
||
|
],
|
||
|
'first': [
|
||
|
'returns an empty array when n <= 0 (0 case)',
|
||
|
'returns an empty array when n <= 0 (negative case)',
|
||
|
'can fetch the first n elements',
|
||
|
'returns the whole array if n > length'
|
||
|
],
|
||
|
'findIndex': [
|
||
|
'called with context'
|
||
|
],
|
||
|
'findLastIndex': [
|
||
|
'called with context'
|
||
|
],
|
||
|
'flatten': [
|
||
|
'supports empty arrays',
|
||
|
'can flatten nested arrays',
|
||
|
'works on an arguments object',
|
||
|
'can handle very deep arrays'
|
||
|
],
|
||
|
'head': [
|
||
|
'is an alias for first'
|
||
|
],
|
||
|
'indexOf': [
|
||
|
"sorted indexOf doesn't uses binary search",
|
||
|
'0'
|
||
|
],
|
||
|
'initial': [
|
||
|
'returns all but the last n elements',
|
||
|
'returns an empty array when n > length',
|
||
|
'works on an arguments object'
|
||
|
],
|
||
|
'intersection': [
|
||
|
'can perform an OO-style intersection'
|
||
|
],
|
||
|
'last': [
|
||
|
'returns an empty array when n <= 0 (0 case)',
|
||
|
'returns an empty array when n <= 0 (negative case)',
|
||
|
'can fetch the last n elements',
|
||
|
'returns the whole array if n > length'
|
||
|
],
|
||
|
'lastIndexOf': [
|
||
|
'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`',
|
||
|
'should treat non-number `fromIndex` values as `array.length`',
|
||
|
'[0,-1,-1]'
|
||
|
],
|
||
|
'object': [
|
||
|
'an array of pairs zipped together into an object',
|
||
|
'an object converted to pairs and back to an object'
|
||
|
],
|
||
|
'range': [
|
||
|
'range with two arguments a & b, b<a generates an empty array'
|
||
|
],
|
||
|
'rest': [
|
||
|
'returns the whole array when index is 0',
|
||
|
'returns elements starting at the given index',
|
||
|
'works on an arguments object'
|
||
|
],
|
||
|
'sortedIndex': [
|
||
|
'2',
|
||
|
'3'
|
||
|
],
|
||
|
'tail': [
|
||
|
'is an alias for rest'
|
||
|
],
|
||
|
'take': [
|
||
|
'is an alias for first'
|
||
|
],
|
||
|
'uniq': [
|
||
|
'uses the result of `iterator` for uniqueness comparisons (unsorted case)',
|
||
|
'`sorted` argument defaults to false when omitted',
|
||
|
'when `iterator` is a string, uses that key for comparisons (unsorted case)',
|
||
|
'uses the result of `iterator` for uniqueness comparisons (sorted case)',
|
||
|
'when `iterator` is a string, uses that key for comparisons (sorted case)',
|
||
|
'can use falsey pluck like iterator'
|
||
|
],
|
||
|
'union': [
|
||
|
'can perform an OO-style union'
|
||
|
]
|
||
|
},
|
||
|
'Chaining': {
|
||
|
'pop': true,
|
||
|
'shift': true,
|
||
|
'splice': true,
|
||
|
'reverse/concat/unshift/pop/map': [
|
||
|
'can chain together array functions.'
|
||
|
]
|
||
|
},
|
||
|
'Collections': {
|
||
|
'lookupIterator with contexts': true,
|
||
|
'Iterating objects with sketchy length properties': true,
|
||
|
'Resistant to collection length and properties changing while iterating': true,
|
||
|
'countBy': [
|
||
|
'true'
|
||
|
],
|
||
|
'each': [
|
||
|
'context object property accessed'
|
||
|
],
|
||
|
'every': [
|
||
|
'Can be called with object',
|
||
|
'Died on test #15',
|
||
|
'context works'
|
||
|
],
|
||
|
'filter': [
|
||
|
'given context',
|
||
|
'[{"a":1,"b":2},{"a":1,"b":3},{"a":1,"b":4}]',
|
||
|
'[{"a":1,"b":2},{"a":2,"b":2}]',
|
||
|
'Empty object accepts all items',
|
||
|
'OO-filter'
|
||
|
],
|
||
|
'find': [
|
||
|
'{"a":1,"b":4}',
|
||
|
'undefined when not found',
|
||
|
'undefined when searching empty list',
|
||
|
'works on objects',
|
||
|
'undefined',
|
||
|
'called with context'
|
||
|
],
|
||
|
'findWhere': [
|
||
|
'checks properties given function'
|
||
|
],
|
||
|
'groupBy': [
|
||
|
'true'
|
||
|
],
|
||
|
'includes': [
|
||
|
"doesn't delegate to binary search"
|
||
|
],
|
||
|
'invoke': [
|
||
|
'handles null & undefined'
|
||
|
],
|
||
|
'map': [
|
||
|
'tripled numbers with context',
|
||
|
'OO-style doubled numbers'
|
||
|
],
|
||
|
'max': [
|
||
|
'can handle null/undefined',
|
||
|
'can perform a computation-based max',
|
||
|
'Maximum value of an empty object',
|
||
|
'Maximum value of an empty array',
|
||
|
'Maximum value of a non-numeric collection',
|
||
|
'Finds correct max in array starting with num and containing a NaN',
|
||
|
'Finds correct max in array starting with NaN',
|
||
|
'Respects iterator return value of -Infinity',
|
||
|
'String keys use property iterator',
|
||
|
'Iterator context',
|
||
|
'Lookup falsy iterator'
|
||
|
],
|
||
|
'min': [
|
||
|
'can handle null/undefined',
|
||
|
'can perform a computation-based min',
|
||
|
'Minimum value of an empty object',
|
||
|
'Minimum value of an empty array',
|
||
|
'Minimum value of a non-numeric collection',
|
||
|
'Finds correct min in array starting with NaN',
|
||
|
'Respects iterator return value of Infinity',
|
||
|
'String keys use property iterator',
|
||
|
'Iterator context',
|
||
|
'Lookup falsy iterator'
|
||
|
],
|
||
|
'partition': [
|
||
|
'can reference the array index',
|
||
|
'Died on test #8',
|
||
|
'partition takes a context argument',
|
||
|
'function(a){[code]}'
|
||
|
],
|
||
|
'pluck': [
|
||
|
'[1]'
|
||
|
],
|
||
|
'reduce': [
|
||
|
'can reduce with a context object'
|
||
|
],
|
||
|
'reject': [
|
||
|
'Returns empty list given empty array'
|
||
|
],
|
||
|
'sample': [
|
||
|
'behaves correctly on negative n',
|
||
|
'Died on test #3'
|
||
|
],
|
||
|
'some': [
|
||
|
'Can be called with object',
|
||
|
'Died on test #17',
|
||
|
'context works'
|
||
|
],
|
||
|
'where': [
|
||
|
'checks properties given function'
|
||
|
],
|
||
|
'Can use various collection methods on NodeLists': [
|
||
|
'<span id="id2"></span>',
|
||
|
'<span id="id1"></span>'
|
||
|
]
|
||
|
},
|
||
|
'Functions': {
|
||
|
'debounce asap': true,
|
||
|
'debounce asap cancel': true,
|
||
|
'debounce after system time is set backwards': true,
|
||
|
'debounce asap recursively': true,
|
||
|
'throttle repeatedly with results': true,
|
||
|
'more throttle does not trigger leading call when leading is set to false': true,
|
||
|
'throttle does not trigger trailing call when trailing is set to false': true,
|
||
|
'before': [
|
||
|
'stores a memo to the last value',
|
||
|
'provides context'
|
||
|
],
|
||
|
'bind': [
|
||
|
'Died on test #2'
|
||
|
],
|
||
|
'bindAll': [
|
||
|
'throws an error for bindAll with no functions named'
|
||
|
],
|
||
|
'memoize': [
|
||
|
'{"bar":"BAR","foo":"FOO"}',
|
||
|
'Died on test #8'
|
||
|
],
|
||
|
'partial':[
|
||
|
'can partially apply with placeholders',
|
||
|
'accepts more arguments than the number of placeholders',
|
||
|
'accepts fewer arguments than the number of placeholders',
|
||
|
'unfilled placeholders are undefined',
|
||
|
'keeps prototype',
|
||
|
'allows the placeholder to be swapped out'
|
||
|
]
|
||
|
},
|
||
|
'Objects': {
|
||
|
'#1929 Typed Array constructors are functions': true,
|
||
|
'allKeys': [
|
||
|
'is not fooled by sparse arrays; see issue #95',
|
||
|
'is not fooled by sparse arrays with additional properties',
|
||
|
'[]'
|
||
|
],
|
||
|
'defaults': [
|
||
|
'defaults skips nulls',
|
||
|
'defaults skips undefined'
|
||
|
],
|
||
|
'extend': [
|
||
|
'extending null results in null',
|
||
|
'extending undefined results in undefined'
|
||
|
],
|
||
|
'extendOwn': [
|
||
|
'extending non-objects results in returning the non-object value',
|
||
|
'extending undefined results in undefined'
|
||
|
],
|
||
|
'functions': [
|
||
|
'also looks up functions on the prototype'
|
||
|
],
|
||
|
'isEqual': [
|
||
|
'`0` is not equal to `-0`',
|
||
|
'Commutative equality is implemented for `0` and `-0`',
|
||
|
'`new Number(0)` and `-0` are not equal',
|
||
|
'Commutative equality is implemented for `new Number(0)` and `-0`',
|
||
|
'false'
|
||
|
],
|
||
|
'isFinite': [
|
||
|
'Numeric strings are numbers',
|
||
|
'Number instances can be finite'
|
||
|
],
|
||
|
'isMatch': [
|
||
|
'doesnt falsey match constructor on undefined/null'
|
||
|
],
|
||
|
'isSet': [
|
||
|
'Died on test #9'
|
||
|
],
|
||
|
'findKey': [
|
||
|
'called with context'
|
||
|
],
|
||
|
'keys': [
|
||
|
'is not fooled by sparse arrays; see issue #95',
|
||
|
'[]'
|
||
|
],
|
||
|
'mapObject': [
|
||
|
'keep context',
|
||
|
'called with context',
|
||
|
'mapValue identity'
|
||
|
],
|
||
|
'matcher': [
|
||
|
'null matches null',
|
||
|
'treats primitives as empty'
|
||
|
],
|
||
|
'omit': [
|
||
|
'can accept a predicate',
|
||
|
'function is given context'
|
||
|
],
|
||
|
'pick': [
|
||
|
'can accept a predicate and context',
|
||
|
'function is given context'
|
||
|
]
|
||
|
},
|
||
|
'Utility': {
|
||
|
'noConflict (node vm)': true,
|
||
|
'now': [
|
||
|
'Produces the correct time in milliseconds'
|
||
|
],
|
||
|
'times': [
|
||
|
'works as a wrapper'
|
||
|
]
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var mixinPrereqs = (function() {
|
||
|
var aliasToReal = {
|
||
|
'all': 'every',
|
||
|
'allKeys': 'keysIn',
|
||
|
'any': 'some',
|
||
|
'collect': 'map',
|
||
|
'compose': 'flowRight',
|
||
|
'contains': 'includes',
|
||
|
'detect': 'find',
|
||
|
'extendOwn': 'assign',
|
||
|
'findWhere': 'find',
|
||
|
'foldl': 'reduce',
|
||
|
'foldr': 'reduceRight',
|
||
|
'include': 'includes',
|
||
|
'indexBy': 'keyBy',
|
||
|
'inject': 'reduce',
|
||
|
'invoke': 'invokeMap',
|
||
|
'mapObject': 'mapValues',
|
||
|
'matcher': 'matches',
|
||
|
'methods': 'functions',
|
||
|
'object': 'zipObject',
|
||
|
'pairs': 'toPairs',
|
||
|
'pluck': 'map',
|
||
|
'restParam': 'restArgs',
|
||
|
'select': 'filter',
|
||
|
'unique': 'uniq',
|
||
|
'where': 'filter'
|
||
|
};
|
||
|
|
||
|
var keyMap = {
|
||
|
'rest': 'tail',
|
||
|
'restArgs': 'rest'
|
||
|
};
|
||
|
|
||
|
var lodash = _.noConflict();
|
||
|
|
||
|
return function(_) {
|
||
|
lodash.defaultsDeep(_, { 'templateSettings': lodash.templateSettings });
|
||
|
lodash.mixin(_, lodash.pick(lodash, lodash.difference(lodash.functions(lodash), lodash.functions(_))));
|
||
|
|
||
|
lodash.forOwn(keyMap, function(realName, otherName) {
|
||
|
_[otherName] = lodash[realName];
|
||
|
_.prototype[otherName] = lodash.prototype[realName];
|
||
|
});
|
||
|
|
||
|
lodash.forOwn(aliasToReal, function(realName, alias) {
|
||
|
_[alias] = _[realName];
|
||
|
_.prototype[alias] = _.prototype[realName];
|
||
|
});
|
||
|
};
|
||
|
}());
|
||
|
|
||
|
// Only excuse in Sauce Labs.
|
||
|
if (!ui.isSauceLabs) {
|
||
|
delete QUnit.config.excused.Functions['throttle does not trigger trailing call when trailing is set to false'];
|
||
|
delete QUnit.config.excused.Utility.now;
|
||
|
}
|
||
|
// Load prerequisite scripts.
|
||
|
document.write(ui.urlParams.loader == 'none'
|
||
|
? '<script src="' + ui.buildPath + '"><\/script>'
|
||
|
: '<script data-dojo-config="async:1" src="' + ui.loaderPath + '"><\/script>'
|
||
|
);
|
||
|
</script>
|
||
|
<script>
|
||
|
if (ui.urlParams.loader == 'none') {
|
||
|
mixinPrereqs(_);
|
||
|
document.write([
|
||
|
'<script src="../vendor/underscore/test/collections.js"><\/script>',
|
||
|
'<script src="../vendor/underscore/test/arrays.js"><\/script>',
|
||
|
'<script src="../vendor/underscore/test/functions.js"><\/script>',
|
||
|
'<script src="../vendor/underscore/test/objects.js"><\/script>',
|
||
|
'<script src="../vendor/underscore/test/cross-document.js"><\/script>',
|
||
|
'<script src="../vendor/underscore/test/utility.js"><\/script>',
|
||
|
'<script src="../vendor/underscore/test/chaining.js"><\/script>'
|
||
|
].join('\n'));
|
||
|
}
|
||
|
</script>
|
||
|
<script>
|
||
|
(function() {
|
||
|
if (window.curl) {
|
||
|
curl.config({ 'apiName': 'require' });
|
||
|
}
|
||
|
if (!window.require) {
|
||
|
return;
|
||
|
}
|
||
|
// Wrap to work around tests assuming Node `require` use.
|
||
|
require = (function(func) {
|
||
|
return function() {
|
||
|
return arguments[0] === '..' ? window._ : func.apply(null, arguments);
|
||
|
};
|
||
|
}(require));
|
||
|
|
||
|
var reBasename = /[\w.-]+$/,
|
||
|
basePath = ('//' + location.host + location.pathname.replace(reBasename, '')).replace(/\btest\/$/, ''),
|
||
|
modulePath = ui.buildPath.replace(/\.js$/, ''),
|
||
|
locationPath = modulePath.replace(reBasename, '').replace(/^\/|\/$/g, ''),
|
||
|
moduleId = /\bunderscore\b/i.test(ui.buildPath) ? 'underscore' : 'lodash',
|
||
|
moduleMain = modulePath.match(reBasename)[0],
|
||
|
uid = +new Date;
|
||
|
|
||
|
function getConfig() {
|
||
|
var result = {
|
||
|
'baseUrl': './',
|
||
|
'urlArgs': 't=' + uid++,
|
||
|
'waitSeconds': 0,
|
||
|
'paths': {},
|
||
|
'packages': [{
|
||
|
'name': 'test',
|
||
|
'location': '../vendor/underscore/test',
|
||
|
'config': {
|
||
|
// Work around no global being exported.
|
||
|
'exports': 'QUnit',
|
||
|
'loader': 'curl/loader/legacy'
|
||
|
}
|
||
|
}]
|
||
|
};
|
||
|
|
||
|
if (ui.isModularize) {
|
||
|
result.packages.push({
|
||
|
'name': moduleId,
|
||
|
'location': locationPath,
|
||
|
'main': moduleMain
|
||
|
});
|
||
|
} else {
|
||
|
result.paths[moduleId] = modulePath;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
QUnit.config.autostart = false;
|
||
|
|
||
|
require(getConfig(), [moduleId], function(lodash) {
|
||
|
mixinPrereqs(lodash);
|
||
|
require(getConfig(), [
|
||
|
'test/collections',
|
||
|
'test/arrays',
|
||
|
'test/functions',
|
||
|
'test/objects',
|
||
|
'test/cross-document',
|
||
|
'test/utility',
|
||
|
'test/chaining'
|
||
|
], function() {
|
||
|
QUnit.start();
|
||
|
});
|
||
|
});
|
||
|
}());
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|