Upgrade QUnit from 2.4.0 to 2.6.0

Source
 https://code.jquery.com/qunit/qunit-2.6.0.js
 https://code.jquery.com/qunit/qunit-2.6.0.css

Changelog
 https://github.com/qunitjs/qunit/blob/2.6.0/History.md

Highlights:
* 2.4.1: Fixed various bugs in HTML interface.
* 2.5.0: Added assert.rejects.
* 2.5.1: Fixed HTML reporter to reset attributes on qunit-fixture.
* 2.6.0: Changed behaviour to fail if no test suites exist.

Change-Id: I24120a74094db358f02f9fc1935920c43a0a7ced
This commit is contained in:
Timo Tijhof 2018-05-01 21:04:21 +01:00
parent 0e746c7ef3
commit 065b21b4bd
3 changed files with 291 additions and 75 deletions

View file

@ -22,7 +22,7 @@ production.
* …
==== Upgraded external libraries ====
*
* Updated QUnit from 2.4.0 to 2.6.0.
==== New external libraries ====
* …

View file

@ -1,12 +1,12 @@
/*!
* QUnit 2.4.0
* QUnit 2.6.0
* https://qunitjs.com/
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2017-07-08T15:20Z
* Date: 2018-03-27T02:18Z
*/
/** Font Family and Sizes */

View file

@ -1,17 +1,17 @@
/*!
* QUnit 2.4.0
* QUnit 2.6.0
* https://qunitjs.com/
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2017-07-08T15:20Z
* Date: 2018-03-27T02:18Z
*/
(function (global$1) {
'use strict';
global$1 = global$1 && 'default' in global$1 ? global$1['default'] : global$1;
global$1 = global$1 && global$1.hasOwnProperty('default') ? global$1['default'] : global$1;
var window = global$1.window;
var self$1 = global$1.self;
@ -1097,58 +1097,89 @@
var priorityCount = 0;
var unitSampler = void 0;
// This is a queue of functions that are tasks within a single test.
// After tests are dequeued from config.queue they are expanded into
// a set of tasks in this queue.
var taskQueue = [];
/**
* Advances the ProcessingQueue to the next item if it is ready.
* @param {Boolean} last
* Advances the taskQueue to the next task. If the taskQueue is empty,
* process the testQueue
*/
function advance() {
advanceTaskQueue();
if (!taskQueue.length) {
advanceTestQueue();
}
}
/**
* Advances the taskQueue to the next task if it is ready and not empty.
*/
function advanceTaskQueue() {
var start = now();
config.depth = (config.depth || 0) + 1;
while (config.queue.length && !config.blocking) {
while (taskQueue.length && !config.blocking) {
var elapsedTime = now() - start;
if (!defined.setTimeout || config.updateRate <= 0 || elapsedTime < config.updateRate) {
if (priorityCount > 0) {
priorityCount--;
}
config.queue.shift()();
var task = taskQueue.shift();
task();
} else {
setTimeout(advance, 13);
setTimeout(advance);
break;
}
}
config.depth--;
if (!config.blocking && !config.queue.length && config.depth === 0) {
done();
}
}
function addToQueueImmediate(callback) {
if (objectType(callback) === "array") {
while (callback.length) {
addToQueueImmediate(callback.pop());
}
return;
}
config.queue.unshift(callback);
priorityCount++;
}
/**
* Adds a function to the ProcessingQueue for execution.
* @param {Function|Array} callback
* @param {Boolean} priority
* Advance the testQueue to the next test to process. Call done() if testQueue completes.
*/
function advanceTestQueue() {
if (!config.blocking && !config.queue.length && config.depth === 0) {
done();
return;
}
var testTasks = config.queue.shift();
addToTaskQueue(testTasks());
if (priorityCount > 0) {
priorityCount--;
}
advance();
}
/**
* Enqueue the tasks for a test into the task queue.
* @param {Array} tasksArray
*/
function addToTaskQueue(tasksArray) {
taskQueue.push.apply(taskQueue, toConsumableArray(tasksArray));
}
/**
* Return the number of tasks remaining in the task queue to be processed.
* @return {Number}
*/
function taskQueueLength() {
return taskQueue.length;
}
/**
* Adds a test to the TestQueue for execution.
* @param {Function} testTasksFunc
* @param {Boolean} prioritize
* @param {String} seed
*/
function addToQueue(callback, prioritize, seed) {
function addToTestQueue(testTasksFunc, prioritize, seed) {
if (prioritize) {
config.queue.splice(priorityCount++, 0, callback);
config.queue.splice(priorityCount++, 0, testTasksFunc);
} else if (seed) {
if (!unitSampler) {
unitSampler = unitSamplerGenerator(seed);
@ -1156,9 +1187,9 @@
// Insert into a random position after all prioritized items
var index = Math.floor(unitSampler() * (config.queue.length - priorityCount + 1));
config.queue.splice(priorityCount + index, 0, callback);
config.queue.splice(priorityCount + index, 0, testTasksFunc);
} else {
config.queue.push(callback);
config.queue.push(testTasksFunc);
}
}
@ -1196,6 +1227,27 @@
var runtime = now() - config.started;
var passed = config.stats.all - config.stats.bad;
if (config.stats.all === 0) {
if (config.filter && config.filter.length) {
throw new Error("No tests matched the filter \"" + config.filter + "\".");
}
if (config.module && config.module.length) {
throw new Error("No tests matched the module \"" + config.module + "\".");
}
if (config.moduleId && config.moduleId.length) {
throw new Error("No tests matched the moduleId \"" + config.moduleId + "\".");
}
if (config.testId && config.testId.length) {
throw new Error("No tests matched the testId \"" + config.testId + "\".");
}
throw new Error("No tests were run.");
}
emit("runEnd", globalSuite.end(true));
runLoggingCallbacks("done", {
passed: passed,
@ -1218,9 +1270,9 @@
var ProcessingQueue = {
finished: false,
add: addToQueue,
addImmediate: addToQueueImmediate,
advance: advance
add: addToTestQueue,
advance: advance,
taskCount: taskQueueLength
};
var TestReport = function () {
@ -1388,6 +1440,13 @@
this.async = false;
this.expected = 0;
} else {
if (typeof this.callback !== "function") {
var method = this.todo ? "todo" : "test";
// eslint-disable-next-line max-len
throw new TypeError("You must provide a function as a test callback to QUnit." + method + "(\"" + settings.testName + "\")");
}
this.assert = new Assert(this);
}
}
@ -1500,7 +1559,9 @@
_this.preserveEnvironment = true;
}
if (hookName === "after" && hookOwner.unskippedTestsRun !== numberOfUnskippedTests(hookOwner) - 1 && config.queue.length > 2) {
// The 'after' hook should only execute when there are not tests left and
// when the 'after' and 'finish' tasks are the only tasks left to process
if (hookName === "after" && hookOwner.unskippedTestsRun !== numberOfUnskippedTests(hookOwner) - 1 && (config.queue.length > 0 || ProcessingQueue.taskCount() > 2)) {
return;
}
@ -1547,6 +1608,12 @@
finish: function finish() {
config.current = this;
if (this.steps.length) {
var stepsList = this.steps.join(", ");
this.pushFailure("Expected assert.verifySteps() to be called before end of test " + ("after using assert.step(). Unverified steps: " + stepsList), this.stack);
}
if (config.requireExpects && this.expected === null) {
this.pushFailure("Expected number of assertions to be defined, but expect() was " + "not called.", this.stack);
} else if (this.expected !== null && this.expected !== this.assertions.length) {
@ -1653,15 +1720,13 @@
}
function runTest() {
// Each of these can by async
ProcessingQueue.addImmediate([function () {
return [function () {
test.before();
}, test.hooks("before"), function () {
}].concat(toConsumableArray(test.hooks("before")), [function () {
test.preserveTestEnvironment();
}, test.hooks("beforeEach"), function () {
}], toConsumableArray(test.hooks("beforeEach")), [function () {
test.run();
}, test.hooks("afterEach").reverse(), test.hooks("after").reverse(), function () {
}], toConsumableArray(test.hooks("afterEach").reverse()), toConsumableArray(test.hooks("after").reverse()), [function () {
test.after();
}, function () {
test.finish();
@ -1686,7 +1751,7 @@
pushResult: function pushResult(resultInfo) {
if (this !== config.current) {
throw new Error("Assertion occured after test had finished.");
throw new Error("Assertion occurred after test had finished.");
}
// Destructure of resultInfo = { result, actual, expected, message, negative }
@ -1697,13 +1762,16 @@
result: resultInfo.result,
message: resultInfo.message,
actual: resultInfo.actual,
expected: resultInfo.expected,
testId: this.testId,
negative: resultInfo.negative || false,
runtime: now() - this.started,
todo: !!this.todo
};
if (hasOwn.call(resultInfo, "expected")) {
details.expected = resultInfo.expected;
}
if (!resultInfo.result) {
source = resultInfo.source || sourceFromStacktrace();
@ -1729,7 +1797,6 @@
result: false,
message: message || "error",
actual: actual || null,
expected: null,
source: source
});
},
@ -1765,18 +1832,24 @@
then = promise.then;
if (objectType(then) === "function") {
resume = internalStop(test);
then.call(promise, function () {
resume();
}, function (error) {
message = "Promise rejected " + (!phase ? "during" : phase.replace(/Each$/, "")) + " \"" + test.testName + "\": " + (error && error.message || error);
test.pushFailure(message, extractStacktrace(error, 0));
if (config.notrycatch) {
then.call(promise, function () {
resume();
});
} else {
then.call(promise, function () {
resume();
}, function (error) {
message = "Promise rejected " + (!phase ? "during" : phase.replace(/Each$/, "")) + " \"" + test.testName + "\": " + (error && error.message || error);
test.pushFailure(message, extractStacktrace(error, 0));
// Else next test will carry the responsibility
saveGlobal();
// Else next test will carry the responsibility
saveGlobal();
// Unblock
resume();
});
// Unblock
internalRecover(test);
});
}
}
}
},
@ -2040,7 +2113,7 @@
}
begin();
}, 13);
});
} else {
begin();
}
@ -2125,13 +2198,21 @@
}, {
key: "step",
value: function step(message) {
var assertionMessage = message;
var result = !!message;
this.test.steps.push(message);
if (objectType(message) === "undefined" || message === "") {
assertionMessage = "You must provide a message to assert.step";
} else if (objectType(message) !== "string") {
assertionMessage = "You must provide a string value to assert.step";
result = false;
}
return this.pushResult({
result: result,
message: message || "You must provide a message to assert.step"
message: assertionMessage
});
}
@ -2140,7 +2221,11 @@
}, {
key: "verifySteps",
value: function verifySteps(steps, message) {
this.deepEqual(this.test.steps, steps, message);
// Since the steps array is just string values, we can clone with slice
var actualStepsClone = this.test.steps.slice();
this.deepEqual(actualStepsClone, steps, message);
this.test.steps.length = 0;
}
// Specify the number of expected assertions to guarantee that failed test
@ -2418,6 +2503,98 @@
message: message
});
}
}, {
key: "rejects",
value: function rejects(promise, expected, message) {
var result = false;
var currentTest = this instanceof Assert && this.test || config.current;
// 'expected' is optional unless doing string comparison
if (objectType(expected) === "string") {
if (message === undefined) {
message = expected;
expected = undefined;
} else {
message = "assert.rejects does not accept a string value for the expected " + "argument.\nUse a non-string object value (e.g. validator function) instead " + "if necessary.";
currentTest.assert.pushResult({
result: false,
message: message
});
return;
}
}
var then = promise && promise.then;
if (objectType(then) !== "function") {
var _message = "The value provided to `assert.rejects` in " + "\"" + currentTest.testName + "\" was not a promise.";
currentTest.assert.pushResult({
result: false,
message: _message,
actual: promise
});
return;
}
var done = this.async();
return then.call(promise, function handleFulfillment() {
var message = "The promise returned by the `assert.rejects` callback in " + "\"" + currentTest.testName + "\" did not reject.";
currentTest.assert.pushResult({
result: false,
message: message,
actual: promise
});
done();
}, function handleRejection(actual) {
var expectedType = objectType(expected);
// We don't want to validate
if (expected === undefined) {
result = true;
expected = actual;
// Expected is a regexp
} else if (expectedType === "regexp") {
result = expected.test(errorString(actual));
// Expected is a constructor, maybe an Error constructor
} else if (expectedType === "function" && actual instanceof expected) {
result = true;
// Expected is an Error object
} else if (expectedType === "object") {
result = actual instanceof expected.constructor && actual.name === expected.name && actual.message === expected.message;
// Expected is a validation function which returns true if validation passed
} else {
if (expectedType === "function") {
result = expected.call({}, actual) === true;
expected = null;
// Expected is some other invalid type
} else {
result = false;
message = "invalid expected value provided to `assert.rejects` " + "callback in \"" + currentTest.testName + "\": " + expectedType + ".";
}
}
currentTest.assert.pushResult({
result: result,
actual: actual,
expected: expected,
message: message
});
done();
});
}
}]);
return Assert;
}();
@ -2633,6 +2810,25 @@
return false;
}
// Handle an unhandled rejection
function onUnhandledRejection(reason) {
var resultInfo = {
result: false,
message: reason.message || "error",
actual: reason,
source: reason.stack || sourceFromStacktrace(3)
};
var currentTest = config.current;
if (currentTest) {
currentTest.assert.pushResult(resultInfo);
} else {
test("global failure", extend(function (assert) {
assert.pushResult(resultInfo);
}, { validTest: true }));
}
}
var focused = false;
var QUnit = {};
var globalSuite = new SuiteReport();
@ -2650,7 +2846,7 @@
QUnit.isLocal = !(defined.document && window.location.protocol !== "file:");
// Expose the current QUnit version
QUnit.version = "2.4.0";
QUnit.version = "2.6.0";
function createModule(name, testEnvironment, modifiers) {
var parentModule = moduleStack.length ? moduleStack.slice(-1)[0] : null;
@ -2868,7 +3064,9 @@
return sourceFromStacktrace(offset);
},
onError: onError
onError: onError,
onUnhandledRejection: onUnhandledRejection
});
QUnit.pushFailure = pushFailure;
@ -2886,7 +3084,7 @@
if (defined.setTimeout) {
setTimeout(function () {
begin();
}, 13);
});
} else {
begin();
}
@ -2955,7 +3153,7 @@
var fixture = document.getElementById("qunit-fixture");
if (fixture) {
config.fixture = fixture.innerHTML;
config.fixture = fixture.cloneNode(true);
}
}
@ -2968,8 +3166,17 @@
}
var fixture = document.getElementById("qunit-fixture");
if (fixture) {
fixture.innerHTML = config.fixture;
var resetFixtureType = _typeof(config.fixture);
if (resetFixtureType === "string") {
// support user defined values for `config.fixture`
var newFixture = document.createElement("div");
newFixture.setAttribute("id", "qunit-fixture");
newFixture.innerHTML = config.fixture;
fixture.parentNode.replaceChild(newFixture, fixture);
} else {
var clonedFixture = config.fixture.cloneNode(true);
fixture.parentNode.replaceChild(clonedFixture, fixture);
}
}
@ -3284,7 +3491,8 @@
// Skip inherited or undefined properties
if (hasOwn.call(params, key) && params[key] !== undefined) {
// Output a parameter for each value of this key (but usually just one)
// Output a parameter for each value of this key
// (but usually just one)
arrValue = [].concat(params[key]);
for (i = 0; i < arrValue.length; i++) {
querystring += encodeURIComponent(key);
@ -3705,7 +3913,8 @@
if (config.altertitle && document$$1.title) {
// Show ✖ for good, ✔ for bad suite result in title
// use escape sequences in case file gets loaded with non-utf-8-charset
// use escape sequences in case file gets loaded with non-utf-8
// charset
document$$1.title = [stats.failedTests ? "\u2716" : "\u2714", document$$1.title.replace(/^[\u2714\u2716] /i, "")].join(" ");
}
@ -3743,7 +3952,7 @@
if (running) {
bad = QUnit.config.reorder && details.previousFailure;
running.innerHTML = (bad ? "Rerunning previously failed test: <br />" : "Running: <br />") + getNameHtml(details.name, details.module);
running.innerHTML = [bad ? "Rerunning previously failed test: <br />" : "Running: <br />", getNameHtml(details.name, details.module)].join("");
}
});
@ -3974,6 +4183,11 @@
return ret;
};
// Listen for unhandled rejections, and call QUnit.onUnhandledRejection
window.addEventListener("unhandledrejection", function (event) {
QUnit.onUnhandledRejection(event.reason);
});
})();
/*
@ -4874,7 +5088,9 @@
line = text.substring(lineStart, lineEnd + 1);
lineStart = lineEnd + 1;
if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== undefined) {
var lineHashExists = lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== undefined;
if (lineHashExists) {
chars += String.fromCharCode(lineHash[line]);
} else {
chars += String.fromCharCode(lineArrayLength);