mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-07 01:57:50 +00:00
Move qunit extras to qunit-extras.js.
This commit is contained in:
164
test/asset/qunit-extras.js
Normal file
164
test/asset/qunit-extras.js
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
;(function(root, undefined) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** Native method shortcut */
|
||||||
|
var unshift = Array.prototype.unshift;
|
||||||
|
|
||||||
|
/** Used to match HTML entities */
|
||||||
|
var reEscapedHtml = /(&|<|>|"|')/g;
|
||||||
|
|
||||||
|
/** Used to match parts of the assert message */
|
||||||
|
var reDied = /^Died on test #\d+/,
|
||||||
|
reExpected = /Expected: *<\/th><td><pre>([\s\S]*?)<\/pre>/,
|
||||||
|
reMessage = /^<span class='test-message'>([\s\S]*?)<\/span>/;
|
||||||
|
|
||||||
|
/** Used to convert HTML entities to characters */
|
||||||
|
var htmlUnescapes = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"',
|
||||||
|
''': "'"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a given value is present in an array using strict equality
|
||||||
|
* for comparisons, i.e. `===`.
|
||||||
|
*
|
||||||
|
* @oruvate
|
||||||
|
* @param {Array} array The array to iterate over.
|
||||||
|
* @param {*} target The value to check for.
|
||||||
|
* @returns {boolean} Returns `true` if the `target` element is found, else `false`.
|
||||||
|
*/
|
||||||
|
function contains(array, value) {
|
||||||
|
var index = -1,
|
||||||
|
length = array ? array.length : 0;
|
||||||
|
|
||||||
|
while (++index < length) {
|
||||||
|
if (array[index] === value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the value of `property` on `object`. If `object` is falsey then
|
||||||
|
* `undefined` is returned.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} object The object to inspect.
|
||||||
|
* @param {string} property The property to get the value of.
|
||||||
|
* @returns {*} Returns the resolved value.
|
||||||
|
*/
|
||||||
|
function result(object, property) {
|
||||||
|
return object ? object[property] : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the HTML entities `&`, `<`, `>`, `"`, and `'`
|
||||||
|
* in `string` to their corresponding characters.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} string The string to unescape.
|
||||||
|
* @returns {string} Returns the unescaped string.
|
||||||
|
*/
|
||||||
|
function unescape(string) {
|
||||||
|
return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by `unescape` to convert HTML entities to characters.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} match The matched character to unescape.
|
||||||
|
* @returns {string} Returns the unescaped character.
|
||||||
|
*/
|
||||||
|
function unescapeHtmlChar(match) {
|
||||||
|
return htmlUnescapes[match];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/** The number of retries async tests have to succeed */
|
||||||
|
QUnit.config.asyncRetries = 0;
|
||||||
|
|
||||||
|
/** An object of excused tests and assertions */
|
||||||
|
QUnit.config.excused = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback triggered at the start of every test.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @param {Object} details An object with `module` and `name` properties.
|
||||||
|
*/
|
||||||
|
QUnit.testStart(function(details) {
|
||||||
|
var excused = QUnit.config.excused || {},
|
||||||
|
excusedTests = excused[details.module],
|
||||||
|
excusedAsserts = excusedTests && excusedTests[details.name];
|
||||||
|
|
||||||
|
var test = QUnit.config.current,
|
||||||
|
finish = test.finish;
|
||||||
|
|
||||||
|
// allow async tests to retry
|
||||||
|
if (test.async && !test.retries) {
|
||||||
|
test.retries = 0;
|
||||||
|
test.finish = function() {
|
||||||
|
var asserts = this.assertions,
|
||||||
|
index = -1,
|
||||||
|
length = asserts.length,
|
||||||
|
queue = QUnit.config.queue;
|
||||||
|
|
||||||
|
while (++index < length) {
|
||||||
|
var assert = asserts[index];
|
||||||
|
if (!assert.result && this.retries < QUnit.config.asyncRetries) {
|
||||||
|
this.retries++;
|
||||||
|
asserts.length = 0;
|
||||||
|
|
||||||
|
var oldLength = queue.length;
|
||||||
|
this.queue();
|
||||||
|
unshift.apply(queue, queue.splice(oldLength, queue.length - oldLength));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finish.call(this);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// nothing to excuse
|
||||||
|
if (!excusedAsserts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// excuse the entire test
|
||||||
|
if (excusedAsserts === true) {
|
||||||
|
test.async = false;
|
||||||
|
test.callback = function() {};
|
||||||
|
test.expected = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// excuse specific assertions
|
||||||
|
test.finish = function() {
|
||||||
|
var asserts = this.assertions,
|
||||||
|
index = -1,
|
||||||
|
length = asserts.length;
|
||||||
|
|
||||||
|
while (++index < length) {
|
||||||
|
var assert = asserts[index],
|
||||||
|
message = unescape(result(reMessage.exec(assert.message), 1)),
|
||||||
|
died = result(reDied.exec(message), 0),
|
||||||
|
expected = unescape(result(reExpected.exec(assert.message), 1));
|
||||||
|
|
||||||
|
if ((message && contains(excusedAsserts, message)) ||
|
||||||
|
(died && contains(excusedAsserts, died)) ||
|
||||||
|
(expected && (
|
||||||
|
contains(excusedAsserts, expected) ||
|
||||||
|
contains(excusedAsserts, expected.replace(/\s+/g, ''))
|
||||||
|
))) {
|
||||||
|
assert.result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finish.call(this);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}(this));
|
||||||
@@ -22,75 +22,37 @@
|
|||||||
<script src="../vendor/jquery/jquery.js"></script>
|
<script src="../vendor/jquery/jquery.js"></script>
|
||||||
<script src="../vendor/platform.js/platform.js"></script>
|
<script src="../vendor/platform.js/platform.js"></script>
|
||||||
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
||||||
|
<script src="./asset/qunit-extras.js"></script>
|
||||||
<script src="./asset/test-ui.js"></script>
|
<script src="./asset/test-ui.js"></script>
|
||||||
<script src="../lodash.js"></script>
|
<script src="../lodash.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var lodash = _.noConflict();
|
var lodash = _.noConflict();
|
||||||
|
|
||||||
|
QUnit.config.asyncRetries = 3;
|
||||||
QUnit.config.hidepassed = true;
|
QUnit.config.hidepassed = true;
|
||||||
|
|
||||||
|
// excuse tests we intentionally fail or those with problems
|
||||||
|
QUnit.config.excused = {
|
||||||
|
'Backbone.Collection': {
|
||||||
|
'set with many models does not overflow the stack': true
|
||||||
|
},
|
||||||
|
'Backbone.Router': {
|
||||||
|
'#2656 - No trailing slash on root.': true,
|
||||||
|
'#2765 - Fragment matching sans query/hash.': true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// only excuse `Backbone.Router` tests in IE < 8
|
||||||
|
if (!(document.attachEvent && (document.documentMode || 0) < 8)) {
|
||||||
|
delete QUnit.config.excused['Backbone.Router'];
|
||||||
|
}
|
||||||
|
|
||||||
// assign results to `global_test_results` for Sauce Labs
|
// assign results to `global_test_results` for Sauce Labs
|
||||||
var global_test_results;
|
var global_test_results;
|
||||||
QUnit.done(function(results) {
|
QUnit.done(function(results) {
|
||||||
global_test_results = results;
|
global_test_results = results;
|
||||||
});
|
});
|
||||||
|
|
||||||
// skip tests we intentionally fail or those with problems
|
|
||||||
(function() {
|
|
||||||
var skipped = {
|
|
||||||
'Backbone.Collection': {
|
|
||||||
'set with many models does not overflow the stack': true
|
|
||||||
},
|
|
||||||
'Backbone.Router': {
|
|
||||||
'#2656 - No trailing slash on root.': true,
|
|
||||||
'#2765 - Fragment matching sans query/hash.': true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// only skip `Backbone.Router` tests in IE < 8
|
|
||||||
if (!(document.attachEvent && (document.documentMode || 0) < 8)) {
|
|
||||||
delete skipped['Backbone.Router'];
|
|
||||||
}
|
|
||||||
|
|
||||||
QUnit.testStart(function(details) {
|
|
||||||
var test = QUnit.config.current,
|
|
||||||
finish = test.finish,
|
|
||||||
skippedTests = skipped[details.module],
|
|
||||||
skippedAsserts = skippedTests && skippedTests[details.name];
|
|
||||||
|
|
||||||
if (!skippedAsserts) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (skippedAsserts === true) {
|
|
||||||
test.async = false;
|
|
||||||
test.callback = function() {};
|
|
||||||
test.expected = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
test.finish = function() {
|
|
||||||
var index = -1,
|
|
||||||
asserts = this.assertions,
|
|
||||||
length = asserts.length;
|
|
||||||
|
|
||||||
while (++index < length) {
|
|
||||||
var assert = asserts[index],
|
|
||||||
message = _.unescape(_.result(/^<span class='test-message'>([\s\S]*?)<\/span>/.exec(assert.message), 1)),
|
|
||||||
died = _.result(/^Died on test #\d+/.exec(message), 0),
|
|
||||||
expected = _.unescape(_.result(/Expected: *<\/th><td><pre>([\s\S]*?)<\/pre>/.exec(assert.message), 1));
|
|
||||||
|
|
||||||
if ((message && _.contains(skippedAsserts, message)) ||
|
|
||||||
(died && _.contains(skippedAsserts, died)) ||
|
|
||||||
(expected && (_.contains(skippedAsserts, expected) ||
|
|
||||||
_.contains(skippedAsserts, expected.replace(/\s+/g, '')))
|
|
||||||
)) {
|
|
||||||
assert.result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finish.call(this);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}());
|
|
||||||
|
|
||||||
// load Lo-Dash again to overwrite the existing `_` value
|
// load Lo-Dash again to overwrite the existing `_` value
|
||||||
document.write('<script src="' + ui.buildPath + '"><\/script>');
|
document.write('<script src="' + ui.buildPath + '"><\/script>');
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
||||||
<script src="../vendor/platform.js/platform.js"></script>
|
<script src="../vendor/platform.js/platform.js"></script>
|
||||||
|
<script src="./asset/qunit-extras.js"></script>
|
||||||
<script src="./asset/test-ui.js"></script>
|
<script src="./asset/test-ui.js"></script>
|
||||||
<div id="qunit"></div>
|
<div id="qunit"></div>
|
||||||
<div id="exports"></div>
|
<div id="exports"></div>
|
||||||
@@ -72,6 +73,7 @@
|
|||||||
delete Object._defineProperty;
|
delete Object._defineProperty;
|
||||||
delete Object._keys;
|
delete Object._keys;
|
||||||
|
|
||||||
|
QUnit.config.asyncRetries = 3;
|
||||||
QUnit.config.hidepassed = true;
|
QUnit.config.hidepassed = true;
|
||||||
|
|
||||||
// assign results to `global_test_results` for Sauce Labs
|
// assign results to `global_test_results` for Sauce Labs
|
||||||
|
|||||||
@@ -22,150 +22,94 @@
|
|||||||
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
||||||
<script src="../vendor/jquery/jquery.js"></script>
|
<script src="../vendor/jquery/jquery.js"></script>
|
||||||
<script src="../vendor/platform.js/platform.js"></script>
|
<script src="../vendor/platform.js/platform.js"></script>
|
||||||
|
<script src="./asset/qunit-extras.js"></script>
|
||||||
<script src="./asset/test-ui.js"></script>
|
<script src="./asset/test-ui.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
QUnit.config.asyncRetries = 3;
|
||||||
QUnit.config.hidepassed = true;
|
QUnit.config.hidepassed = true;
|
||||||
|
|
||||||
|
// excuse tests we intentionally fail or those with problems
|
||||||
|
QUnit.config.excused = {
|
||||||
|
'Arrays': {
|
||||||
|
'union': [
|
||||||
|
'[null,1,2,3]'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'Chaining': {
|
||||||
|
'reverse/concat/unshift/pop/map': [
|
||||||
|
'"34, 10, 8, 6, 4, 2, 10, 10"'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'Collections': {
|
||||||
|
'reduce': [
|
||||||
|
'handles a null (without initial value) properly',
|
||||||
|
'throws an error for empty arrays with no initial value'
|
||||||
|
],
|
||||||
|
'reduceRight': [
|
||||||
|
'handles a null (without initial value) properly',
|
||||||
|
'throws an error for empty arrays with no initial value'
|
||||||
|
],
|
||||||
|
'where': [
|
||||||
|
'Only get the first object matched.'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'Functions': {
|
||||||
|
'bind': [
|
||||||
|
'can bind without specifying a context',
|
||||||
|
'Died on test #2'
|
||||||
|
],
|
||||||
|
'bindAll': [
|
||||||
|
'throws an error for bindAll with no functions named'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'Objects': {
|
||||||
|
'isEqual': [
|
||||||
|
'Died on test #78'
|
||||||
|
],
|
||||||
|
'keys': [
|
||||||
|
'throws an error for `null` values',
|
||||||
|
'throws an error for `undefined` values',
|
||||||
|
'throws an error for number primitives',
|
||||||
|
'throws an error for string primitives',
|
||||||
|
'throws an error for boolean primitives'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'Utility': {
|
||||||
|
'_.escape': [
|
||||||
|
'"<a href="http://moe.com">Curly & Moe's</a>"'
|
||||||
|
],
|
||||||
|
'_.unescape': [
|
||||||
|
'"<a href=\\"http://moe.com\\">Curly & Moe's</a>"'
|
||||||
|
],
|
||||||
|
'times': [
|
||||||
|
'Died on test #1'
|
||||||
|
],
|
||||||
|
'uniqueId': [
|
||||||
|
'Died on test #1'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// only excuse in non-Underscore builds
|
||||||
|
if (/\bunderscore\b/i.test(ui.buildPath)) {
|
||||||
|
delete QUnit.config.excused.Chaining;
|
||||||
|
delete QUnit.config.excused.Collections.where;
|
||||||
|
delete QUnit.config.excused.Utility['_.escape'];
|
||||||
|
delete QUnit.config.excused.Utility['_.unescape'];
|
||||||
|
}
|
||||||
|
// only excuse in Sauce Labs
|
||||||
|
if (location.port != '8081') {
|
||||||
|
delete QUnit.config.excused.Objects.isEqual;
|
||||||
|
delete QUnit.config.excused.Utility.times;
|
||||||
|
delete QUnit.config.excused.Utility.uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
// assign results to `global_test_results` for Sauce Labs
|
// assign results to `global_test_results` for Sauce Labs
|
||||||
var global_test_results;
|
var global_test_results;
|
||||||
QUnit.done(function(results) {
|
QUnit.done(function(results) {
|
||||||
global_test_results = results;
|
global_test_results = results;
|
||||||
});
|
});
|
||||||
|
|
||||||
// skip tests we intentionally fail or those with problems
|
|
||||||
(function() {
|
|
||||||
var skipped = {
|
|
||||||
'Arrays': {
|
|
||||||
'union': [
|
|
||||||
'[null,1,2,3]'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'Chaining': {
|
|
||||||
'reverse/concat/unshift/pop/map': [
|
|
||||||
'"34, 10, 8, 6, 4, 2, 10, 10"'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'Collections': {
|
|
||||||
'reduce': [
|
|
||||||
'handles a null (without initial value) properly',
|
|
||||||
'throws an error for empty arrays with no initial value'
|
|
||||||
],
|
|
||||||
'reduceRight': [
|
|
||||||
'handles a null (without initial value) properly',
|
|
||||||
'throws an error for empty arrays with no initial value'
|
|
||||||
],
|
|
||||||
'where': [
|
|
||||||
'Only get the first object matched.'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'Functions': {
|
|
||||||
'bind': [
|
|
||||||
'can bind without specifying a context',
|
|
||||||
'Died on test #2'
|
|
||||||
],
|
|
||||||
'bindAll': [
|
|
||||||
'throws an error for bindAll with no functions named'
|
|
||||||
],
|
|
||||||
'throttle': true,
|
|
||||||
'throttle arguments': true,
|
|
||||||
'throttle once': true,
|
|
||||||
'throttle twice': true,
|
|
||||||
'more throttling': true,
|
|
||||||
'throttle repeatedly with results': true,
|
|
||||||
'throttle triggers trailing call when invoked repeatedly': true,
|
|
||||||
'throttle does not trigger leading call when leading is set to false': 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,
|
|
||||||
'debounce': true,
|
|
||||||
'debounce asap': true,
|
|
||||||
'debounce asap recursively': true
|
|
||||||
},
|
|
||||||
'Objects': {
|
|
||||||
'isEqual': [
|
|
||||||
'Died on test #78'
|
|
||||||
],
|
|
||||||
'keys': [
|
|
||||||
'throws an error for `null` values',
|
|
||||||
'throws an error for `undefined` values',
|
|
||||||
'throws an error for number primitives',
|
|
||||||
'throws an error for string primitives',
|
|
||||||
'throws an error for boolean primitives'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'Utility': {
|
|
||||||
'_.escape': [
|
|
||||||
'"<a href="http://moe.com">Curly & Moe's</a>"'
|
|
||||||
],
|
|
||||||
'_.unescape': [
|
|
||||||
'"<a href=\\"http://moe.com\\">Curly & Moe's</a>"'
|
|
||||||
],
|
|
||||||
'times': [
|
|
||||||
'Died on test #1'
|
|
||||||
],
|
|
||||||
'uniqueId': [
|
|
||||||
'Died on test #1'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// only skip in non-Underscore builds
|
|
||||||
if (/\bunderscore\b/i.test(ui.buildPath)) {
|
|
||||||
delete skipped.Chaining;
|
|
||||||
delete skipped.Collections.where;
|
|
||||||
delete skipped.Utility['_.escape'];
|
|
||||||
delete skipped.Utility['_.unescape'];
|
|
||||||
}
|
|
||||||
// only skip in Sauce Labs
|
|
||||||
if (location.port != '8081') {
|
|
||||||
for (var key in skipped.Functions) {
|
|
||||||
if (/\b(debounce|throttl)/.test(key)) {
|
|
||||||
delete skipped.Functions[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete skipped.Objects.isEqual;
|
|
||||||
delete skipped.Utility.times;
|
|
||||||
delete skipped.Utility.uniqueId;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUnit.testStart(function(details) {
|
|
||||||
var test = QUnit.config.current,
|
|
||||||
finish = test.finish,
|
|
||||||
skippedTests = skipped[details.module],
|
|
||||||
skippedAsserts = skippedTests && skippedTests[details.name];
|
|
||||||
|
|
||||||
if (!skippedAsserts) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (skippedAsserts === true) {
|
|
||||||
test.async = false;
|
|
||||||
test.callback = function() {};
|
|
||||||
test.expected = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
test.finish = function() {
|
|
||||||
var index = -1,
|
|
||||||
asserts = this.assertions,
|
|
||||||
length = asserts.length;
|
|
||||||
|
|
||||||
while (++index < length) {
|
|
||||||
var assert = asserts[index],
|
|
||||||
message = _.unescape(_.result(/^<span class='test-message'>([\s\S]*?)<\/span>/.exec(assert.message), 1)),
|
|
||||||
died = _.result(/^Died on test #\d+/.exec(message), 0),
|
|
||||||
expected = _.unescape(_.result(/Expected: *<\/th><td><pre>([\s\S]*?)<\/pre>/.exec(assert.message), 1));
|
|
||||||
|
|
||||||
if ((message && _.contains(skippedAsserts, message)) ||
|
|
||||||
(died && _.contains(skippedAsserts, died)) ||
|
|
||||||
(expected && (_.contains(skippedAsserts, expected) ||
|
|
||||||
_.contains(skippedAsserts, expected.replace(/\s+/g, '')))
|
|
||||||
)) {
|
|
||||||
assert.result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finish.call(this);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}());
|
|
||||||
|
|
||||||
// load Lo-Dash again to overwrite the existing `_` value
|
// load Lo-Dash again to overwrite the existing `_` value
|
||||||
document.write('<script src="' + (ui.isModularize ? '../lodash.js' : ui.buildPath) + '"><\/script>');
|
document.write('<script src="' + (ui.isModularize ? '../lodash.js' : ui.buildPath) + '"><\/script>');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user