1.
/*!
2.
* QUnit 2.10.0
3.
* https://qunitjs.com/
4.
*
5.
* Copyright jQuery Foundation and other contributors
6.
* Released under the MIT license
7.
* https://jquery.org/license
8.
*
9.
* Date: 2020-05-02T22:51Z
10.
*/
11.
(function (global$1) {
12.
'use strict';
13.
14.
global$1 = global$1 && global$1.hasOwnProperty('default') ? global$1['default'] : global$1;
15.
16.
var window$1 = global$1.window;
17.
var self$1 = global$1.self;
18.
var console = global$1.console;
19.
var setTimeout$1 = global$1.setTimeout;
20.
var clearTimeout = global$1.clearTimeout;
21.
22.
var document$1 = window$1 && window$1.document;
23.
var navigator = window$1 && window$1.navigator;
24.
25.
var localSessionStorage = function () {
26.
var x = "qunit-test-string";
27.
try {
28.
global$1.sessionStorage.setItem(x, x);
29.
global$1.sessionStorage.removeItem(x);
30.
return global$1.sessionStorage;
31.
} catch (e) {
32.
return undefined;
33.
}
34.
}();
35.
36.
/**
37.
* Returns a function that proxies to the given method name on the globals
38.
* console object. The proxy will also detect if the console doesn't exist and
39.
* will appropriately no-op. This allows support for IE9, which doesn't have a
40.
* console if the developer tools are not open.
41.
*/
42.
function consoleProxy(method) {
43.
return function () {
44.
if (console) {
45.
console[method].apply(console, arguments);
46.
}
47.
};
48.
}
49.
50.
var Logger = {
51.
warn: consoleProxy("warn")
52.
};
53.
54.
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
55.
return typeof obj;
56.
} : function (obj) {
57.
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
58.
};
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
var classCallCheck = function (instance, Constructor) {
71.
if (!(instance instanceof Constructor)) {
72.
throw new TypeError("Cannot call a class as a function");
73.
}
74.
};
75.
76.
var createClass = function () {
77.
function defineProperties(target, props) {
78.
for (var i = 0; i < props.length; i++) {
79.
var descriptor = props[i];
80.
descriptor.enumerable = descriptor.enumerable || false;
81.
descriptor.configurable = true;
82.
if ("value" in descriptor) descriptor.writable = true;
83.
Object.defineProperty(target, descriptor.key, descriptor);
84.
}
85.
}
86.
87.
return function (Constructor, protoProps, staticProps) {
88.
if (protoProps) defineProperties(Constructor.prototype, protoProps);
89.
if (staticProps) defineProperties(Constructor, staticProps);
90.
return Constructor;
91.
};
92.
}();
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
var toConsumableArray = function (arr) {
135.
if (Array.isArray(arr)) {
136.
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
137.
138.
return arr2;
139.
} else {
140.
return Array.from(arr);
141.
}
142.
};
143.
144.
var toString = Object.prototype.toString;
145.
var hasOwn = Object.prototype.hasOwnProperty;
146.
var now = Date.now || function () {
147.
return new Date().getTime();
148.
};
149.
150.
var hasPerformanceApi = detectPerformanceApi();
151.
var performance = hasPerformanceApi ? window$1.performance : undefined;
152.
var performanceNow = hasPerformanceApi ? performance.now.bind(performance) : now;
153.
154.
function detectPerformanceApi() {
155.
return window$1 && typeof window$1.performance !== "undefined" && typeof window$1.performance.mark === "function" && typeof window$1.performance.measure === "function";
156.
}
157.
158.
function measure(comment, startMark, endMark) {
159.
160.
// `performance.measure` may fail if the mark could not be found.
161.
// reasons a specific mark could not be found include: outside code invoking `performance.clearMarks()`
162.
try {
163.
performance.measure(comment, startMark, endMark);
164.
} catch (ex) {
165.
Logger.warn("performance.measure could not be executed because of ", ex.message);
166.
}
167.
}
168.
169.
var defined = {
170.
document: window$1 && window$1.document !== undefined,
171.
setTimeout: setTimeout$1 !== undefined
172.
};
173.
174.
// Returns a new Array with the elements that are in a but not in b
175.
function diff(a, b) {
176.
var i,
177.
j,
178.
result = a.slice();
179.
180.
for (i = 0; i < result.length; i++) {
181.
for (j = 0; j < b.length; j++) {
182.
if (result[i] === b[j]) {
183.
result.splice(i, 1);
184.
i--;
185.
break;
186.
}
187.
}
188.
}
189.
return result;
190.
}
191.
192.
/**
193.
* Determines whether an element exists in a given array or not.
194.
*
195.
* @method inArray
196.
* @param {Any} elem
197.
* @param {Array} array
198.
* @return {Boolean}
199.
*/
200.
function inArray(elem, array) {
201.
return array.indexOf(elem) !== -1;
202.
}
203.
204.
/**
205.
* Makes a clone of an object using only Array or Object as base,
206.
* and copies over the own enumerable properties.
207.
*
208.
* @param {Object} obj
209.
* @return {Object} New object with only the own properties (recursively).
210.
*/
211.
function objectValues(obj) {
212.
var key,
213.
val,
214.
vals = is("array", obj) ? [] : {};
215.
for (key in obj) {
216.
if (hasOwn.call(obj, key)) {
217.
val = obj[key];
218.
vals[key] = val === Object(val) ? objectValues(val) : val;
219.
}
220.
}
221.
return vals;
222.
}
223.
224.
function extend(a, b, undefOnly) {
225.
for (var prop in b) {
226.
if (hasOwn.call(b, prop)) {
227.
if (b[prop] === undefined) {
228.
delete a[prop];
229.
} else if (!(undefOnly && typeof a[prop] !== "undefined")) {
230.
a[prop] = b[prop];
231.
}
232.
}
233.
}
234.
235.
return a;
236.
}
237.
238.
function objectType(obj) {
239.
if (typeof obj === "undefined") {
240.
return "undefined";
241.
}
242.
243.
// Consider: typeof null === object
244.
if (obj === null) {
245.
return "null";
246.
}
247.
248.
var match = toString.call(obj).match(/^\[object\s(.*)\]$/),
249.
type = match && match[1];
250.
251.
switch (type) {
252.
case "Number":
253.
if (isNaN(obj)) {
254.
return "nan";
255.
}
256.
return "number";
257.
case "String":
258.
case "Boolean":
259.
case "Array":
260.
case "Set":
261.
case "Map":
262.
case "Date":
263.
case "RegExp":
264.
case "Function":
265.
case "Symbol":
266.
return type.toLowerCase();
267.
default:
268.
return typeof obj === "undefined" ? "undefined" : _typeof(obj);
269.
}
270.
}
271.
272.
// Safe object type checking
273.
function is(type, obj) {
274.
return objectType(obj) === type;
275.
}
276.
277.
// Based on Java's String.hashCode, a simple but not
278.
// rigorously collision resistant hashing function
279.
function generateHash(module, testName) {
280.
var str = module + "\x1C" + testName;
281.
var hash = 0;
282.
283.
for (var i = 0; i < str.length; i++) {
284.
hash = (hash << 5) - hash + str.charCodeAt(i);
285.
hash |= 0;
286.
}
287.
288.
// Convert the possibly negative integer hash code into an 8 character hex string, which isn't
289.
// strictly necessary but increases user understanding that the id is a SHA-like hash
290.
var hex = (0x100000000 + hash).toString(16);
291.
if (hex.length < 8) {
292.
hex = "0000000" + hex;
293.
}
294.
295.
return hex.slice(-8);
296.
}
297.
298.
// Test for equality any JavaScript type.
299.
// Authors: Philippe Rathé <prathe@gmail.com>, David Chan <david@troi.org>
300.
var equiv = (function () {
301.
302.
// Value pairs queued for comparison. Used for breadth-first processing order, recursion
303.
// detection and avoiding repeated comparison (see below for details).
304.
// Elements are { a: val, b: val }.
305.
var pairs = [];
306.
307.
var getProto = Object.getPrototypeOf || function (obj) {
308.
return obj.__proto__;
309.
};
310.
311.
function useStrictEquality(a, b) {
312.
313.
// This only gets called if a and b are not strict equal, and is used to compare on
314.
// the primitive values inside object wrappers. For example:
315.
// `var i = 1;`
316.
// `var j = new Number(1);`
317.
// Neither a nor b can be null, as a !== b and they have the same type.
318.
if ((typeof a === "undefined" ? "undefined" : _typeof(a)) === "object") {
319.
a = a.valueOf();
320.
}
321.
if ((typeof b === "undefined" ? "undefined" : _typeof(b)) === "object") {
322.
b = b.valueOf();
323.
}
324.
325.
return a === b;
326.
}
327.
328.
function compareConstructors(a, b) {
329.
var protoA = getProto(a);
330.
var protoB = getProto(b);
331.
332.
// Comparing constructors is more strict than using `instanceof`
333.
if (a.constructor === b.constructor) {
334.
return true;
335.
}
336.
337.
// Ref #851
338.
// If the obj prototype descends from a null constructor, treat it
339.
// as a null prototype.
340.
if (protoA && protoA.constructor === null) {
341.
protoA = null;
342.
}
343.
if (protoB && protoB.constructor === null) {
344.
protoB = null;
345.
}
346.
347.
// Allow objects with no prototype to be equivalent to
348.
// objects with Object as their constructor.
349.
if (protoA === null && protoB === Object.prototype || protoB === null && protoA === Object.prototype) {
350.
return true;
351.
}
352.
353.
return false;
354.
}
355.
356.
function getRegExpFlags(regexp) {
357.
return "flags" in regexp ? regexp.flags : regexp.toString().match(/[gimuy]*$/)[0];
358.
}
359.
360.
function isContainer(val) {
361.
return ["object", "array", "map", "set"].indexOf(objectType(val)) !== -1;
362.
}
363.
364.
function breadthFirstCompareChild(a, b) {
365.
366.
// If a is a container not reference-equal to b, postpone the comparison to the
367.
// end of the pairs queue -- unless (a, b) has been seen before, in which case skip
368.
// over the pair.
369.
if (a === b) {
370.
return true;
371.
}
372.
if (!isContainer(a)) {
373.
return typeEquiv(a, b);
374.
}
375.
if (pairs.every(function (pair) {
376.
return pair.a !== a || pair.b !== b;
377.
})) {
378.
379.
// Not yet started comparing this pair
380.
pairs.push({ a: a, b: b });
381.
}
382.
return true;
383.
}
384.
385.
var callbacks = {
386.
"string": useStrictEquality,
387.
"boolean": useStrictEquality,
388.
"number": useStrictEquality,
389.
"null": useStrictEquality,
390.
"undefined": useStrictEquality,
391.
"symbol": useStrictEquality,
392.
"date": useStrictEquality,
393.
394.
"nan": function nan() {
395.
return true;
396.
},
397.
398.
"regexp": function regexp(a, b) {
399.
return a.source === b.source &&
400.
401.
// Include flags in the comparison
402.
getRegExpFlags(a) === getRegExpFlags(b);
403.
},
404.
405.
// abort (identical references / instance methods were skipped earlier)
406.
"function": function _function() {
407.
return false;
408.
},
409.
410.
"array": function array(a, b) {
411.
var i, len;
412.
413.
len = a.length;
414.
if (len !== b.length) {
415.
416.
// Safe and faster
417.
return false;
418.
}
419.
420.
for (i = 0; i < len; i++) {
421.
422.
// Compare non-containers; queue non-reference-equal containers
423.
if (!breadthFirstCompareChild(a[i], b[i])) {
424.
return false;
425.
}
426.
}
427.
return true;
428.
},
429.
430.
// Define sets a and b to be equivalent if for each element aVal in a, there
431.
// is some element bVal in b such that aVal and bVal are equivalent. Element
432.
// repetitions are not counted, so these are equivalent:
433.
// a = new Set( [ {}, [], [] ] );
434.
// b = new Set( [ {}, {}, [] ] );
435.
"set": function set$$1(a, b) {
436.
var innerEq,
437.
outerEq = true;
438.
439.
if (a.size !== b.size) {
440.
441.
// This optimization has certain quirks because of the lack of
442.
// repetition counting. For instance, adding the same
443.
// (reference-identical) element to two equivalent sets can
444.
// make them non-equivalent.
445.
return false;
446.
}
447.
448.
a.forEach(function (aVal) {
449.
450.
// Short-circuit if the result is already known. (Using for...of
451.
// with a break clause would be cleaner here, but it would cause
452.
// a syntax error on older Javascript implementations even if
453.
// Set is unused)
454.
if (!outerEq) {
455.
return;
456.
}
457.
458.
innerEq = false;
459.
460.
b.forEach(function (bVal) {
461.
var parentPairs;
462.
463.
// Likewise, short-circuit if the result is already known
464.
if (innerEq) {
465.
return;
466.
}
467.
468.
// Swap out the global pairs list, as the nested call to
469.
// innerEquiv will clobber its contents
470.
parentPairs = pairs;
471.
if (innerEquiv(bVal, aVal)) {
472.
innerEq = true;
473.
}
474.
475.
// Replace the global pairs list
476.
pairs = parentPairs;
477.
});
478.
479.
if (!innerEq) {
480.
outerEq = false;
481.
}
482.
});
483.
484.
return outerEq;
485.
},
486.
487.
// Define maps a and b to be equivalent if for each key-value pair (aKey, aVal)
488.
// in a, there is some key-value pair (bKey, bVal) in b such that
489.
// [ aKey, aVal ] and [ bKey, bVal ] are equivalent. Key repetitions are not
490.
// counted, so these are equivalent:
491.
// a = new Map( [ [ {}, 1 ], [ {}, 1 ], [ [], 1 ] ] );
492.
// b = new Map( [ [ {}, 1 ], [ [], 1 ], [ [], 1 ] ] );
493.
"map": function map(a, b) {
494.
var innerEq,
495.
outerEq = true;
496.
497.
if (a.size !== b.size) {
498.
499.
// This optimization has certain quirks because of the lack of
500.
// repetition counting. For instance, adding the same
501.
// (reference-identical) key-value pair to two equivalent maps
502.
// can make them non-equivalent.
503.
return false;
504.
}
505.
506.
a.forEach(function (aVal, aKey) {
507.
508.
// Short-circuit if the result is already known. (Using for...of
509.
// with a break clause would be cleaner here, but it would cause
510.
// a syntax error on older Javascript implementations even if
511.
// Map is unused)
512.
if (!outerEq) {
513.
return;
514.
}
515.
516.
innerEq = false;
517.
518.
b.forEach(function (bVal, bKey) {
519.
var parentPairs;
520.
521.
// Likewise, short-circuit if the result is already known
522.
if (innerEq) {
523.
return;
524.
}
525.
526.
// Swap out the global pairs list, as the nested call to
527.
// innerEquiv will clobber its contents
528.
parentPairs = pairs;
529.
if (innerEquiv([bVal, bKey], [aVal, aKey])) {
530.
innerEq = true;
531.
}
532.
533.
// Replace the global pairs list
534.
pairs = parentPairs;
535.
});
536.
537.
if (!innerEq) {
538.
outerEq = false;
539.
}
540.
});
541.
542.
return outerEq;
543.
},
544.
545.
"object": function object(a, b) {
546.
var i,
547.
aProperties = [],
548.
bProperties = [];
549.
550.
if (compareConstructors(a, b) === false) {
551.
return false;
552.
}
553.
554.
// Be strict: don't ensure hasOwnProperty and go deep
555.
for (i in a) {
556.
557.
// Collect a's properties
558.
aProperties.push(i);
559.
560.
// Skip OOP methods that look the same
561.
if (a.constructor !== Object && typeof a.constructor !== "undefined" && typeof a[i] === "function" && typeof b[i] === "function" && a[i].toString() === b[i].toString()) {
562.
continue;
563.
}
564.
565.
// Compare non-containers; queue non-reference-equal containers
566.
if (!breadthFirstCompareChild(a[i], b[i])) {
567.
return false;
568.
}
569.
}
570.
571.
for (i in b) {
572.
573.
// Collect b's properties
574.
bProperties.push(i);
575.
}
576.
577.
// Ensures identical properties name
578.
return typeEquiv(aProperties.sort(), bProperties.sort());
579.
}
580.
};
581.
582.
function typeEquiv(a, b) {
583.
var type = objectType(a);
584.
585.
// Callbacks for containers will append to the pairs queue to achieve breadth-first
586.
// search order. The pairs queue is also used to avoid reprocessing any pair of
587.
// containers that are reference-equal to a previously visited pair (a special case
588.
// this being recursion detection).
589.
//
590.
// Because of this approach, once typeEquiv returns a false value, it should not be
591.
// called again without clearing the pair queue else it may wrongly report a visited
592.
// pair as being equivalent.
593.
return objectType(b) === type && callbacks[type](a, b);
594.
}
595.
596.
function innerEquiv(a, b) {
597.
var i, pair;
598.
599.
// We're done when there's nothing more to compare
600.
if (arguments.length < 2) {
601.
return true;
602.
}
603.
604.
// Clear the global pair queue and add the top-level values being compared
605.
pairs = [{ a: a, b: b }];
606.
607.
for (i = 0; i < pairs.length; i++) {
608.
pair = pairs[i];
609.
610.
// Perform type-specific comparison on any pairs that are not strictly
611.
// equal. For container types, that comparison will postpone comparison
612.
// of any sub-container pair to the end of the pair queue. This gives
613.
// breadth-first search order. It also avoids the reprocessing of
614.
// reference-equal siblings, cousins etc, which can have a significant speed
615.
// impact when comparing a container of small objects each of which has a
616.
// reference to the same (singleton) large object.
617.
if (pair.a !== pair.b && !typeEquiv(pair.a, pair.b)) {
618.
return false;
619.
}
620.
}
621.
622.
// ...across all consecutive argument pairs
623.
return arguments.length === 2 || innerEquiv.apply(this, [].slice.call(arguments, 1));
624.
}
625.
626.
return function () {
627.
var result = innerEquiv.apply(undefined, arguments);
628.
629.
// Release any retained objects
630.
pairs.length = 0;
631.
return result;
632.
};
633.
})();
634.
635.
/**
636.
* Config object: Maintain internal state
637.
* Later exposed as QUnit.config
638.
* `config` initialized at top of scope
639.
*/
640.
var config = {
641.
642.
// The queue of tests to run
643.
queue: [],
644.
645.
// Block until document ready
646.
blocking: true,
647.
648.
// By default, run previously failed tests first
649.
// very useful in combination with "Hide passed tests" checked
650.
reorder: true,
651.
652.
// By default, modify document.title when suite is done
653.
altertitle: true,
654.
655.
// HTML Reporter: collapse every test except the first failing test
656.
// If false, all failing tests will be expanded
657.
collapse: true,
658.
659.
// By default, scroll to top of the page when suite is done
660.
scrolltop: true,
661.
662.
// Depth up-to which object will be dumped
663.
maxDepth: 5,
664.
665.
// When enabled, all tests must call expect()
666.
requireExpects: false,
667.
668.
// Placeholder for user-configurable form-exposed URL parameters
669.
urlConfig: [],
670.
671.
// Set of all modules.
672.
modules: [],
673.
674.
// The first unnamed module
675.
currentModule: {
676.
name: "",
677.
tests: [],
678.
childModules: [],
679.
testsRun: 0,
680.
unskippedTestsRun: 0,
681.
hooks: {
682.
before: [],
683.
beforeEach: [],
684.
afterEach: [],
685.
after: []
686.
}
687.
},
688.
689.
callbacks: {},
690.
691.
// The storage module to use for reordering tests
692.
storage: localSessionStorage
693.
};
694.
695.
// take a predefined QUnit.config and extend the defaults
696.
var globalConfig = window$1 && window$1.QUnit && window$1.QUnit.config;
697.
698.
// only extend the global config if there is no QUnit overload
699.
if (window$1 && window$1.QUnit && !window$1.QUnit.version) {
700.
extend(config, globalConfig);
701.
}
702.
703.
// Push a loose unnamed module to the modules collection
704.
config.modules.push(config.currentModule);
705.
706.
// Based on jsDump by Ariel Flesler
707.
// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
708.
var dump = (function () {
709.
function quote(str) {
710.
return "\"" + str.toString().replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\"";
711.
}
712.
function literal(o) {
713.
return o + "";
714.
}
715.
function join(pre, arr, post) {
716.
var s = dump.separator(),
717.
base = dump.indent(),
718.
inner = dump.indent(1);
719.
if (arr.join) {
720.
arr = arr.join("," + s + inner);
721.
}
722.
if (!arr) {
723.
return pre + post;
724.
}
725.
return [pre, inner + arr, base + post].join(s);
726.
}
727.
function array(arr, stack) {
728.
var i = arr.length,
729.
ret = new Array(i);
730.
731.
if (dump.maxDepth && dump.depth > dump.maxDepth) {
732.
return "[object Array]";
733.
}
734.
735.
this.up();
736.
while (i--) {
737.
ret[i] = this.parse(arr[i], undefined, stack);
738.
}
739.
this.down();
740.
return join("[", ret, "]");
741.
}
742.
743.
function isArray(obj) {
744.
return (
745.
746.
//Native Arrays
747.
toString.call(obj) === "[object Array]" ||
748.
749.
// NodeList objects
750.
typeof obj.length === "number" && obj.item !== undefined && (obj.length ? obj.item(0) === obj[0] : obj.item(0) === null && obj[0] === undefined)
751.
);
752.
}
753.
754.
var reName = /^function (\w+)/,
755.
dump = {
756.
757.
// The objType is used mostly internally, you can fix a (custom) type in advance
758.
parse: function parse(obj, objType, stack) {
759.
stack = stack || [];
760.
var res,
761.
parser,
762.
parserType,
763.
objIndex = stack.indexOf(obj);
764.
765.
if (objIndex !== -1) {
766.
return "recursion(" + (objIndex - stack.length) + ")";
767.
}
768.
769.
objType = objType || this.typeOf(obj);
770.
parser = this.parsers[objType];
771.
parserType = typeof parser === "undefined" ? "undefined" : _typeof(parser);
772.
773.
if (parserType === "function") {
774.
stack.push(obj);
775.
res = parser.call(this, obj, stack);
776.
stack.pop();
777.
return res;
778.
}
779.
return parserType === "string" ? parser : this.parsers.error;
780.
},
781.
typeOf: function typeOf(obj) {
782.
var type;
783.
784.
if (obj === null) {
785.
type = "null";
786.
} else if (typeof obj === "undefined") {
787.
type = "undefined";
788.
} else if (is("regexp", obj)) {
789.
type = "regexp";
790.
} else if (is("date", obj)) {
791.
type = "date";
792.
} else if (is("function", obj)) {
793.
type = "function";
794.
} else if (obj.setInterval !== undefined && obj.document !== undefined && obj.nodeType === undefined) {
795.
type = "window";
796.
} else if (obj.nodeType === 9) {
797.
type = "document";
798.
} else if (obj.nodeType) {
799.
type = "node";
800.
} else if (isArray(obj)) {
801.
type = "array";
802.
} else if (obj.constructor === Error.prototype.constructor) {
803.
type = "error";
804.
} else {
805.
type = typeof obj === "undefined" ? "undefined" : _typeof(obj);
806.
}
807.
return type;
808.
},
809.
810.
separator: function separator() {
811.
if (this.multiline) {
812.
return this.HTML ? "<br />" : "\n";
813.
} else {
814.
return this.HTML ? " " : " ";
815.
}
816.
},
817.
818.
// Extra can be a number, shortcut for increasing-calling-decreasing
819.
indent: function indent(extra) {
820.
if (!this.multiline) {
821.
return "";
822.
}
823.
var chr = this.indentChar;
824.
if (this.HTML) {
825.
chr = chr.replace(/\t/g, " ").replace(/ /g, " ");
826.
}
827.
return new Array(this.depth + (extra || 0)).join(chr);
828.
},
829.
up: function up(a) {
830.
this.depth += a || 1;
831.
},
832.
down: function down(a) {
833.
this.depth -= a || 1;
834.
},
835.
setParser: function setParser(name, parser) {
836.
this.parsers[name] = parser;
837.
},
838.
839.
// The next 3 are exposed so you can use them
840.
quote: quote,
841.
literal: literal,
842.
join: join,
843.
depth: 1,
844.
maxDepth: config.maxDepth,
845.
846.
// This is the list of parsers, to modify them, use dump.setParser
847.
parsers: {
848.
window: "[Window]",
849.
document: "[Document]",
850.
error: function error(_error) {
851.
return "Error(\"" + _error.message + "\")";
852.
},
853.
unknown: "[Unknown]",
854.
"null": "null",
855.
"undefined": "undefined",
856.
"function": function _function(fn) {
857.
var ret = "function",
858.
859.
860.
// Functions never have name in IE
861.
name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
862.
863.
if (name) {
864.
ret += " " + name;
865.
}
866.
ret += "(";
867.
868.
ret = [ret, dump.parse(fn, "functionArgs"), "){"].join("");
869.
return join(ret, dump.parse(fn, "functionCode"), "}");
870.
},
871.
array: array,
872.
nodelist: array,
873.
"arguments": array,
874.
object: function object(map, stack) {
875.
var keys,
876.
key,
877.
val,
878.
i,
879.
nonEnumerableProperties,
880.
ret = [];
881.
882.
if (dump.maxDepth && dump.depth > dump.maxDepth) {
883.
return "[object Object]";
884.
}
885.
886.
dump.up();
887.
keys = [];
888.
for (key in map) {
889.
keys.push(key);
890.
}
891.
892.
// Some properties are not always enumerable on Error objects.
893.
nonEnumerableProperties = ["message", "name"];
894.
for (i in nonEnumerableProperties) {
895.
key = nonEnumerableProperties[i];
896.
if (key in map && !inArray(key, keys)) {
897.
keys.push(key);
898.
}
899.
}
900.
keys.sort();
901.
for (i = 0; i < keys.length; i++) {
902.
key = keys[i];
903.
val = map[key];
904.
ret.push(dump.parse(key, "key") + ": " + dump.parse(val, undefined, stack));
905.
}
906.
dump.down();
907.
return join("{", ret, "}");
908.
},
909.
node: function node(_node) {
910.
var len,
911.
i,
912.
val,
913.
open = dump.HTML ? "<" : "<",
914.
close = dump.HTML ? ">" : ">",
915.
tag = _node.nodeName.toLowerCase(),
916.
ret = open + tag,
917.
attrs = _node.attributes;
918.
919.
if (attrs) {
920.
for (i = 0, len = attrs.length; i < len; i++) {
921.
val = attrs[i].nodeValue;
922.
923.
// IE6 includes all attributes in .attributes, even ones not explicitly
924.
// set. Those have values like undefined, null, 0, false, "" or
925.
// "inherit".
926.
if (val && val !== "inherit") {
927.
ret += " " + attrs[i].nodeName + "=" + dump.parse(val, "attribute");
928.
}
929.
}
930.
}
931.
ret += close;
932.
933.
// Show content of TextNode or CDATASection
934.
if (_node.nodeType === 3 || _node.nodeType === 4) {
935.
ret += _node.nodeValue;
936.
}
937.
938.
return ret + open + "/" + tag + close;
939.
},
940.
941.
// Function calls it internally, it's the arguments part of the function
942.
functionArgs: function functionArgs(fn) {
943.
var args,
944.
l = fn.length;
945.
946.
if (!l) {
947.
return "";
948.
}
949.
950.
args = new Array(l);
951.
while (l--) {
952.
953.
// 97 is 'a'
954.
args[l] = String.fromCharCode(97 + l);
955.
}
956.
return " " + args.join(", ") + " ";
957.
},
958.
959.
// Object calls it internally, the key part of an item in a map
960.
key: quote,
961.
962.
// Function calls it internally, it's the content of the function
963.
functionCode: "[code]",
964.
965.
// Node calls it internally, it's a html attribute value
966.
attribute: quote,
967.
string: quote,
968.
date: quote,
969.
regexp: literal,
970.
number: literal,
971.
"boolean": literal,
972.
symbol: function symbol(sym) {
973.
return sym.toString();
974.
}
975.
},
976.
977.
// If true, entities are escaped ( <, >, \t, space and \n )
978.
HTML: false,
979.
980.
// Indentation unit
981.
indentChar: " ",
982.
983.
// If true, items in a collection, are separated by a \n, else just a space.
984.
multiline: true
985.
};
986.
987.
return dump;
988.
})();
989.
990.
var SuiteReport = function () {
991.
function SuiteReport(name, parentSuite) {
992.
classCallCheck(this, SuiteReport);
993.
994.
this.name = name;
995.
this.fullName = parentSuite ? parentSuite.fullName.concat(name) : [];
996.
997.
this.tests = [];
998.
this.childSuites = [];
999.
1000.
if (parentSuite) {
1001.
parentSuite.pushChildSuite(this);
1002.
}
1003.
}
1004.
1005.
createClass(SuiteReport, [{
1006.
key: "start",
1007.
value: function start(recordTime) {
1008.
if (recordTime) {
1009.
this._startTime = performanceNow();
1010.
1011.
if (performance) {
1012.
var suiteLevel = this.fullName.length;
1013.
performance.mark("qunit_suite_" + suiteLevel + "_start");
1014.
}
1015.
}
1016.
1017.
return {
1018.
name: this.name,
1019.
fullName: this.fullName.slice(),
1020.
tests: this.tests.map(function (test) {
1021.
return test.start();
1022.
}),
1023.
childSuites: this.childSuites.map(function (suite) {
1024.
return suite.start();
1025.
}),
1026.
testCounts: {
1027.
total: this.getTestCounts().total
1028.
}
1029.
};
1030.
}
1031.
}, {
1032.
key: "end",
1033.
value: function end(recordTime) {
1034.
if (recordTime) {
1035.
this._endTime = performanceNow();
1036.
1037.
if (performance) {
1038.
var suiteLevel = this.fullName.length;
1039.
performance.mark("qunit_suite_" + suiteLevel + "_end");
1040.
1041.
var suiteName = this.fullName.join(" – ");
1042.
1043.
measure(suiteLevel === 0 ? "QUnit Test Run" : "QUnit Test Suite: " + suiteName, "qunit_suite_" + suiteLevel + "_start", "qunit_suite_" + suiteLevel + "_end");
1044.
}
1045.
}
1046.
1047.
return {
1048.
name: this.name,
1049.
fullName: this.fullName.slice(),
1050.
tests: this.tests.map(function (test) {
1051.
return test.end();
1052.
}),
1053.
childSuites: this.childSuites.map(function (suite) {
1054.
return suite.end();
1055.
}),
1056.
testCounts: this.getTestCounts(),
1057.
runtime: this.getRuntime(),
1058.
status: this.getStatus()
1059.
};
1060.
}
1061.
}, {
1062.
key: "pushChildSuite",
1063.
value: function pushChildSuite(suite) {
1064.
this.childSuites.push(suite);
1065.
}
1066.
}, {
1067.
key: "pushTest",
1068.
value: function pushTest(test) {
1069.
this.tests.push(test);
1070.
}
1071.
}, {
1072.
key: "getRuntime",
1073.
value: function getRuntime() {
1074.
return this._endTime - this._startTime;
1075.
}
1076.
}, {
1077.
key: "getTestCounts",
1078.
value: function getTestCounts() {
1079.
var counts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { passed: 0, failed: 0, skipped: 0, todo: 0, total: 0 };
1080.
1081.
counts = this.tests.reduce(function (counts, test) {
1082.
if (test.valid) {
1083.
counts[test.getStatus()]++;
1084.
counts.total++;
1085.
}
1086.
1087.
return counts;
1088.
}, counts);
1089.
1090.
return this.childSuites.reduce(function (counts, suite) {
1091.
return suite.getTestCounts(counts);
1092.
}, counts);
1093.
}
1094.
}, {
1095.
key: "getStatus",
1096.
value: function getStatus() {
1097.
var _getTestCounts = this.getTestCounts(),
1098.
total = _getTestCounts.total,
1099.
failed = _getTestCounts.failed,
1100.
skipped = _getTestCounts.skipped,
1101.
todo = _getTestCounts.todo;
1102.
1103.
if (failed) {
1104.
return "failed";
1105.
} else {
1106.
if (skipped === total) {
1107.
return "skipped";
1108.
} else if (todo === total) {
1109.
return "todo";
1110.
} else {
1111.
return "passed";
1112.
}
1113.
}
1114.
}
1115.
}]);
1116.
return SuiteReport;
1117.
}();
1118.
1119.
var focused = false;
1120.
1121.
var moduleStack = [];
1122.
1123.
function isParentModuleInQueue() {
1124.
var modulesInQueue = config.modules.map(function (module) {
1125.
return module.moduleId;
1126.
});
1127.
return moduleStack.some(function (module) {
1128.
return modulesInQueue.includes(module.moduleId);
1129.
});
1130.
}
1131.
1132.
function createModule(name, testEnvironment, modifiers) {
1133.
var parentModule = moduleStack.length ? moduleStack.slice(-1)[0] : null;
1134.
var moduleName = parentModule !== null ? [parentModule.name, name].join(" > ") : name;
1135.
var parentSuite = parentModule ? parentModule.suiteReport : globalSuite;
1136.
1137.
var skip = parentModule !== null && parentModule.skip || modifiers.skip;
1138.
var todo = parentModule !== null && parentModule.todo || modifiers.todo;
1139.
1140.
var module = {
1141.
name: moduleName,
1142.
parentModule: parentModule,
1143.
tests: [],
1144.
moduleId: generateHash(moduleName),
1145.
testsRun: 0,
1146.
unskippedTestsRun: 0,
1147.
childModules: [],
1148.
suiteReport: new SuiteReport(name, parentSuite),
1149.
1150.
// Pass along `skip` and `todo` properties from parent module, in case
1151.
// there is one, to childs. And use own otherwise.
1152.
// This property will be used to mark own tests and tests of child suites
1153.
// as either `skipped` or `todo`.
1154.
skip: skip,
1155.
todo: skip ? false : todo
1156.
};
1157.
1158.
var env = {};
1159.
if (parentModule) {
1160.
parentModule.childModules.push(module);
1161.
extend(env, parentModule.testEnvironment);
1162.
}
1163.
extend(env, testEnvironment);
1164.
module.testEnvironment = env;
1165.
1166.
config.modules.push(module);
1167.
return module;
1168.
}
1169.
1170.
function processModule(name, options, executeNow) {
1171.
var modifiers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
1172.
1173.
if (objectType(options) === "function") {
1174.
executeNow = options;
1175.
options = undefined;
1176.
}
1177.
1178.
var module = createModule(name, options, modifiers);
1179.
1180.
// Move any hooks to a 'hooks' object
1181.
var testEnvironment = module.testEnvironment;
1182.
var hooks = module.hooks = {};
1183.
1184.
setHookFromEnvironment(hooks, testEnvironment, "before");
1185.
setHookFromEnvironment(hooks, testEnvironment, "beforeEach");
1186.
setHookFromEnvironment(hooks, testEnvironment, "afterEach");
1187.
setHookFromEnvironment(hooks, testEnvironment, "after");
1188.
1189.
var moduleFns = {
1190.
before: setHookFunction(module, "before"),
1191.
beforeEach: setHookFunction(module, "beforeEach"),
1192.
afterEach: setHookFunction(module, "afterEach"),
1193.
after: setHookFunction(module, "after")
1194.
};
1195.
1196.
var currentModule = config.currentModule;
1197.
if (objectType(executeNow) === "function") {
1198.
moduleStack.push(module);
1199.
config.currentModule = module;
1200.
executeNow.call(module.testEnvironment, moduleFns);
1201.
moduleStack.pop();
1202.
module = module.parentModule || currentModule;
1203.
}
1204.
1205.
config.currentModule = module;
1206.
1207.
function setHookFromEnvironment(hooks, environment, name) {
1208.
var potentialHook = environment[name];
1209.
hooks[name] = typeof potentialHook === "function" ? [potentialHook] : [];
1210.
delete environment[name];
1211.
}
1212.
1213.
function setHookFunction(module, hookName) {
1214.
return function setHook(callback) {
1215.
module.hooks[hookName].push(callback);
1216.
};
1217.
}
1218.
}
1219.
1220.
function module$1(name, options, executeNow) {
1221.
if (focused && !isParentModuleInQueue()) {
1222.
return;
1223.
}
1224.
1225.
processModule(name, options, executeNow);
1226.
}
1227.
1228.
module$1.only = function () {
1229.
if (!focused) {
1230.
config.modules.length = 0;
1231.
config.queue.length = 0;
1232.
}
1233.
1234.
processModule.apply(undefined, arguments);
1235.
1236.
focused = true;
1237.
};
1238.
1239.
module$1.skip = function (name, options, executeNow) {
1240.
if (focused) {
1241.
return;
1242.
}
1243.
1244.
processModule(name, options, executeNow, { skip: true });
1245.
};
1246.
1247.
module$1.todo = function (name, options, executeNow) {
1248.
if (focused) {
1249.
return;
1250.
}
1251.
1252.
processModule(name, options, executeNow, { todo: true });
1253.
};
1254.
1255.
var LISTENERS = Object.create(null);
1256.
var SUPPORTED_EVENTS = ["runStart", "suiteStart", "testStart", "assertion", "testEnd", "suiteEnd", "runEnd"];
1257.
1258.
/**
1259.
* Emits an event with the specified data to all currently registered listeners.
1260.
* Callbacks will fire in the order in which they are registered (FIFO). This
1261.
* function is not exposed publicly; it is used by QUnit internals to emit
1262.
* logging events.
1263.
*
1264.
* @private
1265.
* @method emit
1266.
* @param {String} eventName
1267.
* @param {Object} data
1268.
* @return {Void}
1269.
*/
1270.
function emit(eventName, data) {
1271.
if (objectType(eventName) !== "string") {
1272.
throw new TypeError("eventName must be a string when emitting an event");
1273.
}
1274.
1275.
// Clone the callbacks in case one of them registers a new callback
1276.
var originalCallbacks = LISTENERS[eventName];
1277.
var callbacks = originalCallbacks ? [].concat(toConsumableArray(originalCallbacks)) : [];
1278.
1279.
for (var i = 0; i < callbacks.length; i++) {
1280.
callbacks[i](data);
1281.
}
1282.
}
1283.
1284.
/**
1285.
* Registers a callback as a listener to the specified event.
1286.
*
1287.
* @public
1288.
* @method on
1289.
* @param {String} eventName
1290.
* @param {Function} callback
1291.
* @return {Void}
1292.
*/
1293.
function on(eventName, callback) {
1294.
if (objectType(eventName) !== "string") {
1295.
throw new TypeError("eventName must be a string when registering a listener");
1296.
} else if (!inArray(eventName, SUPPORTED_EVENTS)) {
1297.
var events = SUPPORTED_EVENTS.join(", ");
1298.
throw new Error("\"" + eventName + "\" is not a valid event; must be one of: " + events + ".");
1299.
} else if (objectType(callback) !== "function") {
1300.
throw new TypeError("callback must be a function when registering a listener");
1301.
}
1302.
1303.
if (!LISTENERS[eventName]) {
1304.
LISTENERS[eventName] = [];
1305.
}
1306.
1307.
// Don't register the same callback more than once
1308.
if (!inArray(callback, LISTENERS[eventName])) {
1309.
LISTENERS[eventName].push(callback);
1310.
}
1311.
}
1312.
1313.
function objectOrFunction(x) {
1314.
var type = typeof x === 'undefined' ? 'undefined' : _typeof(x);
1315.
return x !== null && (type === 'object' || type === 'function');
1316.
}
1317.
1318.
function isFunction(x) {
1319.
return typeof x === 'function';
1320.
}
1321.
1322.
1323.
1324.
var _isArray = void 0;
1325.
if (Array.isArray) {
1326.
_isArray = Array.isArray;
1327.
} else {
1328.
_isArray = function _isArray(x) {
1329.
return Object.prototype.toString.call(x) === '[object Array]';
1330.
};
1331.
}
1332.
1333.
var isArray = _isArray;
1334.
1335.
var len = 0;
1336.
var vertxNext = void 0;
1337.
var customSchedulerFn = void 0;
1338.
1339.
var asap = function asap(callback, arg) {
1340.
queue[len] = callback;
1341.
queue[len + 1] = arg;
1342.
len += 2;
1343.
if (len === 2) {
1344.
// If len is 2, that means that we need to schedule an async flush.
1345.
// If additional callbacks are queued before the queue is flushed, they
1346.
// will be processed by this flush that we are scheduling.
1347.
if (customSchedulerFn) {
1348.
customSchedulerFn(flush);
1349.
} else {
1350.
scheduleFlush();
1351.
}
1352.
}
1353.
};
1354.
1355.
function setScheduler(scheduleFn) {
1356.
customSchedulerFn = scheduleFn;
1357.
}
1358.
1359.
function setAsap(asapFn) {
1360.
asap = asapFn;
1361.
}
1362.
1363.
var browserWindow = typeof window !== 'undefined' ? window : undefined;
1364.
var browserGlobal = browserWindow || {};
1365.
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
1366.
var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
1367.
1368.
// test for web worker but not in IE10
1369.
var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
1370.
1371.
// node
1372.
function useNextTick() {
1373.
// node version 0.10.x displays a deprecation warning when nextTick is used recursively
1374.
// see https://github.com/cujojs/when/issues/410 for details
1375.
return function () {
1376.
return process.nextTick(flush);
1377.
};
1378.
}
1379.
1380.
// vertx
1381.
function useVertxTimer() {
1382.
if (typeof vertxNext !== 'undefined') {
1383.
return function () {
1384.
vertxNext(flush);
1385.
};
1386.
}
1387.
1388.
return useSetTimeout();
1389.
}
1390.
1391.
function useMutationObserver() {
1392.
var iterations = 0;
1393.
var observer = new BrowserMutationObserver(flush);
1394.
var node = document.createTextNode('');
1395.
observer.observe(node, { characterData: true });
1396.
1397.
return function () {
1398.
node.data = iterations = ++iterations % 2;
1399.
};
1400.
}
1401.
1402.
// web worker
1403.
function useMessageChannel() {
1404.
var channel = new MessageChannel();
1405.
channel.port1.onmessage = flush;
1406.
return function () {
1407.
return channel.port2.postMessage(0);
1408.
};
1409.
}
1410.
1411.
function useSetTimeout() {
1412.
// Store setTimeout reference so es6-promise will be unaffected by
1413.
// other code modifying setTimeout (like sinon.useFakeTimers())
1414.
var globalSetTimeout = setTimeout;
1415.
return function () {
1416.
return globalSetTimeout(flush, 1);
1417.
};
1418.
}
1419.
1420.
var queue = new Array(1000);
1421.
function flush() {
1422.
for (var i = 0; i < len; i += 2) {
1423.
var callback = queue[i];
1424.
var arg = queue[i + 1];
1425.
1426.
callback(arg);
1427.
1428.
queue[i] = undefined;
1429.
queue[i + 1] = undefined;
1430.
}
1431.
1432.
len = 0;
1433.
}
1434.
1435.
function attemptVertx() {
1436.
try {
1437.
var vertx = Function('return this')().require('vertx');
1438.
vertxNext = vertx.runOnLoop || vertx.runOnContext;
1439.
return useVertxTimer();
1440.
} catch (e) {
1441.
return useSetTimeout();
1442.
}
1443.
}
1444.
1445.
var scheduleFlush = void 0;
1446.
// Decide what async method to use to triggering processing of queued callbacks:
1447.
if (isNode) {
1448.
scheduleFlush = useNextTick();
1449.
} else if (BrowserMutationObserver) {
1450.
scheduleFlush = useMutationObserver();
1451.
} else if (isWorker) {
1452.
scheduleFlush = useMessageChannel();
1453.
} else if (browserWindow === undefined && typeof require === 'function') {
1454.
scheduleFlush = attemptVertx();
1455.
} else {
1456.
scheduleFlush = useSetTimeout();
1457.
}
1458.
1459.
function then(onFulfillment, onRejection) {
1460.
var parent = this;
1461.
1462.
var child = new this.constructor(noop);
1463.
1464.
if (child[PROMISE_ID] === undefined) {
1465.
makePromise(child);
1466.
}
1467.
1468.
var _state = parent._state;
1469.
1470.
1471.
if (_state) {
1472.
var callback = arguments[_state - 1];
1473.
asap(function () {
1474.
return invokeCallback(_state, child, callback, parent._result);
1475.
});
1476.
} else {
1477.
subscribe(parent, child, onFulfillment, onRejection);
1478.
}
1479.
1480.
return child;
1481.
}
1482.
1483.
/**
1484.
`Promise.resolve` returns a promise that will become resolved with the
1485.
passed `value`. It is shorthand for the following:
1486.
1487.
```javascript
1488.
let promise = new Promise(function(resolve, reject){
1489.
resolve(1);
1490.
});
1491.
1492.
promise.then(function(value){
1493.
// value === 1
1494.
});
1495.
```
1496.
1497.
Instead of writing the above, your code now simply becomes the following:
1498.
1499.
```javascript
1500.
let promise = Promise.resolve(1);
1501.
1502.
promise.then(function(value){
1503.
// value === 1
1504.
});
1505.
```
1506.
1507.
@method resolve
1508.
@static
1509.
@param {Any} value value that the returned promise will be resolved with
1510.
Useful for tooling.
1511.
@return {Promise} a promise that will become fulfilled with the given
1512.
`value`
1513.
*/
1514.
function resolve$1(object) {
1515.
/*jshint validthis:true */
1516.
var Constructor = this;
1517.
1518.
if (object && (typeof object === 'undefined' ? 'undefined' : _typeof(object)) === 'object' && object.constructor === Constructor) {
1519.
return object;
1520.
}
1521.
1522.
var promise = new Constructor(noop);
1523.
resolve(promise, object);
1524.
return promise;
1525.
}
1526.
1527.
var PROMISE_ID = Math.random().toString(36).substring(2);
1528.
1529.
function noop() {}
1530.
1531.
var PENDING = void 0;
1532.
var FULFILLED = 1;
1533.
var REJECTED = 2;
1534.
1535.
function selfFulfillment() {
1536.
return new TypeError("You cannot resolve a promise with itself");
1537.
}
1538.
1539.
function cannotReturnOwn() {
1540.
return new TypeError('A promises callback cannot return that same promise.');
1541.
}
1542.
1543.
function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {
1544.
try {
1545.
then$$1.call(value, fulfillmentHandler, rejectionHandler);
1546.
} catch (e) {
1547.
return e;
1548.
}
1549.
}
1550.
1551.
function handleForeignThenable(promise, thenable, then$$1) {
1552.
asap(function (promise) {
1553.
var sealed = false;
1554.
var error = tryThen(then$$1, thenable, function (value) {
1555.
if (sealed) {
1556.
return;
1557.
}
1558.
sealed = true;
1559.
if (thenable !== value) {
1560.
resolve(promise, value);
1561.
} else {
1562.
fulfill(promise, value);
1563.
}
1564.
}, function (reason) {
1565.
if (sealed) {
1566.
return;
1567.
}
1568.
sealed = true;
1569.
1570.
reject(promise, reason);
1571.
}, 'Settle: ' + (promise._label || ' unknown promise'));
1572.
1573.
if (!sealed && error) {
1574.
sealed = true;
1575.
reject(promise, error);
1576.
}
1577.
}, promise);
1578.
}
1579.
1580.
function handleOwnThenable(promise, thenable) {
1581.
if (thenable._state === FULFILLED) {
1582.
fulfill(promise, thenable._result);
1583.
} else if (thenable._state === REJECTED) {
1584.
reject(promise, thenable._result);
1585.
} else {
1586.
subscribe(thenable, undefined, function (value) {
1587.
return resolve(promise, value);
1588.
}, function (reason) {
1589.
return reject(promise, reason);
1590.
});
1591.
}
1592.
}
1593.
1594.
function handleMaybeThenable(promise, maybeThenable, then$$1) {
1595.
if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {
1596.
handleOwnThenable(promise, maybeThenable);
1597.
} else {
1598.
if (then$$1 === undefined) {
1599.
fulfill(promise, maybeThenable);
1600.
} else if (isFunction(then$$1)) {
1601.
handleForeignThenable(promise, maybeThenable, then$$1);
1602.
} else {
1603.
fulfill(promise, maybeThenable);
1604.
}
1605.
}
1606.
}
1607.
1608.
function resolve(promise, value) {
1609.
if (promise === value) {
1610.
reject(promise, selfFulfillment());
1611.
} else if (objectOrFunction(value)) {
1612.
var then$$1 = void 0;
1613.
try {
1614.
then$$1 = value.then;
1615.
} catch (error) {
1616.
reject(promise, error);
1617.
return;
1618.
}
1619.
handleMaybeThenable(promise, value, then$$1);
1620.
} else {
1621.
fulfill(promise, value);
1622.
}
1623.
}
1624.
1625.
function publishRejection(promise) {
1626.
if (promise._onerror) {
1627.
promise._onerror(promise._result);
1628.
}
1629.
1630.
publish(promise);
1631.
}
1632.
1633.
function fulfill(promise, value) {
1634.
if (promise._state !== PENDING) {
1635.
return;
1636.
}
1637.
1638.
promise._result = value;
1639.
promise._state = FULFILLED;
1640.
1641.
if (promise._subscribers.length !== 0) {
1642.
asap(publish, promise);
1643.
}
1644.
}
1645.
1646.
function reject(promise, reason) {
1647.
if (promise._state !== PENDING) {
1648.
return;
1649.
}
1650.
promise._state = REJECTED;
1651.
promise._result = reason;
1652.
1653.
asap(publishRejection, promise);
1654.
}
1655.
1656.
function subscribe(parent, child, onFulfillment, onRejection) {
1657.
var _subscribers = parent._subscribers;
1658.
var length = _subscribers.length;
1659.
1660.
1661.
parent._onerror = null;
1662.
1663.
_subscribers[length] = child;
1664.
_subscribers[length + FULFILLED] = onFulfillment;
1665.
_subscribers[length + REJECTED] = onRejection;
1666.
1667.
if (length === 0 && parent._state) {
1668.
asap(publish, parent);
1669.
}
1670.
}
1671.
1672.
function publish(promise) {
1673.
var subscribers = promise._subscribers;
1674.
var settled = promise._state;
1675.
1676.
if (subscribers.length === 0) {
1677.
return;
1678.
}
1679.
1680.
var child = void 0,
1681.
callback = void 0,
1682.
detail = promise._result;
1683.
1684.
for (var i = 0; i < subscribers.length; i += 3) {
1685.
child = subscribers[i];
1686.
callback = subscribers[i + settled];
1687.
1688.
if (child) {
1689.
invokeCallback(settled, child, callback, detail);
1690.
} else {
1691.
callback(detail);
1692.
}
1693.
}
1694.
1695.
promise._subscribers.length = 0;
1696.
}
1697.
1698.
function invokeCallback(settled, promise, callback, detail) {
1699.
var hasCallback = isFunction(callback),
1700.
value = void 0,
1701.
error = void 0,
1702.
succeeded = true;
1703.
1704.
if (hasCallback) {
1705.
try {
1706.
value = callback(detail);
1707.
} catch (e) {
1708.
succeeded = false;
1709.
error = e;
1710.
}
1711.
1712.
if (promise === value) {
1713.
reject(promise, cannotReturnOwn());
1714.
return;
1715.
}
1716.
} else {
1717.
value = detail;
1718.
}
1719.
1720.
if (promise._state !== PENDING) {
1721.
// noop
1722.
} else if (hasCallback && succeeded) {
1723.
resolve(promise, value);
1724.
} else if (succeeded === false) {
1725.
reject(promise, error);
1726.
} else if (settled === FULFILLED) {
1727.
fulfill(promise, value);
1728.
} else if (settled === REJECTED) {
1729.
reject(promise, value);
1730.
}
1731.
}
1732.
1733.
function initializePromise(promise, resolver) {
1734.
try {
1735.
resolver(function resolvePromise(value) {
1736.
resolve(promise, value);
1737.
}, function rejectPromise(reason) {
1738.
reject(promise, reason);
1739.
});
1740.
} catch (e) {
1741.
reject(promise, e);
1742.
}
1743.
}
1744.
1745.
var id = 0;
1746.
function nextId() {
1747.
return id++;
1748.
}
1749.
1750.
function makePromise(promise) {
1751.
promise[PROMISE_ID] = id++;
1752.
promise._state = undefined;
1753.
promise._result = undefined;
1754.
promise._subscribers = [];
1755.
}
1756.
1757.
function validationError() {
1758.
return new Error('Array Methods must be provided an Array');
1759.
}
1760.
1761.
var Enumerator = function () {
1762.
function Enumerator(Constructor, input) {
1763.
classCallCheck(this, Enumerator);
1764.
1765.
this._instanceConstructor = Constructor;
1766.
this.promise = new Constructor(noop);
1767.
1768.
if (!this.promise[PROMISE_ID]) {
1769.
makePromise(this.promise);
1770.
}
1771.
1772.
if (isArray(input)) {
1773.
this.length = input.length;
1774.
this._remaining = input.length;
1775.
1776.
this._result = new Array(this.length);
1777.
1778.
if (this.length === 0) {
1779.
fulfill(this.promise, this._result);
1780.
} else {
1781.
this.length = this.length || 0;
1782.
this._enumerate(input);
1783.
if (this._remaining === 0) {
1784.
fulfill(this.promise, this._result);
1785.
}
1786.
}
1787.
} else {
1788.
reject(this.promise, validationError());
1789.
}
1790.
}
1791.
1792.
createClass(Enumerator, [{
1793.
key: '_enumerate',
1794.
value: function _enumerate(input) {
1795.
for (var i = 0; this._state === PENDING && i < input.length; i++) {
1796.
this._eachEntry(input[i], i);
1797.
}
1798.
}
1799.
}, {
1800.
key: '_eachEntry',
1801.
value: function _eachEntry(entry, i) {
1802.
var c = this._instanceConstructor;
1803.
var resolve$$1 = c.resolve;
1804.
1805.
1806.
if (resolve$$1 === resolve$1) {
1807.
var _then = void 0;
1808.
var error = void 0;
1809.
var didError = false;
1810.
try {
1811.
_then = entry.then;
1812.
} catch (e) {
1813.
didError = true;
1814.
error = e;
1815.
}
1816.
1817.
if (_then === then && entry._state !== PENDING) {
1818.
this._settledAt(entry._state, i, entry._result);
1819.
} else if (typeof _then !== 'function') {
1820.
this._remaining--;
1821.
this._result[i] = entry;
1822.
} else if (c === Promise$2) {
1823.
var promise = new c(noop);
1824.
if (didError) {
1825.
reject(promise, error);
1826.
} else {
1827.
handleMaybeThenable(promise, entry, _then);
1828.
}
1829.
this._willSettleAt(promise, i);
1830.
} else {
1831.
this._willSettleAt(new c(function (resolve$$1) {
1832.
return resolve$$1(entry);
1833.
}), i);
1834.
}
1835.
} else {
1836.
this._willSettleAt(resolve$$1(entry), i);
1837.
}
1838.
}
1839.
}, {
1840.
key: '_settledAt',
1841.
value: function _settledAt(state, i, value) {
1842.
var promise = this.promise;
1843.
1844.
1845.
if (promise._state === PENDING) {
1846.
this._remaining--;
1847.
1848.
if (state === REJECTED) {
1849.
reject(promise, value);
1850.
} else {
1851.
this._result[i] = value;
1852.
}
1853.
}
1854.
1855.
if (this._remaining === 0) {
1856.
fulfill(promise, this._result);
1857.
}
1858.
}
1859.
}, {
1860.
key: '_willSettleAt',
1861.
value: function _willSettleAt(promise, i) {
1862.
var enumerator = this;
1863.
1864.
subscribe(promise, undefined, function (value) {
1865.
return enumerator._settledAt(FULFILLED, i, value);
1866.
}, function (reason) {
1867.
return enumerator._settledAt(REJECTED, i, reason);
1868.
});
1869.
}
1870.
}]);
1871.
return Enumerator;
1872.
}();
1873.
1874.
/**
1875.
`Promise.all` accepts an array of promises, and returns a new promise which
1876.
is fulfilled with an array of fulfillment values for the passed promises, or
1877.
rejected with the reason of the first passed promise to be rejected. It casts all
1878.
elements of the passed iterable to promises as it runs this algorithm.
1879.
1880.
Example:
1881.
1882.
```javascript
1883.
let promise1 = resolve(1);
1884.
let promise2 = resolve(2);
1885.
let promise3 = resolve(3);
1886.
let promises = [ promise1, promise2, promise3 ];
1887.
1888.
Promise.all(promises).then(function(array){
1889.
// The array here would be [ 1, 2, 3 ];
1890.
});
1891.
```
1892.
1893.
If any of the `promises` given to `all` are rejected, the first promise
1894.
that is rejected will be given as an argument to the returned promises's
1895.
rejection handler. For example:
1896.
1897.
Example:
1898.
1899.
```javascript
1900.
let promise1 = resolve(1);
1901.
let promise2 = reject(new Error("2"));
1902.
let promise3 = reject(new Error("3"));
1903.
let promises = [ promise1, promise2, promise3 ];
1904.
1905.
Promise.all(promises).then(function(array){
1906.
// Code here never runs because there are rejected promises!
1907.
}, function(error) {
1908.
// error.message === "2"
1909.
});
1910.
```
1911.
1912.
@method all
1913.
@static
1914.
@param {Array} entries array of promises
1915.
@param {String} label optional string for labeling the promise.
1916.
Useful for tooling.
1917.
@return {Promise} promise that is fulfilled when all `promises` have been
1918.
fulfilled, or rejected if any of them become rejected.
1919.
@static
1920.
*/
1921.
function all(entries) {
1922.
return new Enumerator(this, entries).promise;
1923.
}
1924.
1925.
/**
1926.
`Promise.race` returns a new promise which is settled in the same way as the
1927.
first passed promise to settle.
1928.
1929.
Example:
1930.
1931.
```javascript
1932.
let promise1 = new Promise(function(resolve, reject){
1933.
setTimeout(function(){
1934.
resolve('promise 1');
1935.
}, 200);
1936.
});
1937.
1938.
let promise2 = new Promise(function(resolve, reject){
1939.
setTimeout(function(){
1940.
resolve('promise 2');
1941.
}, 100);
1942.
});
1943.
1944.
Promise.race([promise1, promise2]).then(function(result){
1945.
// result === 'promise 2' because it was resolved before promise1
1946.
// was resolved.
1947.
});
1948.
```
1949.
1950.
`Promise.race` is deterministic in that only the state of the first
1951.
settled promise matters. For example, even if other promises given to the
1952.
`promises` array argument are resolved, but the first settled promise has
1953.
become rejected before the other promises became fulfilled, the returned
1954.
promise will become rejected:
1955.
1956.
```javascript
1957.
let promise1 = new Promise(function(resolve, reject){
1958.
setTimeout(function(){
1959.
resolve('promise 1');
1960.
}, 200);
1961.
});
1962.
1963.
let promise2 = new Promise(function(resolve, reject){
1964.
setTimeout(function(){
1965.
reject(new Error('promise 2'));
1966.
}, 100);
1967.
});
1968.
1969.
Promise.race([promise1, promise2]).then(function(result){
1970.
// Code here never runs
1971.
}, function(reason){
1972.
// reason.message === 'promise 2' because promise 2 became rejected before
1973.
// promise 1 became fulfilled
1974.
});
1975.
```
1976.
1977.
An example real-world use case is implementing timeouts:
1978.
1979.
```javascript
1980.
Promise.race([ajax('foo.json'), timeout(5000)])
1981.
```
1982.
1983.
@method race
1984.
@static
1985.
@param {Array} promises array of promises to observe
1986.
Useful for tooling.
1987.
@return {Promise} a promise which settles in the same way as the first passed
1988.
promise to settle.
1989.
*/
1990.
function race(entries) {
1991.
/*jshint validthis:true */
1992.
var Constructor = this;
1993.
1994.
if (!isArray(entries)) {
1995.
return new Constructor(function (_, reject) {
1996.
return reject(new TypeError('You must pass an array to race.'));
1997.
});
1998.
} else {
1999.
return new Constructor(function (resolve, reject) {
2000.
var length = entries.length;
2001.
for (var i = 0; i < length; i++) {
2002.
Constructor.resolve(entries[i]).then(resolve, reject);
2003.
}
2004.
});
2005.
}
2006.
}
2007.
2008.
/**
2009.
`Promise.reject` returns a promise rejected with the passed `reason`.
2010.
It is shorthand for the following:
2011.
2012.
```javascript
2013.
let promise = new Promise(function(resolve, reject){
2014.
reject(new Error('WHOOPS'));
2015.
});
2016.
2017.
promise.then(function(value){
2018.
// Code here doesn't run because the promise is rejected!
2019.
}, function(reason){
2020.
// reason.message === 'WHOOPS'
2021.
});
2022.
```
2023.
2024.
Instead of writing the above, your code now simply becomes the following:
2025.
2026.
```javascript
2027.
let promise = Promise.reject(new Error('WHOOPS'));
2028.
2029.
promise.then(function(value){
2030.
// Code here doesn't run because the promise is rejected!
2031.
}, function(reason){
2032.
// reason.message === 'WHOOPS'
2033.
});
2034.
```
2035.
2036.
@method reject
2037.
@static
2038.
@param {Any} reason value that the returned promise will be rejected with.
2039.
Useful for tooling.
2040.
@return {Promise} a promise rejected with the given `reason`.
2041.
*/
2042.
function reject$1(reason) {
2043.
/*jshint validthis:true */
2044.
var Constructor = this;
2045.
var promise = new Constructor(noop);
2046.
reject(promise, reason);
2047.
return promise;
2048.
}
2049.
2050.
function needsResolver() {
2051.
throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
2052.
}
2053.
2054.
function needsNew() {
2055.
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
2056.
}
2057.
2058.
/**
2059.
Promise objects represent the eventual result of an asynchronous operation. The
2060.
primary way of interacting with a promise is through its `then` method, which
2061.
registers callbacks to receive either a promise's eventual value or the reason
2062.
why the promise cannot be fulfilled.
2063.
2064.
Terminology
2065.
-----------
2066.
2067.
- `promise` is an object or function with a `then` method whose behavior conforms to this specification.
2068.
- `thenable` is an object or function that defines a `then` method.
2069.
- `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
2070.
- `exception` is a value that is thrown using the throw statement.
2071.
- `reason` is a value that indicates why a promise was rejected.
2072.
- `settled` the final resting state of a promise, fulfilled or rejected.
2073.
2074.
A promise can be in one of three states: pending, fulfilled, or rejected.
2075.
2076.
Promises that are fulfilled have a fulfillment value and are in the fulfilled
2077.
state. Promises that are rejected have a rejection reason and are in the
2078.
rejected state. A fulfillment value is never a thenable.
2079.
2080.
Promises can also be said to *resolve* a value. If this value is also a
2081.
promise, then the original promise's settled state will match the value's
2082.
settled state. So a promise that *resolves* a promise that rejects will
2083.
itself reject, and a promise that *resolves* a promise that fulfills will
2084.
itself fulfill.
2085.
2086.
2087.
Basic Usage:
2088.
------------
2089.
2090.
```js
2091.
let promise = new Promise(function(resolve, reject) {
2092.
// on success
2093.
resolve(value);
2094.
2095.
// on failure
2096.
reject(reason);
2097.
});
2098.
2099.
promise.then(function(value) {
2100.
// on fulfillment
2101.
}, function(reason) {
2102.
// on rejection
2103.
});
2104.
```
2105.
2106.
Advanced Usage:
2107.
---------------
2108.
2109.
Promises shine when abstracting away asynchronous interactions such as
2110.
`XMLHttpRequest`s.
2111.
2112.
```js
2113.
function getJSON(url) {
2114.
return new Promise(function(resolve, reject){
2115.
let xhr = new XMLHttpRequest();
2116.
2117.
xhr.open('GET', url);
2118.
xhr.onreadystatechange = handler;
2119.
xhr.responseType = 'json';
2120.
xhr.setRequestHeader('Accept', 'application/json');
2121.
xhr.send();
2122.
2123.
function handler() {
2124.
if (this.readyState === this.DONE) {
2125.
if (this.status === 200) {
2126.
resolve(this.response);
2127.
} else {
2128.
reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
2129.
}
2130.
}
2131.
};
2132.
});
2133.
}
2134.
2135.
getJSON('/posts.json').then(function(json) {
2136.
// on fulfillment
2137.
}, function(reason) {
2138.
// on rejection
2139.
});
2140.
```
2141.
2142.
Unlike callbacks, promises are great composable primitives.
2143.
2144.
```js
2145.
Promise.all([
2146.
getJSON('/posts'),
2147.
getJSON('/comments')
2148.
]).then(function(values){
2149.
values[0] // => postsJSON
2150.
values[1] // => commentsJSON
2151.
2152.
return values;
2153.
});
2154.
```
2155.
2156.
@class Promise
2157.
@param {Function} resolver
2158.
Useful for tooling.
2159.
@constructor
2160.
*/
2161.
2162.
var Promise$2 = function () {
2163.
function Promise(resolver) {
2164.
classCallCheck(this, Promise);
2165.
2166.
this[PROMISE_ID] = nextId();
2167.
this._result = this._state = undefined;
2168.
this._subscribers = [];
2169.
2170.
if (noop !== resolver) {
2171.
typeof resolver !== 'function' && needsResolver();
2172.
this instanceof Promise ? initializePromise(this, resolver) : needsNew();
2173.
}
2174.
}
2175.
2176.
/**
2177.
The primary way of interacting with a promise is through its `then` method,
2178.
which registers callbacks to receive either a promise's eventual value or the
2179.
reason why the promise cannot be fulfilled.
2180.
```js
2181.
findUser().then(function(user){
2182.
// user is available
2183.
}, function(reason){
2184.
// user is unavailable, and you are given the reason why
2185.
});
2186.
```
2187.
Chaining
2188.
--------
2189.
The return value of `then` is itself a promise. This second, 'downstream'
2190.
promise is resolved with the return value of the first promise's fulfillment
2191.
or rejection handler, or rejected if the handler throws an exception.
2192.
```js
2193.
findUser().then(function (user) {
2194.
return user.name;
2195.
}, function (reason) {
2196.
return 'default name';
2197.
}).then(function (userName) {
2198.
// If `findUser` fulfilled, `userName` will be the user's name, otherwise it
2199.
// will be `'default name'`
2200.
});
2201.
findUser().then(function (user) {
2202.
throw new Error('Found user, but still unhappy');
2203.
}, function (reason) {
2204.
throw new Error('`findUser` rejected and we're unhappy');
2205.
}).then(function (value) {
2206.
// never reached
2207.
}, function (reason) {
2208.
// if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
2209.
// If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
2210.
});
2211.
```
2212.
If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
2213.
```js
2214.
findUser().then(function (user) {
2215.
throw new PedagogicalException('Upstream error');
2216.
}).then(function (value) {
2217.
// never reached
2218.
}).then(function (value) {
2219.
// never reached
2220.
}, function (reason) {
2221.
// The `PedgagocialException` is propagated all the way down to here
2222.
});
2223.
```
2224.
Assimilation
2225.
------------
2226.
Sometimes the value you want to propagate to a downstream promise can only be
2227.
retrieved asynchronously. This can be achieved by returning a promise in the
2228.
fulfillment or rejection handler. The downstream promise will then be pending
2229.
until the returned promise is settled. This is called *assimilation*.
2230.
```js
2231.
findUser().then(function (user) {
2232.
return findCommentsByAuthor(user);
2233.
}).then(function (comments) {
2234.
// The user's comments are now available
2235.
});
2236.
```
2237.
If the assimliated promise rejects, then the downstream promise will also reject.
2238.
```js
2239.
findUser().then(function (user) {
2240.
return findCommentsByAuthor(user);
2241.
}).then(function (comments) {
2242.
// If `findCommentsByAuthor` fulfills, we'll have the value here
2243.
}, function (reason) {
2244.
// If `findCommentsByAuthor` rejects, we'll have the reason here
2245.
});
2246.
```
2247.
Simple Example
2248.
--------------
2249.
Synchronous Example
2250.
```javascript
2251.
let result;
2252.
try {
2253.
result = findResult();
2254.
// success
2255.
} catch(reason) {
2256.
// failure
2257.
}
2258.
```
2259.
Errback Example
2260.
```js
2261.
findResult(function(result, err){
2262.
if (err) {
2263.
// failure
2264.
} else {
2265.
// success
2266.
}
2267.
});
2268.
```
2269.
Promise Example;
2270.
```javascript
2271.
findResult().then(function(result){
2272.
// success
2273.
}, function(reason){
2274.
// failure
2275.
});
2276.
```
2277.
Advanced Example
2278.
--------------
2279.
Synchronous Example
2280.
```javascript
2281.
let author, books;
2282.
try {
2283.
author = findAuthor();
2284.
books = findBooksByAuthor(author);
2285.
// success
2286.
} catch(reason) {
2287.
// failure
2288.
}
2289.
```
2290.
Errback Example
2291.
```js
2292.
function foundBooks(books) {
2293.
}
2294.
function failure(reason) {
2295.
}
2296.
findAuthor(function(author, err){
2297.
if (err) {
2298.
failure(err);
2299.
// failure
2300.
} else {
2301.
try {
2302.
findBoooksByAuthor(author, function(books, err) {
2303.
if (err) {
2304.
failure(err);
2305.
} else {
2306.
try {
2307.
foundBooks(books);
2308.
} catch(reason) {
2309.
failure(reason);
2310.
}
2311.
}
2312.
});
2313.
} catch(error) {
2314.
failure(err);
2315.
}
2316.
// success
2317.
}
2318.
});
2319.
```
2320.
Promise Example;
2321.
```javascript
2322.
findAuthor().
2323.
then(findBooksByAuthor).
2324.
then(function(books){
2325.
// found books
2326.
}).catch(function(reason){
2327.
// something went wrong
2328.
});
2329.
```
2330.
@method then
2331.
@param {Function} onFulfilled
2332.
@param {Function} onRejected
2333.
Useful for tooling.
2334.
@return {Promise}
2335.
*/
2336.
2337.
/**
2338.
`catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
2339.
as the catch block of a try/catch statement.
2340.
```js
2341.
function findAuthor(){
2342.
throw new Error('couldn't find that author');
2343.
}
2344.
// synchronous
2345.
try {
2346.
findAuthor();
2347.
} catch(reason) {
2348.
// something went wrong
2349.
}
2350.
// async with promises
2351.
findAuthor().catch(function(reason){
2352.
// something went wrong
2353.
});
2354.
```
2355.
@method catch
2356.
@param {Function} onRejection
2357.
Useful for tooling.
2358.
@return {Promise}
2359.
*/
2360.
2361.
2362.
createClass(Promise, [{
2363.
key: 'catch',
2364.
value: function _catch(onRejection) {
2365.
return this.then(null, onRejection);
2366.
}
2367.
2368.
/**
2369.
`finally` will be invoked regardless of the promise's fate just as native
2370.
try/catch/finally behaves
2371.
2372.
Synchronous example:
2373.
2374.
```js
2375.
findAuthor() {
2376.
if (Math.random() > 0.5) {
2377.
throw new Error();
2378.
}
2379.
return new Author();
2380.
}
2381.
2382.
try {
2383.
return findAuthor(); // succeed or fail
2384.
} catch(error) {
2385.
return findOtherAuther();
2386.
} finally {
2387.
// always runs
2388.
// doesn't affect the return value
2389.
}
2390.
```
2391.
2392.
Asynchronous example:
2393.
2394.
```js
2395.
findAuthor().catch(function(reason){
2396.
return findOtherAuther();
2397.
}).finally(function(){
2398.
// author was either found, or not
2399.
});
2400.
```
2401.
2402.
@method finally
2403.
@param {Function} callback
2404.
@return {Promise}
2405.
*/
2406.
2407.
}, {
2408.
key: 'finally',
2409.
value: function _finally(callback) {
2410.
var promise = this;
2411.
var constructor = promise.constructor;
2412.
2413.
if (isFunction(callback)) {
2414.
return promise.then(function (value) {
2415.
return constructor.resolve(callback()).then(function () {
2416.
return value;
2417.
});
2418.
}, function (reason) {
2419.
return constructor.resolve(callback()).then(function () {
2420.
throw reason;
2421.
});
2422.
});
2423.
}
2424.
2425.
return promise.then(callback, callback);
2426.
}
2427.
}]);
2428.
return Promise;
2429.
}();
2430.
2431.
Promise$2.prototype.then = then;
2432.
Promise$2.all = all;
2433.
Promise$2.race = race;
2434.
Promise$2.resolve = resolve$1;
2435.
Promise$2.reject = reject$1;
2436.
Promise$2._setScheduler = setScheduler;
2437.
Promise$2._setAsap = setAsap;
2438.
Promise$2._asap = asap;
2439.
2440.
/*global self*/
2441.
function polyfill() {
2442.
var local = void 0;
2443.
2444.
if (typeof global !== 'undefined') {
2445.
local = global;
2446.
} else if (typeof self !== 'undefined') {
2447.
local = self;
2448.
} else {
2449.
try {
2450.
local = Function('return this')();
2451.
} catch (e) {
2452.
throw new Error('polyfill failed because global object is unavailable in this environment');
2453.
}
2454.
}
2455.
2456.
var P = local.Promise;
2457.
2458.
if (P) {
2459.
var promiseToString = null;
2460.
try {
2461.
promiseToString = Object.prototype.toString.call(P.resolve());
2462.
} catch (e) {
2463.
// silently ignored
2464.
}
2465.
2466.
if (promiseToString === '[object Promise]' && !P.cast) {
2467.
return;
2468.
}
2469.
}
2470.
2471.
local.Promise = Promise$2;
2472.
}
2473.
2474.
// Strange compat..
2475.
Promise$2.polyfill = polyfill;
2476.
Promise$2.Promise = Promise$2;
2477.
2478.
var Promise$1 = typeof Promise !== "undefined" ? Promise : Promise$2;
2479.
2480.
// Register logging callbacks
2481.
function registerLoggingCallbacks(obj) {
2482.
var i,
2483.
l,
2484.
key,
2485.
callbackNames = ["begin", "done", "log", "testStart", "testDone", "moduleStart", "moduleDone"];
2486.
2487.
function registerLoggingCallback(key) {
2488.
var loggingCallback = function loggingCallback(callback) {
2489.
if (objectType(callback) !== "function") {
2490.
throw new Error("QUnit logging methods require a callback function as their first parameters.");
2491.
}
2492.
2493.
config.callbacks[key].push(callback);
2494.
};
2495.
2496.
return loggingCallback;
2497.
}
2498.
2499.
for (i = 0, l = callbackNames.length; i < l; i++) {
2500.
key = callbackNames[i];
2501.
2502.
// Initialize key collection of logging callback
2503.
if (objectType(config.callbacks[key]) === "undefined") {
2504.
config.callbacks[key] = [];
2505.
}
2506.
2507.
obj[key] = registerLoggingCallback(key);
2508.
}
2509.
}
2510.
2511.
function runLoggingCallbacks(key, args) {
2512.
var callbacks = config.callbacks[key];
2513.
2514.
// Handling 'log' callbacks separately. Unlike the other callbacks,
2515.
// the log callback is not controlled by the processing queue,
2516.
// but rather used by asserts. Hence to promisfy the 'log' callback
2517.
// would mean promisfying each step of a test
2518.
if (key === "log") {
2519.
callbacks.map(function (callback) {
2520.
return callback(args);
2521.
});
2522.
return;
2523.
}
2524.
2525.
// ensure that each callback is executed serially
2526.
return callbacks.reduce(function (promiseChain, callback) {
2527.
return promiseChain.then(function () {
2528.
return Promise$1.resolve(callback(args));
2529.
});
2530.
}, Promise$1.resolve([]));
2531.
}
2532.
2533.
// Doesn't support IE9, it will return undefined on these browsers
2534.
// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
2535.
var fileName = (sourceFromStacktrace(0) || "").replace(/(:\d+)+\)?/, "").replace(/.+\//, "");
2536.
2537.
function extractStacktrace(e, offset) {
2538.
offset = offset === undefined ? 4 : offset;
2539.
2540.
var stack, include, i;
2541.
2542.
if (e && e.stack) {
2543.
stack = e.stack.split("\n");
2544.
if (/^error$/i.test(stack[0])) {
2545.
stack.shift();
2546.
}
2547.
if (fileName) {
2548.
include = [];
2549.
for (i = offset; i < stack.length; i++) {
2550.
if (stack[i].indexOf(fileName) !== -1) {
2551.
break;
2552.
}
2553.
include.push(stack[i]);
2554.
}
2555.
if (include.length) {
2556.
return include.join("\n");
2557.
}
2558.
}
2559.
return stack[offset];
2560.
}
2561.
}
2562.
2563.
function sourceFromStacktrace(offset) {
2564.
var error = new Error();
2565.
2566.
// Support: Safari <=7 only, IE <=10 - 11 only
2567.
// Not all browsers generate the `stack` property for `new Error()`, see also #636
2568.
if (!error.stack) {
2569.
try {
2570.
throw error;
2571.
} catch (err) {
2572.
error = err;
2573.
}
2574.
}
2575.
2576.
return extractStacktrace(error, offset);
2577.
}
2578.
2579.
var priorityCount = 0;
2580.
var unitSampler = void 0;
2581.
2582.
// This is a queue of functions that are tasks within a single test.
2583.
// After tests are dequeued from config.queue they are expanded into
2584.
// a set of tasks in this queue.
2585.
var taskQueue = [];
2586.
2587.
/**
2588.
* Advances the taskQueue to the next task. If the taskQueue is empty,
2589.
* process the testQueue
2590.
*/
2591.
function advance() {
2592.
advanceTaskQueue();
2593.
2594.
if (!taskQueue.length && !config.blocking && !config.current) {
2595.
advanceTestQueue();
2596.
}
2597.
}
2598.
2599.
/**
2600.
* Advances the taskQueue with an increased depth
2601.
*/
2602.
function advanceTaskQueue() {
2603.
var start = now();
2604.
config.depth = (config.depth || 0) + 1;
2605.
2606.
processTaskQueue(start);
2607.
2608.
config.depth--;
2609.
}
2610.
2611.
/**
2612.
* Process the first task on the taskQueue as a promise.
2613.
* Each task is a function returned by https://github.com/qunitjs/qunit/blob/master/src/test.js#L381
2614.
*/
2615.
function processTaskQueue(start) {
2616.
if (taskQueue.length && !config.blocking) {
2617.
var elapsedTime = now() - start;
2618.
2619.
if (!defined.setTimeout || config.updateRate <= 0 || elapsedTime < config.updateRate) {
2620.
var task = taskQueue.shift();
2621.
Promise$1.resolve(task()).then(function () {
2622.
if (!taskQueue.length) {
2623.
advance();
2624.
} else {
2625.
processTaskQueue(start);
2626.
}
2627.
});
2628.
} else {
2629.
setTimeout$1(advance);
2630.
}
2631.
}
2632.
}
2633.
2634.
/**
2635.
* Advance the testQueue to the next test to process. Call done() if testQueue completes.
2636.
*/
2637.
function advanceTestQueue() {
2638.
if (!config.blocking && !config.queue.length && config.depth === 0) {
2639.
done();
2640.
return;
2641.
}
2642.
2643.
var testTasks = config.queue.shift();
2644.
addToTaskQueue(testTasks());
2645.
2646.
if (priorityCount > 0) {
2647.
priorityCount--;
2648.
}
2649.
2650.
advance();
2651.
}
2652.
2653.
/**
2654.
* Enqueue the tasks for a test into the task queue.
2655.
* @param {Array} tasksArray
2656.
*/
2657.
function addToTaskQueue(tasksArray) {
2658.
taskQueue.push.apply(taskQueue, toConsumableArray(tasksArray));
2659.
}
2660.
2661.
/**
2662.
* Return the number of tasks remaining in the task queue to be processed.
2663.
* @return {Number}
2664.
*/
2665.
function taskQueueLength() {
2666.
return taskQueue.length;
2667.
}
2668.
2669.
/**
2670.
* Adds a test to the TestQueue for execution.
2671.
* @param {Function} testTasksFunc
2672.
* @param {Boolean} prioritize
2673.
* @param {String} seed
2674.
*/
2675.
function addToTestQueue(testTasksFunc, prioritize, seed) {
2676.
if (prioritize) {
2677.
config.queue.splice(priorityCount++, 0, testTasksFunc);
2678.
} else if (seed) {
2679.
if (!unitSampler) {
2680.
unitSampler = unitSamplerGenerator(seed);
2681.
}
2682.
2683.
// Insert into a random position after all prioritized items
2684.
var index = Math.floor(unitSampler() * (config.queue.length - priorityCount + 1));
2685.
config.queue.splice(priorityCount + index, 0, testTasksFunc);
2686.
} else {
2687.
config.queue.push(testTasksFunc);
2688.
}
2689.
}
2690.
2691.
/**
2692.
* Creates a seeded "sample" generator which is used for randomizing tests.
2693.
*/
2694.
function unitSamplerGenerator(seed) {
2695.
2696.
// 32-bit xorshift, requires only a nonzero seed
2697.
// http://excamera.com/sphinx/article-xorshift.html
2698.
var sample = parseInt(generateHash(seed), 16) || -1;
2699.
return function () {
2700.
sample ^= sample << 13;
2701.
sample ^= sample >>> 17;
2702.
sample ^= sample << 5;
2703.
2704.
// ECMAScript has no unsigned number type
2705.
if (sample < 0) {
2706.
sample += 0x100000000;
2707.
}
2708.
2709.
return sample / 0x100000000;
2710.
};
2711.
}
2712.
2713.
/**
2714.
* This function is called when the ProcessingQueue is done processing all
2715.
* items. It handles emitting the final run events.
2716.
*/
2717.
function done() {
2718.
var storage = config.storage;
2719.
2720.
ProcessingQueue.finished = true;
2721.
2722.
var runtime = now() - config.started;
2723.
var passed = config.stats.all - config.stats.bad;
2724.
2725.
if (config.stats.all === 0) {
2726.
2727.
if (config.filter && config.filter.length) {
2728.
throw new Error("No tests matched the filter \"" + config.filter + "\".");
2729.
}
2730.
2731.
if (config.module && config.module.length) {
2732.
throw new Error("No tests matched the module \"" + config.module + "\".");
2733.
}
2734.
2735.
if (config.moduleId && config.moduleId.length) {
2736.
throw new Error("No tests matched the moduleId \"" + config.moduleId + "\".");
2737.
}
2738.
2739.
if (config.testId && config.testId.length) {
2740.
throw new Error("No tests matched the testId \"" + config.testId + "\".");
2741.
}
2742.
2743.
throw new Error("No tests were run.");
2744.
}
2745.
2746.
emit("runEnd", globalSuite.end(true));
2747.
runLoggingCallbacks("done", {
2748.
passed: passed,
2749.
failed: config.stats.bad,
2750.
total: config.stats.all,
2751.
runtime: runtime
2752.
}).then(function () {
2753.
2754.
// Clear own storage items if all tests passed
2755.
if (storage && config.stats.bad === 0) {
2756.
for (var i = storage.length - 1; i >= 0; i--) {
2757.
var key = storage.key(i);
2758.
2759.
if (key.indexOf("qunit-test-") === 0) {
2760.
storage.removeItem(key);
2761.
}
2762.
}
2763.
}
2764.
});
2765.
}
2766.
2767.
var ProcessingQueue = {
2768.
finished: false,
2769.
add: addToTestQueue,
2770.
advance: advance,
2771.
taskCount: taskQueueLength
2772.
};
2773.
2774.
var TestReport = function () {
2775.
function TestReport(name, suite, options) {
2776.
classCallCheck(this, TestReport);
2777.
2778.
this.name = name;
2779.
this.suiteName = suite.name;
2780.
this.fullName = suite.fullName.concat(name);
2781.
this.runtime = 0;
2782.
this.assertions = [];
2783.
2784.
this.skipped = !!options.skip;
2785.
this.todo = !!options.todo;
2786.
2787.
this.valid = options.valid;
2788.
2789.
this._startTime = 0;
2790.
this._endTime = 0;
2791.
2792.
suite.pushTest(this);
2793.
}
2794.
2795.
createClass(TestReport, [{
2796.
key: "start",
2797.
value: function start(recordTime) {
2798.
if (recordTime) {
2799.
this._startTime = performanceNow();
2800.
if (performance) {
2801.
performance.mark("qunit_test_start");
2802.
}
2803.
}
2804.
2805.
return {
2806.
name: this.name,
2807.
suiteName: this.suiteName,
2808.
fullName: this.fullName.slice()
2809.
};
2810.
}
2811.
}, {
2812.
key: "end",
2813.
value: function end(recordTime) {
2814.
if (recordTime) {
2815.
this._endTime = performanceNow();
2816.
if (performance) {
2817.
performance.mark("qunit_test_end");
2818.
2819.
var testName = this.fullName.join(" – ");
2820.
2821.
measure("QUnit Test: " + testName, "qunit_test_start", "qunit_test_end");
2822.
}
2823.
}
2824.
2825.
return extend(this.start(), {
2826.
runtime: this.getRuntime(),
2827.
status: this.getStatus(),
2828.
errors: this.getFailedAssertions(),
2829.
assertions: this.getAssertions()
2830.
});
2831.
}
2832.
}, {
2833.
key: "pushAssertion",
2834.
value: function pushAssertion(assertion) {
2835.
this.assertions.push(assertion);
2836.
}
2837.
}, {
2838.
key: "getRuntime",
2839.
value: function getRuntime() {
2840.
return this._endTime - this._startTime;
2841.
}
2842.
}, {
2843.
key: "getStatus",
2844.
value: function getStatus() {
2845.
if (this.skipped) {
2846.
return "skipped";
2847.
}
2848.
2849.
var testPassed = this.getFailedAssertions().length > 0 ? this.todo : !this.todo;
2850.
2851.
if (!testPassed) {
2852.
return "failed";
2853.
} else if (this.todo) {
2854.
return "todo";
2855.
} else {
2856.
return "passed";
2857.
}
2858.
}
2859.
}, {
2860.
key: "getFailedAssertions",
2861.
value: function getFailedAssertions() {
2862.
return this.assertions.filter(function (assertion) {
2863.
return !assertion.passed;
2864.
});
2865.
}
2866.
}, {
2867.
key: "getAssertions",
2868.
value: function getAssertions() {
2869.
return this.assertions.slice();
2870.
}
2871.
2872.
// Remove actual and expected values from assertions. This is to prevent
2873.
// leaking memory throughout a test suite.
2874.
2875.
}, {
2876.
key: "slimAssertions",
2877.
value: function slimAssertions() {
2878.
this.assertions = this.assertions.map(function (assertion) {
2879.
delete assertion.actual;
2880.
delete assertion.expected;
2881.
return assertion;
2882.
});
2883.
}
2884.
}]);
2885.
return TestReport;
2886.
}();
2887.
2888.
var focused$1 = false;
2889.
2890.
function Test(settings) {
2891.
var i, l;
2892.
2893.
++Test.count;
2894.
2895.
this.expected = null;
2896.
this.assertions = [];
2897.
this.semaphore = 0;
2898.
this.module = config.currentModule;
2899.
this.steps = [];
2900.
this.timeout = undefined;
2901.
this.errorForStack = new Error();
2902.
2903.
// If a module is skipped, all its tests and the tests of the child suites
2904.
// should be treated as skipped even if they are defined as `only` or `todo`.
2905.
// As for `todo` module, all its tests will be treated as `todo` except for
2906.
// tests defined as `skip` which will be left intact.
2907.
//
2908.
// So, if a test is defined as `todo` and is inside a skipped module, we should
2909.
// then treat that test as if was defined as `skip`.
2910.
if (this.module.skip) {
2911.
settings.skip = true;
2912.
settings.todo = false;
2913.
2914.
// Skipped tests should be left intact
2915.
} else if (this.module.todo && !settings.skip) {
2916.
settings.todo = true;
2917.
}
2918.
2919.
extend(this, settings);
2920.
2921.
this.testReport = new TestReport(settings.testName, this.module.suiteReport, {
2922.
todo: settings.todo,
2923.
skip: settings.skip,
2924.
valid: this.valid()
2925.
});
2926.
2927.
// Register unique strings
2928.
for (i = 0, l = this.module.tests; i < l.length; i++) {
2929.
if (this.module.tests[i].name === this.testName) {
2930.
this.testName += " ";
2931.
}
2932.
}
2933.
2934.
this.testId = generateHash(this.module.name, this.testName);
2935.
2936.
this.module.tests.push({
2937.
name: this.testName,
2938.
testId: this.testId,
2939.
skip: !!settings.skip
2940.
});
2941.
2942.
if (settings.skip) {
2943.
2944.
// Skipped tests will fully ignore any sent callback
2945.
this.callback = function () {};
2946.
this.async = false;
2947.
this.expected = 0;
2948.
} else {
2949.
if (typeof this.callback !== "function") {
2950.
var method = this.todo ? "todo" : "test";
2951.
2952.
// eslint-disable-next-line max-len
2953.
throw new TypeError("You must provide a function as a test callback to QUnit." + method + "(\"" + settings.testName + "\")");
2954.
}
2955.
2956.
this.assert = new Assert(this);
2957.
}
2958.
}
2959.
2960.
Test.count = 0;
2961.
2962.
function getNotStartedModules(startModule) {
2963.
var module = startModule,
2964.
modules = [];
2965.
2966.
while (module && module.testsRun === 0) {
2967.
modules.push(module);
2968.
module = module.parentModule;
2969.
}
2970.
2971.
// The above push modules from the child to the parent
2972.
// return a reversed order with the top being the top most parent module
2973.
return modules.reverse();
2974.
}
2975.
2976.
Test.prototype = {
2977.
2978.
// generating a stack trace can be expensive, so using a getter defers this until we need it
2979.
get stack() {
2980.
return extractStacktrace(this.errorForStack, 2);
2981.
},
2982.
2983.
before: function before() {
2984.
var _this = this;
2985.
2986.
var module = this.module,
2987.
notStartedModules = getNotStartedModules(module);
2988.
2989.
// ensure the callbacks are executed serially for each module
2990.
var callbackPromises = notStartedModules.reduce(function (promiseChain, startModule) {
2991.
return promiseChain.then(function () {
2992.
startModule.stats = { all: 0, bad: 0, started: now() };
2993.
emit("suiteStart", startModule.suiteReport.start(true));
2994.
return runLoggingCallbacks("moduleStart", {
2995.
name: startModule.name,
2996.
tests: startModule.tests
2997.
});
2998.
});
2999.
}, Promise$1.resolve([]));
3000.
3001.
return callbackPromises.then(function () {
3002.
config.current = _this;
3003.
3004.
_this.testEnvironment = extend({}, module.testEnvironment);
3005.
3006.
_this.started = now();
3007.
emit("testStart", _this.testReport.start(true));
3008.
return runLoggingCallbacks("testStart", {
3009.
name: _this.testName,
3010.
module: module.name,
3011.
testId: _this.testId,
3012.
previousFailure: _this.previousFailure
3013.
}).then(function () {
3014.
if (!config.pollution) {
3015.
saveGlobal();
3016.
}
3017.
});
3018.
});
3019.
},
3020.
3021.
run: function run() {
3022.
var promise;
3023.
3024.
config.current = this;
3025.
3026.
this.callbackStarted = now();
3027.
3028.
if (config.notrycatch) {
3029.
runTest(this);
3030.
return;
3031.
}
3032.
3033.
try {
3034.
runTest(this);
3035.
} catch (e) {
3036.
this.pushFailure("Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + (e.message || e), extractStacktrace(e, 0));
3037.
3038.
// Else next test will carry the responsibility
3039.
saveGlobal();
3040.
3041.
// Restart the tests if they're blocking
3042.
if (config.blocking) {
3043.
internalRecover(this);
3044.
}
3045.
}
3046.
3047.
function runTest(test) {
3048.
promise = test.callback.call(test.testEnvironment, test.assert);
3049.
test.resolvePromise(promise);
3050.
3051.
// If the test has a "lock" on it, but the timeout is 0, then we push a
3052.
// failure as the test should be synchronous.
3053.
if (test.timeout === 0 && test.semaphore !== 0) {
3054.
pushFailure("Test did not finish synchronously even though assert.timeout( 0 ) was used.", sourceFromStacktrace(2));
3055.
}
3056.
}
3057.
},
3058.
3059.
after: function after() {
3060.
checkPollution();
3061.
},
3062.
3063.
queueHook: function queueHook(hook, hookName, hookOwner) {
3064.
var _this2 = this;
3065.
3066.
var callHook = function callHook() {
3067.
var promise = hook.call(_this2.testEnvironment, _this2.assert);
3068.
_this2.resolvePromise(promise, hookName);
3069.
};
3070.
3071.
var runHook = function runHook() {
3072.
if (hookName === "before") {
3073.
if (hookOwner.unskippedTestsRun !== 0) {
3074.
return;
3075.
}
3076.
3077.
_this2.preserveEnvironment = true;
3078.
}
3079.
3080.
// The 'after' hook should only execute when there are not tests left and
3081.
// when the 'after' and 'finish' tasks are the only tasks left to process
3082.
if (hookName === "after" && hookOwner.unskippedTestsRun !== numberOfUnskippedTests(hookOwner) - 1 && (config.queue.length > 0 || ProcessingQueue.taskCount() > 2)) {
3083.
return;
3084.
}
3085.
3086.
config.current = _this2;
3087.
if (config.notrycatch) {
3088.
callHook();
3089.
return;
3090.
}
3091.
try {
3092.
callHook();
3093.
} catch (error) {
3094.
_this2.pushFailure(hookName + " failed on " + _this2.testName + ": " + (error.message || error), extractStacktrace(error, 0));
3095.
}
3096.
};
3097.
3098.
return runHook;
3099.
},
3100.
3101.
3102.
// Currently only used for module level hooks, can be used to add global level ones
3103.
hooks: function hooks(handler) {
3104.
var hooks = [];
3105.
3106.
function processHooks(test, module) {
3107.
if (module.parentModule) {
3108.
processHooks(test, module.parentModule);
3109.
}
3110.
3111.
if (module.hooks[handler].length) {
3112.
for (var i = 0; i < module.hooks[handler].length; i++) {
3113.
hooks.push(test.queueHook(module.hooks[handler][i], handler, module));
3114.
}
3115.
}
3116.
}
3117.
3118.
// Hooks are ignored on skipped tests
3119.
if (!this.skip) {
3120.
processHooks(this, this.module);
3121.
}
3122.
3123.
return hooks;
3124.
},
3125.
3126.
3127.
finish: function finish() {
3128.
config.current = this;
3129.
3130.
// Release the test callback to ensure that anything referenced has been
3131.
// released to be garbage collected.
3132.
this.callback = undefined;
3133.
3134.
if (this.steps.length) {
3135.
var stepsList = this.steps.join(", ");
3136.
this.pushFailure("Expected assert.verifySteps() to be called before end of test " + ("after using assert.step(). Unverified steps: " + stepsList), this.stack);
3137.
}
3138.
3139.
if (config.requireExpects && this.expected === null) {
3140.
this.pushFailure("Expected number of assertions to be defined, but expect() was " + "not called.", this.stack);
3141.
} else if (this.expected !== null && this.expected !== this.assertions.length) {
3142.
this.pushFailure("Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack);
3143.
} else if (this.expected === null && !this.assertions.length) {
3144.
this.pushFailure("Expected at least one assertion, but none were run - call " + "expect(0) to accept zero assertions.", this.stack);
3145.
}
3146.
3147.
var i,
3148.
module = this.module,
3149.
moduleName = module.name,
3150.
testName = this.testName,
3151.
skipped = !!this.skip,
3152.
todo = !!this.todo,
3153.
bad = 0,
3154.
storage = config.storage;
3155.
3156.
this.runtime = now() - this.started;
3157.
3158.
config.stats.all += this.assertions.length;
3159.
module.stats.all += this.assertions.length;
3160.
3161.
for (i = 0; i < this.assertions.length; i++) {
3162.
if (!this.assertions[i].result) {
3163.
bad++;
3164.
config.stats.bad++;
3165.
module.stats.bad++;
3166.
}
3167.
}
3168.
3169.
notifyTestsRan(module, skipped);
3170.
3171.
// Store result when possible
3172.
if (storage) {
3173.
if (bad) {
3174.
storage.setItem("qunit-test-" + moduleName + "-" + testName, bad);
3175.
} else {
3176.
storage.removeItem("qunit-test-" + moduleName + "-" + testName);
3177.
}
3178.
}
3179.
3180.
// After emitting the js-reporters event we cleanup the assertion data to
3181.
// avoid leaking it. It is not used by the legacy testDone callbacks.
3182.
emit("testEnd", this.testReport.end(true));
3183.
this.testReport.slimAssertions();
3184.
var test = this;
3185.
3186.
return runLoggingCallbacks("testDone", {
3187.
name: testName,
3188.
module: moduleName,
3189.
skipped: skipped,
3190.
todo: todo,
3191.
failed: bad,
3192.
passed: this.assertions.length - bad,
3193.
total: this.assertions.length,
3194.
runtime: skipped ? 0 : this.runtime,
3195.
3196.
// HTML Reporter use
3197.
assertions: this.assertions,
3198.
testId: this.testId,
3199.
3200.
// Source of Test
3201.
// generating stack trace is expensive, so using a getter will help defer this until we need it
3202.
get source() {
3203.
return test.stack;
3204.
}
3205.
}).then(function () {
3206.
if (module.testsRun === numberOfTests(module)) {
3207.
var completedModules = [module];
3208.
3209.
// Check if the parent modules, iteratively, are done. If that the case,
3210.
// we emit the `suiteEnd` event and trigger `moduleDone` callback.
3211.
var parent = module.parentModule;
3212.
while (parent && parent.testsRun === numberOfTests(parent)) {
3213.
completedModules.push(parent);
3214.
parent = parent.parentModule;
3215.
}
3216.
3217.
return completedModules.reduce(function (promiseChain, completedModule) {
3218.
return promiseChain.then(function () {
3219.
return logSuiteEnd(completedModule);
3220.
});
3221.
}, Promise$1.resolve([]));
3222.
}
3223.
}).then(function () {
3224.
config.current = undefined;
3225.
});
3226.
3227.
function logSuiteEnd(module) {
3228.
3229.
// Reset `module.hooks` to ensure that anything referenced in these hooks
3230.
// has been released to be garbage collected.
3231.
module.hooks = {};
3232.
3233.
emit("suiteEnd", module.suiteReport.end(true));
3234.
return runLoggingCallbacks("moduleDone", {
3235.
name: module.name,
3236.
tests: module.tests,
3237.
failed: module.stats.bad,
3238.
passed: module.stats.all - module.stats.bad,
3239.
total: module.stats.all,
3240.
runtime: now() - module.stats.started
3241.
});
3242.
}
3243.
},
3244.
3245.
preserveTestEnvironment: function preserveTestEnvironment() {
3246.
if (this.preserveEnvironment) {
3247.
this.module.testEnvironment = this.testEnvironment;
3248.
this.testEnvironment = extend({}, this.module.testEnvironment);
3249.
}
3250.
},
3251.
3252.
queue: function queue() {
3253.
var test = this;
3254.
3255.
if (!this.valid()) {
3256.
return;
3257.
}
3258.
3259.
function runTest() {
3260.
return [function () {
3261.
return test.before();
3262.
}].concat(toConsumableArray(test.hooks("before")), [function () {
3263.
test.preserveTestEnvironment();
3264.
}], toConsumableArray(test.hooks("beforeEach")), [function () {
3265.
test.run();
3266.
}], toConsumableArray(test.hooks("afterEach").reverse()), toConsumableArray(test.hooks("after").reverse()), [function () {
3267.
test.after();
3268.
}, function () {
3269.
return test.finish();
3270.
}]);
3271.
}
3272.
3273.
var previousFailCount = config.storage && +config.storage.getItem("qunit-test-" + this.module.name + "-" + this.testName);
3274.
3275.
// Prioritize previously failed tests, detected from storage
3276.
var prioritize = config.reorder && !!previousFailCount;
3277.
3278.
this.previousFailure = !!previousFailCount;
3279.
3280.
ProcessingQueue.add(runTest, prioritize, config.seed);
3281.
3282.
// If the queue has already finished, we manually process the new test
3283.
if (ProcessingQueue.finished) {
3284.
ProcessingQueue.advance();
3285.
}
3286.
},
3287.
3288.
3289.
pushResult: function pushResult(resultInfo) {
3290.
if (this !== config.current) {
3291.
throw new Error("Assertion occurred after test had finished.");
3292.
}
3293.
3294.
// Destructure of resultInfo = { result, actual, expected, message, negative }
3295.
var source,
3296.
details = {
3297.
module: this.module.name,
3298.
name: this.testName,
3299.
result: resultInfo.result,
3300.
message: resultInfo.message,
3301.
actual: resultInfo.actual,
3302.
testId: this.testId,
3303.
negative: resultInfo.negative || false,
3304.
runtime: now() - this.started,
3305.
todo: !!this.todo
3306.
};
3307.
3308.
if (hasOwn.call(resultInfo, "expected")) {
3309.
details.expected = resultInfo.expected;
3310.
}
3311.
3312.
if (!resultInfo.result) {
3313.
source = resultInfo.source || sourceFromStacktrace();
3314.
3315.
if (source) {
3316.
details.source = source;
3317.
}
3318.
}
3319.
3320.
this.logAssertion(details);
3321.
3322.
this.assertions.push({
3323.
result: !!resultInfo.result,
3324.
message: resultInfo.message
3325.
});
3326.
},
3327.
3328.
pushFailure: function pushFailure(message, source, actual) {
3329.
if (!(this instanceof Test)) {
3330.
throw new Error("pushFailure() assertion outside test context, was " + sourceFromStacktrace(2));
3331.
}
3332.
3333.
this.pushResult({
3334.
result: false,
3335.
message: message || "error",
3336.
actual: actual || null,
3337.
source: source
3338.
});
3339.
},
3340.
3341.
/**
3342.
* Log assertion details using both the old QUnit.log interface and
3343.
* QUnit.on( "assertion" ) interface.
3344.
*
3345.
* @private
3346.
*/
3347.
logAssertion: function logAssertion(details) {
3348.
runLoggingCallbacks("log", details);
3349.
3350.
var assertion = {
3351.
passed: details.result,
3352.
actual: details.actual,
3353.
expected: details.expected,
3354.
message: details.message,
3355.
stack: details.source,
3356.
todo: details.todo
3357.
};
3358.
this.testReport.pushAssertion(assertion);
3359.
emit("assertion", assertion);
3360.
},
3361.
3362.
3363.
resolvePromise: function resolvePromise(promise, phase) {
3364.
var then,
3365.
resume,
3366.
message,
3367.
test = this;
3368.
if (promise != null) {
3369.
then = promise.then;
3370.
if (objectType(then) === "function") {
3371.
resume = internalStop(test);
3372.
if (config.notrycatch) {
3373.
then.call(promise, function () {
3374.
resume();
3375.
});
3376.
} else {
3377.
then.call(promise, function () {
3378.
resume();
3379.
}, function (error) {
3380.
message = "Promise rejected " + (!phase ? "during" : phase.replace(/Each$/, "")) + " \"" + test.testName + "\": " + (error && error.message || error);
3381.
test.pushFailure(message, extractStacktrace(error, 0));
3382.
3383.
// Else next test will carry the responsibility
3384.
saveGlobal();
3385.
3386.
// Unblock
3387.
internalRecover(test);
3388.
});
3389.
}
3390.
}
3391.
}
3392.
},
3393.
3394.
valid: function valid() {
3395.
var filter = config.filter,
3396.
regexFilter = /^(!?)\/([\w\W]*)\/(i?$)/.exec(filter),
3397.
module = config.module && config.module.toLowerCase(),
3398.
fullName = this.module.name + ": " + this.testName;
3399.
3400.
function moduleChainNameMatch(testModule) {
3401.
var testModuleName = testModule.name ? testModule.name.toLowerCase() : null;
3402.
if (testModuleName === module) {
3403.
return true;
3404.
} else if (testModule.parentModule) {
3405.
return moduleChainNameMatch(testModule.parentModule);
3406.
} else {
3407.
return false;
3408.
}
3409.
}
3410.
3411.
function moduleChainIdMatch(testModule) {
3412.
return inArray(testModule.moduleId, config.moduleId) || testModule.parentModule && moduleChainIdMatch(testModule.parentModule);
3413.
}
3414.
3415.
// Internally-generated tests are always valid
3416.
if (this.callback && this.callback.validTest) {
3417.
return true;
3418.
}
3419.
3420.
if (config.moduleId && config.moduleId.length > 0 && !moduleChainIdMatch(this.module)) {
3421.
3422.
return false;
3423.
}
3424.
3425.
if (config.testId && config.testId.length > 0 && !inArray(this.testId, config.testId)) {
3426.
3427.
return false;
3428.
}
3429.
3430.
if (module && !moduleChainNameMatch(this.module)) {
3431.
return false;
3432.
}
3433.
3434.
if (!filter) {
3435.
return true;
3436.
}
3437.
3438.
return regexFilter ? this.regexFilter(!!regexFilter[1], regexFilter[2], regexFilter[3], fullName) : this.stringFilter(filter, fullName);
3439.
},
3440.
3441.
regexFilter: function regexFilter(exclude, pattern, flags, fullName) {
3442.
var regex = new RegExp(pattern, flags);
3443.
var match = regex.test(fullName);
3444.
3445.
return match !== exclude;
3446.
},
3447.
3448.
stringFilter: function stringFilter(filter, fullName) {
3449.
filter = filter.toLowerCase();
3450.
fullName = fullName.toLowerCase();
3451.
3452.
var include = filter.charAt(0) !== "!";
3453.
if (!include) {
3454.
filter = filter.slice(1);
3455.
}
3456.
3457.
// If the filter matches, we need to honour include
3458.
if (fullName.indexOf(filter) !== -1) {
3459.
return include;
3460.
}
3461.
3462.
// Otherwise, do the opposite
3463.
return !include;
3464.
}
3465.
};
3466.
3467.
function pushFailure() {
3468.
if (!config.current) {
3469.
throw new Error("pushFailure() assertion outside test context, in " + sourceFromStacktrace(2));
3470.
}
3471.
3472.
// Gets current test obj
3473.
var currentTest = config.current;
3474.
3475.
return currentTest.pushFailure.apply(currentTest, arguments);
3476.
}
3477.
3478.
function saveGlobal() {
3479.
config.pollution = [];
3480.
3481.
if (config.noglobals) {
3482.
for (var key in global$1) {
3483.
if (hasOwn.call(global$1, key)) {
3484.
3485.
// In Opera sometimes DOM element ids show up here, ignore them
3486.
if (/^qunit-test-output/.test(key)) {
3487.
continue;
3488.
}
3489.
config.pollution.push(key);
3490.
}
3491.
}
3492.
}
3493.
}
3494.
3495.
function checkPollution() {
3496.
var newGlobals,
3497.
deletedGlobals,
3498.
old = config.pollution;
3499.
3500.
saveGlobal();
3501.
3502.
newGlobals = diff(config.pollution, old);
3503.
if (newGlobals.length > 0) {
3504.
pushFailure("Introduced global variable(s): " + newGlobals.join(", "));
3505.
}
3506.
3507.
deletedGlobals = diff(old, config.pollution);
3508.
if (deletedGlobals.length > 0) {
3509.
pushFailure("Deleted global variable(s): " + deletedGlobals.join(", "));
3510.
}
3511.
}
3512.
3513.
// Will be exposed as QUnit.test
3514.
function test(testName, callback) {
3515.
if (focused$1) {
3516.
return;
3517.
}
3518.
3519.
var newTest = new Test({
3520.
testName: testName,
3521.
callback: callback
3522.
});
3523.
3524.
newTest.queue();
3525.
}
3526.
3527.
function todo(testName, callback) {
3528.
if (focused$1) {
3529.
return;
3530.
}
3531.
3532.
var newTest = new Test({
3533.
testName: testName,
3534.
callback: callback,
3535.
todo: true
3536.
});
3537.
3538.
newTest.queue();
3539.
}
3540.
3541.
// Will be exposed as QUnit.skip
3542.
function skip(testName) {
3543.
if (focused$1) {
3544.
return;
3545.
}
3546.
3547.
var test = new Test({
3548.
testName: testName,
3549.
skip: true
3550.
});
3551.
3552.
test.queue();
3553.
}
3554.
3555.
// Will be exposed as QUnit.only
3556.
function only(testName, callback) {
3557.
if (!focused$1) {
3558.
config.queue.length = 0;
3559.
focused$1 = true;
3560.
}
3561.
3562.
var newTest = new Test({
3563.
testName: testName,
3564.
callback: callback
3565.
});
3566.
3567.
newTest.queue();
3568.
}
3569.
3570.
// Resets config.timeout with a new timeout duration.
3571.
function resetTestTimeout(timeoutDuration) {
3572.
clearTimeout(config.timeout);
3573.
config.timeout = setTimeout$1(config.timeoutHandler(timeoutDuration), timeoutDuration);
3574.
}
3575.
3576.
// Put a hold on processing and return a function that will release it.
3577.
function internalStop(test) {
3578.
var released = false;
3579.
test.semaphore += 1;
3580.
config.blocking = true;
3581.
3582.
// Set a recovery timeout, if so configured.
3583.
if (defined.setTimeout) {
3584.
var timeoutDuration = void 0;
3585.
3586.
if (typeof test.timeout === "number") {
3587.
timeoutDuration = test.timeout;
3588.
} else if (typeof config.testTimeout === "number") {
3589.
timeoutDuration = config.testTimeout;
3590.
}
3591.
3592.
if (typeof timeoutDuration === "number" && timeoutDuration > 0) {
3593.
clearTimeout(config.timeout);
3594.
config.timeoutHandler = function (timeout) {
3595.
return function () {
3596.
pushFailure("Test took longer than " + timeout + "ms; test timed out.", sourceFromStacktrace(2));
3597.
released = true;
3598.
internalRecover(test);
3599.
};
3600.
};
3601.
config.timeout = setTimeout$1(config.timeoutHandler(timeoutDuration), timeoutDuration);
3602.
}
3603.
}
3604.
3605.
return function resume() {
3606.
if (released) {
3607.
return;
3608.
}
3609.
3610.
released = true;
3611.
test.semaphore -= 1;
3612.
internalStart(test);
3613.
};
3614.
}
3615.
3616.
// Forcefully release all processing holds.
3617.
function internalRecover(test) {
3618.
test.semaphore = 0;
3619.
internalStart(test);
3620.
}
3621.
3622.
// Release a processing hold, scheduling a resumption attempt if no holds remain.
3623.
function internalStart(test) {
3624.
3625.
// If semaphore is non-numeric, throw error
3626.
if (isNaN(test.semaphore)) {
3627.
test.semaphore = 0;
3628.
3629.
pushFailure("Invalid value on test.semaphore", sourceFromStacktrace(2));
3630.
return;
3631.
}
3632.
3633.
// Don't start until equal number of stop-calls
3634.
if (test.semaphore > 0) {
3635.
return;
3636.
}
3637.
3638.
// Throw an Error if start is called more often than stop
3639.
if (test.semaphore < 0) {
3640.
test.semaphore = 0;
3641.
3642.
pushFailure("Tried to restart test while already started (test's semaphore was 0 already)", sourceFromStacktrace(2));
3643.
return;
3644.
}
3645.
3646.
// Add a slight delay to allow more assertions etc.
3647.
if (defined.setTimeout) {
3648.
if (config.timeout) {
3649.
clearTimeout(config.timeout);
3650.
}
3651.
config.timeout = setTimeout$1(function () {
3652.
if (test.semaphore > 0) {
3653.
return;
3654.
}
3655.
3656.
if (config.timeout) {
3657.
clearTimeout(config.timeout);
3658.
}
3659.
3660.
begin();
3661.
});
3662.
} else {
3663.
begin();
3664.
}
3665.
}
3666.
3667.
function collectTests(module) {
3668.
var tests = [].concat(module.tests);
3669.
var modules = [].concat(toConsumableArray(module.childModules));
3670.
3671.
// Do a breadth-first traversal of the child modules
3672.
while (modules.length) {
3673.
var nextModule = modules.shift();
3674.
tests.push.apply(tests, nextModule.tests);
3675.
modules.push.apply(modules, toConsumableArray(nextModule.childModules));
3676.
}
3677.
3678.
return tests;
3679.
}
3680.
3681.
function numberOfTests(module) {
3682.
return collectTests(module).length;
3683.
}
3684.
3685.
function numberOfUnskippedTests(module) {
3686.
return collectTests(module).filter(function (test) {
3687.
return !test.skip;
3688.
}).length;
3689.
}
3690.
3691.
function notifyTestsRan(module, skipped) {
3692.
module.testsRun++;
3693.
if (!skipped) {
3694.
module.unskippedTestsRun++;
3695.
}
3696.
while (module = module.parentModule) {
3697.
module.testsRun++;
3698.
if (!skipped) {
3699.
module.unskippedTestsRun++;
3700.
}
3701.
}
3702.
}
3703.
3704.
var Assert = function () {
3705.
function Assert(testContext) {
3706.
classCallCheck(this, Assert);
3707.
3708.
this.test = testContext;
3709.
}
3710.
3711.
// Assert helpers
3712.
3713.
createClass(Assert, [{
3714.
key: "timeout",
3715.
value: function timeout(duration) {
3716.
if (typeof duration !== "number") {
3717.
throw new Error("You must pass a number as the duration to assert.timeout");
3718.
}
3719.
3720.
this.test.timeout = duration;
3721.
3722.
// If a timeout has been set, clear it and reset with the new duration
3723.
if (config.timeout) {
3724.
clearTimeout(config.timeout);
3725.
3726.
if (config.timeoutHandler && this.test.timeout > 0) {
3727.
resetTestTimeout(this.test.timeout);
3728.
}
3729.
}
3730.
}
3731.
3732.
// Documents a "step", which is a string value, in a test as a passing assertion
3733.
3734.
}, {
3735.
key: "step",
3736.
value: function step(message) {
3737.
var assertionMessage = message;
3738.
var result = !!message;
3739.
3740.
this.test.steps.push(message);
3741.
3742.
if (objectType(message) === "undefined" || message === "") {
3743.
assertionMessage = "You must provide a message to assert.step";
3744.
} else if (objectType(message) !== "string") {
3745.
assertionMessage = "You must provide a string value to assert.step";
3746.
result = false;
3747.
}
3748.
3749.
this.pushResult({
3750.
result: result,
3751.
message: assertionMessage
3752.
});
3753.
}
3754.
3755.
// Verifies the steps in a test match a given array of string values
3756.
3757.
}, {
3758.
key: "verifySteps",
3759.
value: function verifySteps(steps, message) {
3760.
3761.
// Since the steps array is just string values, we can clone with slice
3762.
var actualStepsClone = this.test.steps.slice();
3763.
this.deepEqual(actualStepsClone, steps, message);
3764.
this.test.steps.length = 0;
3765.
}
3766.
3767.
// Specify the number of expected assertions to guarantee that failed test
3768.
// (no assertions are run at all) don't slip through.
3769.
3770.
}, {
3771.
key: "expect",
3772.
value: function expect(asserts) {
3773.
if (arguments.length === 1) {
3774.
this.test.expected = asserts;
3775.
} else {
3776.
return this.test.expected;
3777.
}
3778.
}
3779.
3780.
// Put a hold on processing and return a function that will release it a maximum of once.
3781.
3782.
}, {
3783.
key: "async",
3784.
value: function async(count) {
3785.
var test$$1 = this.test;
3786.
3787.
var popped = false,
3788.
acceptCallCount = count;
3789.
3790.
if (typeof acceptCallCount === "undefined") {
3791.
acceptCallCount = 1;
3792.
}
3793.
3794.
var resume = internalStop(test$$1);
3795.
3796.
return function done() {
3797.
if (config.current !== test$$1) {
3798.
throw Error("assert.async callback called after test finished.");
3799.
}
3800.
3801.
if (popped) {
3802.
test$$1.pushFailure("Too many calls to the `assert.async` callback", sourceFromStacktrace(2));
3803.
return;
3804.
}
3805.
3806.
acceptCallCount -= 1;
3807.
if (acceptCallCount > 0) {
3808.
return;
3809.
}
3810.
3811.
popped = true;
3812.
resume();
3813.
};
3814.
}
3815.
3816.
// Exports test.push() to the user API
3817.
// Alias of pushResult.
3818.
3819.
}, {
3820.
key: "push",
3821.
value: function push(result, actual, expected, message, negative) {
3822.
Logger.warn("assert.push is deprecated and will be removed in QUnit 3.0." + " Please use assert.pushResult instead (https://api.qunitjs.com/assert/pushResult).");
3823.
3824.
var currentAssert = this instanceof Assert ? this : config.current.assert;
3825.
return currentAssert.pushResult({
3826.
result: result,
3827.
actual: actual,
3828.
expected: expected,
3829.
message: message,
3830.
negative: negative
3831.
});
3832.
}
3833.
}, {
3834.
key: "pushResult",
3835.
value: function pushResult(resultInfo) {
3836.
3837.
// Destructure of resultInfo = { result, actual, expected, message, negative }
3838.
var assert = this;
3839.
var currentTest = assert instanceof Assert && assert.test || config.current;
3840.
3841.
// Backwards compatibility fix.
3842.
// Allows the direct use of global exported assertions and QUnit.assert.*
3843.
// Although, it's use is not recommended as it can leak assertions
3844.
// to other tests from async tests, because we only get a reference to the current test,
3845.
// not exactly the test where assertion were intended to be called.
3846.
if (!currentTest) {
3847.
throw new Error("assertion outside test context, in " + sourceFromStacktrace(2));
3848.
}
3849.
3850.
if (!(assert instanceof Assert)) {
3851.
assert = currentTest.assert;
3852.
}
3853.
3854.
return assert.test.pushResult(resultInfo);
3855.
}
3856.
}, {
3857.
key: "ok",
3858.
value: function ok(result, message) {
3859.
if (!message) {
3860.
message = result ? "okay" : "failed, expected argument to be truthy, was: " + dump.parse(result);
3861.
}
3862.
3863.
this.pushResult({
3864.
result: !!result,
3865.
actual: result,
3866.
expected: true,
3867.
message: message
3868.
});
3869.
}
3870.
}, {
3871.
key: "notOk",
3872.
value: function notOk(result, message) {
3873.
if (!message) {
3874.
message = !result ? "okay" : "failed, expected argument to be falsy, was: " + dump.parse(result);
3875.
}
3876.
3877.
this.pushResult({
3878.
result: !result,
3879.
actual: result,
3880.
expected: false,
3881.
message: message
3882.
});
3883.
}
3884.
}, {
3885.
key: "equal",
3886.
value: function equal(actual, expected, message) {
3887.
3888.
// eslint-disable-next-line eqeqeq
3889.
var result = expected == actual;
3890.
3891.
this.pushResult({
3892.
result: result,
3893.
actual: actual,
3894.
expected: expected,
3895.
message: message
3896.
});
3897.
}
3898.
}, {
3899.
key: "notEqual",
3900.
value: function notEqual(actual, expected, message) {
3901.
3902.
// eslint-disable-next-line eqeqeq
3903.
var result = expected != actual;
3904.
3905.
this.pushResult({
3906.
result: result,
3907.
actual: actual,
3908.
expected: expected,
3909.
message: message,
3910.
negative: true
3911.
});
3912.
}
3913.
}, {
3914.
key: "propEqual",
3915.
value: function propEqual(actual, expected, message) {
3916.
actual = objectValues(actual);
3917.
expected = objectValues(expected);
3918.
3919.
this.pushResult({
3920.
result: equiv(actual, expected),
3921.
actual: actual,
3922.
expected: expected,
3923.
message: message
3924.
});
3925.
}
3926.
}, {
3927.
key: "notPropEqual",
3928.
value: function notPropEqual(actual, expected, message) {
3929.
actual = objectValues(actual);
3930.
expected = objectValues(expected);
3931.
3932.
this.pushResult({
3933.
result: !equiv(actual, expected),
3934.
actual: actual,
3935.
expected: expected,
3936.
message: message,
3937.
negative: true
3938.
});
3939.
}
3940.
}, {
3941.
key: "deepEqual",
3942.
value: function deepEqual(actual, expected, message) {
3943.
this.pushResult({
3944.
result: equiv(actual, expected),
3945.
actual: actual,
3946.
expected: expected,
3947.
message: message
3948.
});
3949.
}
3950.
}, {
3951.
key: "notDeepEqual",
3952.
value: function notDeepEqual(actual, expected, message) {
3953.
this.pushResult({
3954.
result: !equiv(actual, expected),
3955.
actual: actual,
3956.
expected: expected,
3957.
message: message,
3958.
negative: true
3959.
});
3960.
}
3961.
}, {
3962.
key: "strictEqual",
3963.
value: function strictEqual(actual, expected, message) {
3964.
this.pushResult({
3965.
result: expected === actual,
3966.
actual: actual,
3967.
expected: expected,
3968.
message: message
3969.
});
3970.
}
3971.
}, {
3972.
key: "notStrictEqual",
3973.
value: function notStrictEqual(actual, expected, message) {
3974.
this.pushResult({
3975.
result: expected !== actual,
3976.
actual: actual,
3977.
expected: expected,
3978.
message: message,
3979.
negative: true
3980.
});
3981.
}
3982.
}, {
3983.
key: "throws",
3984.
value: function throws(block, expected, message) {
3985.
var actual = void 0,
3986.
result = false;
3987.
3988.
var currentTest = this instanceof Assert && this.test || config.current;
3989.
3990.
// 'expected' is optional unless doing string comparison
3991.
if (objectType(expected) === "string") {
3992.
if (message == null) {
3993.
message = expected;
3994.
expected = null;
3995.
} else {
3996.
throw new Error("throws/raises does not accept a string value for the expected argument.\n" + "Use a non-string object value (e.g. regExp) instead if it's necessary.");
3997.
}
3998.
}
3999.
4000.
currentTest.ignoreGlobalErrors = true;
4001.
try {
4002.
block.call(currentTest.testEnvironment);
4003.
} catch (e) {
4004.
actual = e;
4005.
}
4006.
currentTest.ignoreGlobalErrors = false;
4007.
4008.
if (actual) {
4009.
var expectedType = objectType(expected);
4010.
4011.
// We don't want to validate thrown error
4012.
if (!expected) {
4013.
result = true;
4014.
4015.
// Expected is a regexp
4016.
} else if (expectedType === "regexp") {
4017.
result = expected.test(errorString(actual));
4018.
4019.
// Log the string form of the regexp
4020.
expected = String(expected);
4021.
4022.
// Expected is a constructor, maybe an Error constructor
4023.
} else if (expectedType === "function" && actual instanceof expected) {
4024.
result = true;
4025.
4026.
// Expected is an Error object
4027.
} else if (expectedType === "object") {
4028.
result = actual instanceof expected.constructor && actual.name === expected.name && actual.message === expected.message;
4029.
4030.
// Log the string form of the Error object
4031.
expected = errorString(expected);
4032.
4033.
// Expected is a validation function which returns true if validation passed
4034.
} else if (expectedType === "function" && expected.call({}, actual) === true) {
4035.
expected = null;
4036.
result = true;
4037.
}
4038.
}
4039.
4040.
currentTest.assert.pushResult({
4041.
result: result,
4042.
4043.
// undefined if it didn't throw
4044.
actual: actual && errorString(actual),
4045.
expected: expected,
4046.
message: message
4047.
});
4048.
}
4049.
}, {
4050.
key: "rejects",
4051.
value: function rejects(promise, expected, message) {
4052.
var result = false;
4053.
4054.
var currentTest = this instanceof Assert && this.test || config.current;
4055.
4056.
// 'expected' is optional unless doing string comparison
4057.
if (objectType(expected) === "string") {
4058.
if (message === undefined) {
4059.
message = expected;
4060.
expected = undefined;
4061.
} else {
4062.
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.";
4063.
4064.
currentTest.assert.pushResult({
4065.
result: false,
4066.
message: message
4067.
});
4068.
4069.
return;
4070.
}
4071.
}
4072.
4073.
var then = promise && promise.then;
4074.
if (objectType(then) !== "function") {
4075.
var _message = "The value provided to `assert.rejects` in " + "\"" + currentTest.testName + "\" was not a promise.";
4076.
4077.
currentTest.assert.pushResult({
4078.
result: false,
4079.
message: _message,
4080.
actual: promise
4081.
});
4082.
4083.
return;
4084.
}
4085.
4086.
var done = this.async();
4087.
4088.
return then.call(promise, function handleFulfillment() {
4089.
var message = "The promise returned by the `assert.rejects` callback in " + "\"" + currentTest.testName + "\" did not reject.";
4090.
4091.
currentTest.assert.pushResult({
4092.
result: false,
4093.
message: message,
4094.
actual: promise
4095.
});
4096.
4097.
done();
4098.
}, function handleRejection(actual) {
4099.
var expectedType = objectType(expected);
4100.
4101.
// We don't want to validate
4102.
if (expected === undefined) {
4103.
result = true;
4104.
4105.
// Expected is a regexp
4106.
} else if (expectedType === "regexp") {
4107.
result = expected.test(errorString(actual));
4108.
4109.
// Log the string form of the regexp
4110.
expected = String(expected);
4111.
4112.
// Expected is a constructor, maybe an Error constructor
4113.
} else if (expectedType === "function" && actual instanceof expected) {
4114.
result = true;
4115.
4116.
// Expected is an Error object
4117.
} else if (expectedType === "object") {
4118.
result = actual instanceof expected.constructor && actual.name === expected.name && actual.message === expected.message;
4119.
4120.
// Log the string form of the Error object
4121.
expected = errorString(expected);
4122.
4123.
// Expected is a validation function which returns true if validation passed
4124.
} else {
4125.
if (expectedType === "function") {
4126.
result = expected.call({}, actual) === true;
4127.
expected = null;
4128.
4129.
// Expected is some other invalid type
4130.
} else {
4131.
result = false;
4132.
message = "invalid expected value provided to `assert.rejects` " + "callback in \"" + currentTest.testName + "\": " + expectedType + ".";
4133.
}
4134.
}
4135.
4136.
currentTest.assert.pushResult({
4137.
result: result,
4138.
4139.
// leave rejection value of undefined as-is
4140.
actual: actual && errorString(actual),
4141.
expected: expected,
4142.
message: message
4143.
});
4144.
4145.
done();
4146.
});
4147.
}
4148.
}]);
4149.
return Assert;
4150.
}();
4151.
4152.
// Provide an alternative to assert.throws(), for environments that consider throws a reserved word
4153.
// Known to us are: Closure Compiler, Narwhal
4154.
// eslint-disable-next-line dot-notation
4155.
4156.
4157.
Assert.prototype.raises = Assert.prototype["throws"];
4158.
4159.
/**
4160.
* Converts an error into a simple string for comparisons.
4161.
*
4162.
* @param {Error|Object} error
4163.
* @return {String}
4164.
*/
4165.
function errorString(error) {
4166.
var resultErrorString = error.toString();
4167.
4168.
// If the error wasn't a subclass of Error but something like
4169.
// an object literal with name and message properties...
4170.
if (resultErrorString.substring(0, 7) === "[object") {
4171.
var name = error.name ? error.name.toString() : "Error";
4172.
var message = error.message ? error.message.toString() : "";
4173.
4174.
if (name && message) {
4175.
return name + ": " + message;
4176.
} else if (name) {
4177.
return name;
4178.
} else if (message) {
4179.
return message;
4180.
} else {
4181.
return "Error";
4182.
}
4183.
} else {
4184.
return resultErrorString;
4185.
}
4186.
}
4187.
4188.
/* global module, exports, define */
4189.
function exportQUnit(QUnit) {
4190.
4191.
if (defined.document) {
4192.
4193.
// QUnit may be defined when it is preconfigured but then only QUnit and QUnit.config may be defined.
4194.
if (window$1.QUnit && window$1.QUnit.version) {
4195.
throw new Error("QUnit has already been defined.");
4196.
}
4197.
4198.
window$1.QUnit = QUnit;
4199.
}
4200.
4201.
// For nodejs
4202.
if (typeof module !== "undefined" && module && module.exports) {
4203.
module.exports = QUnit;
4204.
4205.
// For consistency with CommonJS environments' exports
4206.
module.exports.QUnit = QUnit;
4207.
}
4208.
4209.
// For CommonJS with exports, but without module.exports, like Rhino
4210.
if (typeof exports !== "undefined" && exports) {
4211.
exports.QUnit = QUnit;
4212.
}
4213.
4214.
if (typeof define === "function" && define.amd) {
4215.
define(function () {
4216.
return QUnit;
4217.
});
4218.
QUnit.config.autostart = false;
4219.
}
4220.
4221.
// For Web/Service Workers
4222.
if (self$1 && self$1.WorkerGlobalScope && self$1 instanceof self$1.WorkerGlobalScope) {
4223.
self$1.QUnit = QUnit;
4224.
}
4225.
}
4226.
4227.
// Handle an unhandled exception. By convention, returns true if further
4228.
// error handling should be suppressed and false otherwise.
4229.
// In this case, we will only suppress further error handling if the
4230.
// "ignoreGlobalErrors" configuration option is enabled.
4231.
function onError(error) {
4232.
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
4233.
args[_key - 1] = arguments[_key];
4234.
}
4235.
4236.
if (config.current) {
4237.
if (config.current.ignoreGlobalErrors) {
4238.
return true;
4239.
}
4240.
pushFailure.apply(undefined, [error.message, error.stacktrace || error.fileName + ":" + error.lineNumber].concat(args));
4241.
} else {
4242.
test("global failure", extend(function () {
4243.
pushFailure.apply(undefined, [error.message, error.stacktrace || error.fileName + ":" + error.lineNumber].concat(args));
4244.
}, { validTest: true }));
4245.
}
4246.
4247.
return false;
4248.
}
4249.
4250.
// Handle an unhandled rejection
4251.
function onUnhandledRejection(reason) {
4252.
var resultInfo = {
4253.
result: false,
4254.
message: reason.message || "error",
4255.
actual: reason,
4256.
source: reason.stack || sourceFromStacktrace(3)
4257.
};
4258.
4259.
var currentTest = config.current;
4260.
if (currentTest) {
4261.
currentTest.assert.pushResult(resultInfo);
4262.
} else {
4263.
test("global failure", extend(function (assert) {
4264.
assert.pushResult(resultInfo);
4265.
}, { validTest: true }));
4266.
}
4267.
}
4268.
4269.
var QUnit = {};
4270.
var globalSuite = new SuiteReport();
4271.
4272.
// The initial "currentModule" represents the global (or top-level) module that
4273.
// is not explicitly defined by the user, therefore we add the "globalSuite" to
4274.
// it since each module has a suiteReport associated with it.
4275.
config.currentModule.suiteReport = globalSuite;
4276.
4277.
var globalStartCalled = false;
4278.
var runStarted = false;
4279.
4280.
// Figure out if we're running the tests from a server or not
4281.
QUnit.isLocal = !(defined.document && window$1.location.protocol !== "file:");
4282.
4283.
// Expose the current QUnit version
4284.
QUnit.version = "2.10.0";
4285.
4286.
extend(QUnit, {
4287.
on: on,
4288.
4289.
module: module$1,
4290.
4291.
test: test,
4292.
4293.
todo: todo,
4294.
4295.
skip: skip,
4296.
4297.
only: only,
4298.
4299.
start: function start(count) {
4300.
var globalStartAlreadyCalled = globalStartCalled;
4301.
4302.
if (!config.current) {
4303.
globalStartCalled = true;
4304.
4305.
if (runStarted) {
4306.
throw new Error("Called start() while test already started running");
4307.
} else if (globalStartAlreadyCalled || count > 1) {
4308.
throw new Error("Called start() outside of a test context too many times");
4309.
} else if (config.autostart) {
4310.
throw new Error("Called start() outside of a test context when " + "QUnit.config.autostart was true");
4311.
} else if (!config.pageLoaded) {
4312.
4313.
// The page isn't completely loaded yet, so we set autostart and then
4314.
// load if we're in Node or wait for the browser's load event.
4315.
config.autostart = true;
4316.
4317.
// Starts from Node even if .load was not previously called. We still return
4318.
// early otherwise we'll wind up "beginning" twice.
4319.
if (!defined.document) {
4320.
QUnit.load();
4321.
}
4322.
4323.
return;
4324.
}
4325.
} else {
4326.
throw new Error("QUnit.start cannot be called inside a test context.");
4327.
}
4328.
4329.
scheduleBegin();
4330.
},
4331.
4332.
config: config,
4333.
4334.
is: is,
4335.
4336.
objectType: objectType,
4337.
4338.
extend: extend,
4339.
4340.
load: function load() {
4341.
config.pageLoaded = true;
4342.
4343.
// Initialize the configuration options
4344.
extend(config, {
4345.
stats: { all: 0, bad: 0 },
4346.
started: 0,
4347.
updateRate: 1000,
4348.
autostart: true,
4349.
filter: ""
4350.
}, true);
4351.
4352.
if (!runStarted) {
4353.
config.blocking = false;
4354.
4355.
if (config.autostart) {
4356.
scheduleBegin();
4357.
}
4358.
}
4359.
},
4360.
4361.
stack: function stack(offset) {
4362.
offset = (offset || 0) + 2;
4363.
return sourceFromStacktrace(offset);
4364.
},
4365.
4366.
onError: onError,
4367.
4368.
onUnhandledRejection: onUnhandledRejection
4369.
});
4370.
4371.
QUnit.pushFailure = pushFailure;
4372.
QUnit.assert = Assert.prototype;
4373.
QUnit.equiv = equiv;
4374.
QUnit.dump = dump;
4375.
4376.
registerLoggingCallbacks(QUnit);
4377.
4378.
function scheduleBegin() {
4379.
4380.
runStarted = true;
4381.
4382.
// Add a slight delay to allow definition of more modules and tests.
4383.
if (defined.setTimeout) {
4384.
setTimeout$1(function () {
4385.
begin();
4386.
});
4387.
} else {
4388.
begin();
4389.
}
4390.
}
4391.
4392.
function unblockAndAdvanceQueue() {
4393.
config.blocking = false;
4394.
ProcessingQueue.advance();
4395.
}
4396.
4397.
function begin() {
4398.
var i,
4399.
l,
4400.
modulesLog = [];
4401.
4402.
// If the test run hasn't officially begun yet
4403.
if (!config.started) {
4404.
4405.
// Record the time of the test run's beginning
4406.
config.started = now();
4407.
4408.
// Delete the loose unnamed module if unused.
4409.
if (config.modules[0].name === "" && config.modules[0].tests.length === 0) {
4410.
config.modules.shift();
4411.
}
4412.
4413.
// Avoid unnecessary information by not logging modules' test environments
4414.
for (i = 0, l = config.modules.length; i < l; i++) {
4415.
modulesLog.push({
4416.
name: config.modules[i].name,
4417.
tests: config.modules[i].tests
4418.
});
4419.
}
4420.
4421.
// The test run is officially beginning now
4422.
emit("runStart", globalSuite.start(true));
4423.
runLoggingCallbacks("begin", {
4424.
totalTests: Test.count,
4425.
modules: modulesLog
4426.
}).then(unblockAndAdvanceQueue);
4427.
} else {
4428.
unblockAndAdvanceQueue();
4429.
}
4430.
}
4431.
4432.
exportQUnit(QUnit);
4433.
4434.
(function () {
4435.
4436.
if (typeof window$1 === "undefined" || typeof document$1 === "undefined") {
4437.
return;
4438.
}
4439.
4440.
var config = QUnit.config,
4441.
hasOwn = Object.prototype.hasOwnProperty;
4442.
4443.
// Stores fixture HTML for resetting later
4444.
function storeFixture() {
4445.
4446.
// Avoid overwriting user-defined values
4447.
if (hasOwn.call(config, "fixture")) {
4448.
return;
4449.
}
4450.
4451.
var fixture = document$1.getElementById("qunit-fixture");
4452.
if (fixture) {
4453.
config.fixture = fixture.cloneNode(true);
4454.
}
4455.
}
4456.
4457.
QUnit.begin(storeFixture);
4458.
4459.
// Resets the fixture DOM element if available.
4460.
function resetFixture() {
4461.
if (config.fixture == null) {
4462.
return;
4463.
}
4464.
4465.
var fixture = document$1.getElementById("qunit-fixture");
4466.
var resetFixtureType = _typeof(config.fixture);
4467.
if (resetFixtureType === "string") {
4468.
4469.
// support user defined values for `config.fixture`
4470.
var newFixture = document$1.createElement("div");
4471.
newFixture.setAttribute("id", "qunit-fixture");
4472.
newFixture.innerHTML = config.fixture;
4473.
fixture.parentNode.replaceChild(newFixture, fixture);
4474.
} else {
4475.
var clonedFixture = config.fixture.cloneNode(true);
4476.
fixture.parentNode.replaceChild(clonedFixture, fixture);
4477.
}
4478.
}
4479.
4480.
QUnit.testStart(resetFixture);
4481.
})();
4482.
4483.
(function () {
4484.
4485.
// Only interact with URLs via window.location
4486.
var location = typeof window$1 !== "undefined" && window$1.location;
4487.
if (!location) {
4488.
return;
4489.
}
4490.
4491.
var urlParams = getUrlParams();
4492.
4493.
QUnit.urlParams = urlParams;
4494.
4495.
// Match module/test by inclusion in an array
4496.
QUnit.config.moduleId = [].concat(urlParams.moduleId || []);
4497.
QUnit.config.testId = [].concat(urlParams.testId || []);
4498.
4499.
// Exact case-insensitive match of the module name
4500.
QUnit.config.module = urlParams.module;
4501.
4502.
// Regular expression or case-insenstive substring match against "moduleName: testName"
4503.
QUnit.config.filter = urlParams.filter;
4504.
4505.
// Test order randomization
4506.
if (urlParams.seed === true) {
4507.
4508.
// Generate a random seed if the option is specified without a value
4509.
QUnit.config.seed = Math.random().toString(36).slice(2);
4510.
} else if (urlParams.seed) {
4511.
QUnit.config.seed = urlParams.seed;
4512.
}
4513.
4514.
// Add URL-parameter-mapped config values with UI form rendering data
4515.
QUnit.config.urlConfig.push({
4516.
id: "hidepassed",
4517.
label: "Hide passed tests",
4518.
tooltip: "Only show tests and assertions that fail. Stored as query-strings."
4519.
}, {
4520.
id: "noglobals",
4521.
label: "Check for Globals",
4522.
tooltip: "Enabling this will test if any test introduces new properties on the " + "global object (`window` in Browsers). Stored as query-strings."
4523.
}, {
4524.
id: "notrycatch",
4525.
label: "No try-catch",
4526.
tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " + "exceptions in IE reasonable. Stored as query-strings."
4527.
});
4528.
4529.
QUnit.begin(function () {
4530.
var i,
4531.
option,
4532.
urlConfig = QUnit.config.urlConfig;
4533.
4534.
for (i = 0; i < urlConfig.length; i++) {
4535.
4536.
// Options can be either strings or objects with nonempty "id" properties
4537.
option = QUnit.config.urlConfig[i];
4538.
if (typeof option !== "string") {
4539.
option = option.id;
4540.
}
4541.
4542.
if (QUnit.config[option] === undefined) {
4543.
QUnit.config[option] = urlParams[option];
4544.
}
4545.
}
4546.
});
4547.
4548.
function getUrlParams() {
4549.
var i, param, name, value;
4550.
var urlParams = Object.create(null);
4551.
var params = location.search.slice(1).split("&");
4552.
var length = params.length;
4553.
4554.
for (i = 0; i < length; i++) {
4555.
if (params[i]) {
4556.
param = params[i].split("=");
4557.
name = decodeQueryParam(param[0]);
4558.
4559.
// Allow just a key to turn on a flag, e.g., test.html?noglobals
4560.
value = param.length === 1 || decodeQueryParam(param.slice(1).join("="));
4561.
if (name in urlParams) {
4562.
urlParams[name] = [].concat(urlParams[name], value);
4563.
} else {
4564.
urlParams[name] = value;
4565.
}
4566.
}
4567.
}
4568.
4569.
return urlParams;
4570.
}
4571.
4572.
function decodeQueryParam(param) {
4573.
return decodeURIComponent(param.replace(/\+/g, "%20"));
4574.
}
4575.
})();
4576.
4577.
var stats = {
4578.
passedTests: 0,
4579.
failedTests: 0,
4580.
skippedTests: 0,
4581.
todoTests: 0
4582.
};
4583.
4584.
// Escape text for attribute or text content.
4585.
function escapeText(s) {
4586.
if (!s) {
4587.
return "";
4588.
}
4589.
s = s + "";
4590.
4591.
// Both single quotes and double quotes (for attributes)
4592.
return s.replace(/['"<>&]/g, function (s) {
4593.
switch (s) {
4594.
case "'":
4595.
return "'";
4596.
case "\"":
4597.
return """;
4598.
case "<":
4599.
return "<";
4600.
case ">":
4601.
return ">";
4602.
case "&":
4603.
return "&";
4604.
}
4605.
});
4606.
}
4607.
4608.
(function () {
4609.
4610.
// Don't load the HTML Reporter on non-browser environments
4611.
if (typeof window$1 === "undefined" || !window$1.document) {
4612.
return;
4613.
}
4614.
4615.
var config = QUnit.config,
4616.
hiddenTests = [],
4617.
document = window$1.document,
4618.
collapseNext = false,
4619.
hasOwn$$1 = Object.prototype.hasOwnProperty,
4620.
unfilteredUrl = setUrl({ filter: undefined, module: undefined,
4621.
moduleId: undefined, testId: undefined }),
4622.
modulesList = [];
4623.
4624.
function addEvent(elem, type, fn) {
4625.
elem.addEventListener(type, fn, false);
4626.
}
4627.
4628.
function removeEvent(elem, type, fn) {
4629.
elem.removeEventListener(type, fn, false);
4630.
}
4631.
4632.
function addEvents(elems, type, fn) {
4633.
var i = elems.length;
4634.
while (i--) {
4635.
addEvent(elems[i], type, fn);
4636.
}
4637.
}
4638.
4639.
function hasClass(elem, name) {
4640.
return (" " + elem.className + " ").indexOf(" " + name + " ") >= 0;
4641.
}
4642.
4643.
function addClass(elem, name) {
4644.
if (!hasClass(elem, name)) {
4645.
elem.className += (elem.className ? " " : "") + name;
4646.
}
4647.
}
4648.
4649.
function toggleClass(elem, name, force) {
4650.
if (force || typeof force === "undefined" && !hasClass(elem, name)) {
4651.
addClass(elem, name);
4652.
} else {
4653.
removeClass(elem, name);
4654.
}
4655.
}
4656.
4657.
function removeClass(elem, name) {
4658.
var set = " " + elem.className + " ";
4659.
4660.
// Class name may appear multiple times
4661.
while (set.indexOf(" " + name + " ") >= 0) {
4662.
set = set.replace(" " + name + " ", " ");
4663.
}
4664.
4665.
// Trim for prettiness
4666.
elem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\s+|\s+$/g, "");
4667.
}
4668.
4669.
function id(name) {
4670.
return document.getElementById && document.getElementById(name);
4671.
}
4672.
4673.
function abortTests() {
4674.
var abortButton = id("qunit-abort-tests-button");
4675.
if (abortButton) {
4676.
abortButton.disabled = true;
4677.
abortButton.innerHTML = "Aborting...";
4678.
}
4679.
QUnit.config.queue.length = 0;
4680.
return false;
4681.
}
4682.
4683.
function interceptNavigation(ev) {
4684.
applyUrlParams();
4685.
4686.
if (ev && ev.preventDefault) {
4687.
ev.preventDefault();
4688.
}
4689.
4690.
return false;
4691.
}
4692.
4693.
function getUrlConfigHtml() {
4694.
var i,
4695.
j,
4696.
val,
4697.
escaped,
4698.
escapedTooltip,
4699.
selection = false,
4700.
urlConfig = config.urlConfig,
4701.
urlConfigHtml = "";
4702.
4703.
for (i = 0; i < urlConfig.length; i++) {
4704.
4705.
// Options can be either strings or objects with nonempty "id" properties
4706.
val = config.urlConfig[i];
4707.
if (typeof val === "string") {
4708.
val = {
4709.
id: val,
4710.
label: val
4711.
};
4712.
}
4713.
4714.
escaped = escapeText(val.id);
4715.
escapedTooltip = escapeText(val.tooltip);
4716.
4717.
if (!val.value || typeof val.value === "string") {
4718.
urlConfigHtml += "<label for='qunit-urlconfig-" + escaped + "' title='" + escapedTooltip + "'><input id='qunit-urlconfig-" + escaped + "' name='" + escaped + "' type='checkbox'" + (val.value ? " value='" + escapeText(val.value) + "'" : "") + (config[val.id] ? " checked='checked'" : "") + " title='" + escapedTooltip + "' />" + escapeText(val.label) + "</label>";
4719.
} else {
4720.
urlConfigHtml += "<label for='qunit-urlconfig-" + escaped + "' title='" + escapedTooltip + "'>" + val.label + ": </label><select id='qunit-urlconfig-" + escaped + "' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>";
4721.
4722.
if (QUnit.is("array", val.value)) {
4723.
for (j = 0; j < val.value.length; j++) {
4724.
escaped = escapeText(val.value[j]);
4725.
urlConfigHtml += "<option value='" + escaped + "'" + (config[val.id] === val.value[j] ? (selection = true) && " selected='selected'" : "") + ">" + escaped + "</option>";
4726.
}
4727.
} else {
4728.
for (j in val.value) {
4729.
if (hasOwn$$1.call(val.value, j)) {
4730.
urlConfigHtml += "<option value='" + escapeText(j) + "'" + (config[val.id] === j ? (selection = true) && " selected='selected'" : "") + ">" + escapeText(val.value[j]) + "</option>";
4731.
}
4732.
}
4733.
}
4734.
if (config[val.id] && !selection) {
4735.
escaped = escapeText(config[val.id]);
4736.
urlConfigHtml += "<option value='" + escaped + "' selected='selected' disabled='disabled'>" + escaped + "</option>";
4737.
}
4738.
urlConfigHtml += "</select>";
4739.
}
4740.
}
4741.
4742.
return urlConfigHtml;
4743.
}
4744.
4745.
// Handle "click" events on toolbar checkboxes and "change" for select menus.
4746.
// Updates the URL with the new state of `config.urlConfig` values.
4747.
function toolbarChanged() {
4748.
var updatedUrl,
4749.
value,
4750.
tests,
4751.
field = this,
4752.
params = {};
4753.
4754.
// Detect if field is a select menu or a checkbox
4755.
if ("selectedIndex" in field) {
4756.
value = field.options[field.selectedIndex].value || undefined;
4757.
} else {
4758.
value = field.checked ? field.defaultValue || true : undefined;
4759.
}
4760.
4761.
params[field.name] = value;
4762.
updatedUrl = setUrl(params);
4763.
4764.
// Check if we can apply the change without a page refresh
4765.
if ("hidepassed" === field.name && "replaceState" in window$1.history) {
4766.
QUnit.urlParams[field.name] = value;
4767.
config[field.name] = value || false;
4768.
tests = id("qunit-tests");
4769.
if (tests) {
4770.
var length = tests.children.length;
4771.
var children = tests.children;
4772.
4773.
if (field.checked) {
4774.
for (var i = 0; i < length; i++) {
4775.
var test$$1 = children[i];
4776.
4777.
if (test$$1 && test$$1.className.indexOf("pass") > -1) {
4778.
hiddenTests.push(test$$1);
4779.
}
4780.
}
4781.
4782.
var _iteratorNormalCompletion = true;
4783.
var _didIteratorError = false;
4784.
var _iteratorError = undefined;
4785.
4786.
try {
4787.
for (var _iterator = hiddenTests[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
4788.
var hiddenTest = _step.value;
4789.
4790.
tests.removeChild(hiddenTest);
4791.
}
4792.
} catch (err) {
4793.
_didIteratorError = true;
4794.
_iteratorError = err;
4795.
} finally {
4796.
try {
4797.
if (!_iteratorNormalCompletion && _iterator.return) {
4798.
_iterator.return();
4799.
}
4800.
} finally {
4801.
if (_didIteratorError) {
4802.
throw _iteratorError;
4803.
}
4804.
}
4805.
}
4806.
} else {
4807.
while ((test$$1 = hiddenTests.pop()) != null) {
4808.
tests.appendChild(test$$1);
4809.
}
4810.
}
4811.
}
4812.
window$1.history.replaceState(null, "", updatedUrl);
4813.
} else {
4814.
window$1.location = updatedUrl;
4815.
}
4816.
}
4817.
4818.
function setUrl(params) {
4819.
var key,
4820.
arrValue,
4821.
i,
4822.
querystring = "?",
4823.
location = window$1.location;
4824.
4825.
params = QUnit.extend(QUnit.extend({}, QUnit.urlParams), params);
4826.
4827.
for (key in params) {
4828.
4829.
// Skip inherited or undefined properties
4830.
if (hasOwn$$1.call(params, key) && params[key] !== undefined) {
4831.
4832.
// Output a parameter for each value of this key
4833.
// (but usually just one)
4834.
arrValue = [].concat(params[key]);
4835.
for (i = 0; i < arrValue.length; i++) {
4836.
querystring += encodeURIComponent(key);
4837.
if (arrValue[i] !== true) {
4838.
querystring += "=" + encodeURIComponent(arrValue[i]);
4839.
}
4840.
querystring += "&";
4841.
}
4842.
}
4843.
}
4844.
return location.protocol + "//" + location.host + location.pathname + querystring.slice(0, -1);
4845.
}
4846.
4847.
function applyUrlParams() {
4848.
var i,
4849.
selectedModules = [],
4850.
modulesList = id("qunit-modulefilter-dropdown-list").getElementsByTagName("input"),
4851.
filter = id("qunit-filter-input").value;
4852.
4853.
for (i = 0; i < modulesList.length; i++) {
4854.
if (modulesList[i].checked) {
4855.
selectedModules.push(modulesList[i].value);
4856.
}
4857.
}
4858.
4859.
window$1.location = setUrl({
4860.
filter: filter === "" ? undefined : filter,
4861.
moduleId: selectedModules.length === 0 ? undefined : selectedModules,
4862.
4863.
// Remove module and testId filter
4864.
module: undefined,
4865.
testId: undefined
4866.
});
4867.
}
4868.
4869.
function toolbarUrlConfigContainer() {
4870.
var urlConfigContainer = document.createElement("span");
4871.
4872.
urlConfigContainer.innerHTML = getUrlConfigHtml();
4873.
addClass(urlConfigContainer, "qunit-url-config");
4874.
4875.
addEvents(urlConfigContainer.getElementsByTagName("input"), "change", toolbarChanged);
4876.
addEvents(urlConfigContainer.getElementsByTagName("select"), "change", toolbarChanged);
4877.
4878.
return urlConfigContainer;
4879.
}
4880.
4881.
function abortTestsButton() {
4882.
var button = document.createElement("button");
4883.
button.id = "qunit-abort-tests-button";
4884.
button.innerHTML = "Abort";
4885.
addEvent(button, "click", abortTests);
4886.
return button;
4887.
}
4888.
4889.
function toolbarLooseFilter() {
4890.
var filter = document.createElement("form"),
4891.
label = document.createElement("label"),
4892.
input = document.createElement("input"),
4893.
button = document.createElement("button");
4894.
4895.
addClass(filter, "qunit-filter");
4896.
4897.
label.innerHTML = "Filter: ";
4898.
4899.
input.type = "text";
4900.
input.value = config.filter || "";
4901.
input.name = "filter";
4902.
input.id = "qunit-filter-input";
4903.
4904.
button.innerHTML = "Go";
4905.
4906.
label.appendChild(input);
4907.
4908.
filter.appendChild(label);
4909.
filter.appendChild(document.createTextNode(" "));
4910.
filter.appendChild(button);
4911.
addEvent(filter, "submit", interceptNavigation);
4912.
4913.
return filter;
4914.
}
4915.
4916.
function moduleListHtml() {
4917.
var i,
4918.
checked,
4919.
html = "";
4920.
4921.
for (i = 0; i < config.modules.length; i++) {
4922.
if (config.modules[i].name !== "") {
4923.
checked = config.moduleId.indexOf(config.modules[i].moduleId) > -1;
4924.
html += "<li><label class='clickable" + (checked ? " checked" : "") + "'><input type='checkbox' " + "value='" + config.modules[i].moduleId + "'" + (checked ? " checked='checked'" : "") + " />" + escapeText(config.modules[i].name) + "</label></li>";
4925.
}
4926.
}
4927.
4928.
return html;
4929.
}
4930.
4931.
function toolbarModuleFilter() {
4932.
var commit,
4933.
reset,
4934.
moduleFilter = document.createElement("form"),
4935.
label = document.createElement("label"),
4936.
moduleSearch = document.createElement("input"),
4937.
dropDown = document.createElement("div"),
4938.
actions = document.createElement("span"),
4939.
applyButton = document.createElement("button"),
4940.
resetButton = document.createElement("button"),
4941.
allModulesLabel = document.createElement("label"),
4942.
allCheckbox = document.createElement("input"),
4943.
dropDownList = document.createElement("ul"),
4944.
dirty = false;
4945.
4946.
moduleSearch.id = "qunit-modulefilter-search";
4947.
moduleSearch.autocomplete = "off";
4948.
addEvent(moduleSearch, "input", searchInput);
4949.
addEvent(moduleSearch, "input", searchFocus);
4950.
addEvent(moduleSearch, "focus", searchFocus);
4951.
addEvent(moduleSearch, "click", searchFocus);
4952.
4953.
label.id = "qunit-modulefilter-search-container";
4954.
label.innerHTML = "Module: ";
4955.
label.appendChild(moduleSearch);
4956.
4957.
applyButton.textContent = "Apply";
4958.
applyButton.style.display = "none";
4959.
4960.
resetButton.textContent = "Reset";
4961.
resetButton.type = "reset";
4962.
resetButton.style.display = "none";
4963.
4964.
allCheckbox.type = "checkbox";
4965.
allCheckbox.checked = config.moduleId.length === 0;
4966.
4967.
allModulesLabel.className = "clickable";
4968.
if (config.moduleId.length) {
4969.
allModulesLabel.className = "checked";
4970.
}
4971.
allModulesLabel.appendChild(allCheckbox);
4972.
allModulesLabel.appendChild(document.createTextNode("All modules"));
4973.
4974.
actions.id = "qunit-modulefilter-actions";
4975.
actions.appendChild(applyButton);
4976.
actions.appendChild(resetButton);
4977.
actions.appendChild(allModulesLabel);
4978.
commit = actions.firstChild;
4979.
reset = commit.nextSibling;
4980.
addEvent(commit, "click", applyUrlParams);
4981.
4982.
dropDownList.id = "qunit-modulefilter-dropdown-list";
4983.
dropDownList.innerHTML = moduleListHtml();
4984.
4985.
dropDown.id = "qunit-modulefilter-dropdown";
4986.
dropDown.style.display = "none";
4987.
dropDown.appendChild(actions);
4988.
dropDown.appendChild(dropDownList);
4989.
addEvent(dropDown, "change", selectionChange);
4990.
selectionChange();
4991.
4992.
moduleFilter.id = "qunit-modulefilter";
4993.
moduleFilter.appendChild(label);
4994.
moduleFilter.appendChild(dropDown);
4995.
addEvent(moduleFilter, "submit", interceptNavigation);
4996.
addEvent(moduleFilter, "reset", function () {
4997.
4998.
// Let the reset happen, then update styles
4999.
window$1.setTimeout(selectionChange);
5000.
});
5001.
5002.
// Enables show/hide for the dropdown
5003.
function searchFocus() {
5004.
if (dropDown.style.display !== "none") {
5005.
return;
5006.
}
5007.
5008.
dropDown.style.display = "block";
5009.
addEvent(document, "click", hideHandler);
5010.
addEvent(document, "keydown", hideHandler);
5011.
5012.
// Hide on Escape keydown or outside-container click
5013.
function hideHandler(e) {
5014.
var inContainer = moduleFilter.contains(e.target);
5015.
5016.
if (e.keyCode === 27 || !inContainer) {
5017.
if (e.keyCode === 27 && inContainer) {
5018.
moduleSearch.focus();
5019.
}
5020.
dropDown.style.display = "none";
5021.
removeEvent(document, "click", hideHandler);
5022.
removeEvent(document, "keydown", hideHandler);
5023.
moduleSearch.value = "";
5024.
searchInput();
5025.
}
5026.
}
5027.
}
5028.
5029.
// Processes module search box input
5030.
function searchInput() {
5031.
var i,
5032.
item,
5033.
searchText = moduleSearch.value.toLowerCase(),
5034.
listItems = dropDownList.children;
5035.
5036.
for (i = 0; i < listItems.length; i++) {
5037.
item = listItems[i];
5038.
if (!searchText || item.textContent.toLowerCase().indexOf(searchText) > -1) {
5039.
item.style.display = "";
5040.
} else {
5041.
item.style.display = "none";
5042.
}
5043.
}
5044.
}
5045.
5046.
// Processes selection changes
5047.
function selectionChange(evt) {
5048.
var i,
5049.
item,
5050.
checkbox = evt && evt.target || allCheckbox,
5051.
modulesList = dropDownList.getElementsByTagName("input"),
5052.
selectedNames = [];
5053.
5054.
toggleClass(checkbox.parentNode, "checked", checkbox.checked);
5055.
5056.
dirty = false;
5057.
if (checkbox.checked && checkbox !== allCheckbox) {
5058.
allCheckbox.checked = false;
5059.
removeClass(allCheckbox.parentNode, "checked");
5060.
}
5061.
for (i = 0; i < modulesList.length; i++) {
5062.
item = modulesList[i];
5063.
if (!evt) {
5064.
toggleClass(item.parentNode, "checked", item.checked);
5065.
} else if (checkbox === allCheckbox && checkbox.checked) {
5066.
item.checked = false;
5067.
removeClass(item.parentNode, "checked");
5068.
}
5069.
dirty = dirty || item.checked !== item.defaultChecked;
5070.
if (item.checked) {
5071.
selectedNames.push(item.parentNode.textContent);
5072.
}
5073.
}
5074.
5075.
commit.style.display = reset.style.display = dirty ? "" : "none";
5076.
moduleSearch.placeholder = selectedNames.join(", ") || allCheckbox.parentNode.textContent;
5077.
moduleSearch.title = "Type to filter list. Current selection:\n" + (selectedNames.join("\n") || allCheckbox.parentNode.textContent);
5078.
}
5079.
5080.
return moduleFilter;
5081.
}
5082.
5083.
function toolbarFilters() {
5084.
var toolbarFilters = document.createElement("span");
5085.
5086.
toolbarFilters.id = "qunit-toolbar-filters";
5087.
toolbarFilters.appendChild(toolbarLooseFilter());
5088.
toolbarFilters.appendChild(toolbarModuleFilter());
5089.
5090.
return toolbarFilters;
5091.
}
5092.
5093.
function appendToolbar() {
5094.
var toolbar = id("qunit-testrunner-toolbar");
5095.
5096.
if (toolbar) {
5097.
toolbar.appendChild(toolbarUrlConfigContainer());
5098.
toolbar.appendChild(toolbarFilters());
5099.
toolbar.appendChild(document.createElement("div")).className = "clearfix";
5100.
}
5101.
}
5102.
5103.
function appendHeader() {
5104.
var header = id("qunit-header");
5105.
5106.
if (header) {
5107.
header.innerHTML = "<a href='" + escapeText(unfilteredUrl) + "'>" + header.innerHTML + "</a> ";
5108.
}
5109.
}
5110.
5111.
function appendBanner() {
5112.
var banner = id("qunit-banner");
5113.
5114.
if (banner) {
5115.
banner.className = "";
5116.
}
5117.
}
5118.
5119.
function appendTestResults() {
5120.
var tests = id("qunit-tests"),
5121.
result = id("qunit-testresult"),
5122.
controls;
5123.
5124.
if (result) {
5125.
result.parentNode.removeChild(result);
5126.
}
5127.
5128.
if (tests) {
5129.
tests.innerHTML = "";
5130.
result = document.createElement("p");
5131.
result.id = "qunit-testresult";
5132.
result.className = "result";
5133.
tests.parentNode.insertBefore(result, tests);
5134.
result.innerHTML = "<div id=\"qunit-testresult-display\">Running...<br /> </div>" + "<div id=\"qunit-testresult-controls\"></div>" + "<div class=\"clearfix\"></div>";
5135.
controls = id("qunit-testresult-controls");
5136.
}
5137.
5138.
if (controls) {
5139.
controls.appendChild(abortTestsButton());
5140.
}
5141.
}
5142.
5143.
function appendFilteredTest() {
5144.
var testId = QUnit.config.testId;
5145.
if (!testId || testId.length <= 0) {
5146.
return "";
5147.
}
5148.
return "<div id='qunit-filteredTest'>Rerunning selected tests: " + escapeText(testId.join(", ")) + " <a id='qunit-clearFilter' href='" + escapeText(unfilteredUrl) + "'>Run all tests</a></div>";
5149.
}
5150.
5151.
function appendUserAgent() {
5152.
var userAgent = id("qunit-userAgent");
5153.
5154.
if (userAgent) {
5155.
userAgent.innerHTML = "";
5156.
userAgent.appendChild(document.createTextNode("QUnit " + QUnit.version + "; " + navigator.userAgent));
5157.
}
5158.
}
5159.
5160.
function appendInterface() {
5161.
var qunit = id("qunit");
5162.
5163.
if (qunit) {
5164.
qunit.innerHTML = "<h1 id='qunit-header'>" + escapeText(document.title) + "</h1>" + "<h2 id='qunit-banner'></h2>" + "<div id='qunit-testrunner-toolbar'></div>" + appendFilteredTest() + "<h2 id='qunit-userAgent'></h2>" + "<ol id='qunit-tests'></ol>";
5165.
}
5166.
5167.
appendHeader();
5168.
appendBanner();
5169.
appendTestResults();
5170.
appendUserAgent();
5171.
appendToolbar();
5172.
}
5173.
5174.
function appendTest(name, testId, moduleName) {
5175.
var title,
5176.
rerunTrigger,
5177.
testBlock,
5178.
assertList,
5179.
tests = id("qunit-tests");
5180.
5181.
if (!tests) {
5182.
return;
5183.
}
5184.
5185.
title = document.createElement("strong");
5186.
title.innerHTML = getNameHtml(name, moduleName);
5187.
5188.
rerunTrigger = document.createElement("a");
5189.
rerunTrigger.innerHTML = "Rerun";
5190.
rerunTrigger.href = setUrl({ testId: testId });
5191.
5192.
testBlock = document.createElement("li");
5193.
testBlock.appendChild(title);
5194.
testBlock.appendChild(rerunTrigger);
5195.
testBlock.id = "qunit-test-output-" + testId;
5196.
5197.
assertList = document.createElement("ol");
5198.
assertList.className = "qunit-assert-list";
5199.
5200.
testBlock.appendChild(assertList);
5201.
5202.
tests.appendChild(testBlock);
5203.
}
5204.
5205.
// HTML Reporter initialization and load
5206.
QUnit.begin(function (details) {
5207.
var i, moduleObj;
5208.
5209.
// Sort modules by name for the picker
5210.
for (i = 0; i < details.modules.length; i++) {
5211.
moduleObj = details.modules[i];
5212.
if (moduleObj.name) {
5213.
modulesList.push(moduleObj.name);
5214.
}
5215.
}
5216.
modulesList.sort(function (a, b) {
5217.
return a.localeCompare(b);
5218.
});
5219.
5220.
// Initialize QUnit elements
5221.
appendInterface();
5222.
});
5223.
5224.
QUnit.done(function (details) {
5225.
var banner = id("qunit-banner"),
5226.
tests = id("qunit-tests"),
5227.
abortButton = id("qunit-abort-tests-button"),
5228.
totalTests = stats.passedTests + stats.skippedTests + stats.todoTests + stats.failedTests,
5229.
html = [totalTests, " tests completed in ", details.runtime, " milliseconds, with ", stats.failedTests, " failed, ", stats.skippedTests, " skipped, and ", stats.todoTests, " todo.<br />", "<span class='passed'>", details.passed, "</span> assertions of <span class='total'>", details.total, "</span> passed, <span class='failed'>", details.failed, "</span> failed."].join(""),
5230.
test$$1,
5231.
assertLi,
5232.
assertList;
5233.
5234.
// Update remaining tests to aborted
5235.
if (abortButton && abortButton.disabled) {
5236.
html = "Tests aborted after " + details.runtime + " milliseconds.";
5237.
5238.
for (var i = 0; i < tests.children.length; i++) {
5239.
test$$1 = tests.children[i];
5240.
if (test$$1.className === "" || test$$1.className === "running") {
5241.
test$$1.className = "aborted";
5242.
assertList = test$$1.getElementsByTagName("ol")[0];
5243.
assertLi = document.createElement("li");
5244.
assertLi.className = "fail";
5245.
assertLi.innerHTML = "Test aborted.";
5246.
assertList.appendChild(assertLi);
5247.
}
5248.
}
5249.
}
5250.
5251.
if (banner && (!abortButton || abortButton.disabled === false)) {
5252.
banner.className = stats.failedTests ? "qunit-fail" : "qunit-pass";
5253.
}
5254.
5255.
if (abortButton) {
5256.
abortButton.parentNode.removeChild(abortButton);
5257.
}
5258.
5259.
if (tests) {
5260.
id("qunit-testresult-display").innerHTML = html;
5261.
}
5262.
5263.
if (config.altertitle && document.title) {
5264.
5265.
// Show ✖ for good, ✔ for bad suite result in title
5266.
// use escape sequences in case file gets loaded with non-utf-8
5267.
// charset
5268.
document.title = [stats.failedTests ? "\u2716" : "\u2714", document.title.replace(/^[\u2714\u2716] /i, "")].join(" ");
5269.
}
5270.
5271.
// Scroll back to top to show results
5272.
if (config.scrolltop && window$1.scrollTo) {
5273.
window$1.scrollTo(0, 0);
5274.
}
5275.
});
5276.
5277.
function getNameHtml(name, module) {
5278.
var nameHtml = "";
5279.
5280.
if (module) {
5281.
nameHtml = "<span class='module-name'>" + escapeText(module) + "</span>: ";
5282.
}
5283.
5284.
nameHtml += "<span class='test-name'>" + escapeText(name) + "</span>";
5285.
5286.
return nameHtml;
5287.
}
5288.
5289.
function getProgressHtml(runtime, stats, total) {
5290.
var completed = stats.passedTests + stats.skippedTests + stats.todoTests + stats.failedTests;
5291.
5292.
return ["<br />", completed, " / ", total, " tests completed in ", runtime, " milliseconds, with ", stats.failedTests, " failed, ", stats.skippedTests, " skipped, and ", stats.todoTests, " todo."].join("");
5293.
}
5294.
5295.
QUnit.testStart(function (details) {
5296.
var running, bad;
5297.
5298.
appendTest(details.name, details.testId, details.module);
5299.
5300.
running = id("qunit-testresult-display");
5301.
5302.
if (running) {
5303.
addClass(running, "running");
5304.
5305.
bad = QUnit.config.reorder && details.previousFailure;
5306.
5307.
running.innerHTML = [bad ? "Rerunning previously failed test: <br />" : "Running: <br />", getNameHtml(details.name, details.module), getProgressHtml(now() - config.started, stats, Test.count)].join("");
5308.
}
5309.
});
5310.
5311.
function stripHtml(string) {
5312.
5313.
// Strip tags, html entity and whitespaces
5314.
return string.replace(/<\/?[^>]+(>|$)/g, "").replace(/"/g, "").replace(/\s+/g, "");
5315.
}
5316.
5317.
QUnit.log(function (details) {
5318.
var assertList,
5319.
assertLi,
5320.
message,
5321.
expected,
5322.
actual,
5323.
diff$$1,
5324.
showDiff = false,
5325.
testItem = id("qunit-test-output-" + details.testId);
5326.
5327.
if (!testItem) {
5328.
return;
5329.
}
5330.
5331.
message = escapeText(details.message) || (details.result ? "okay" : "failed");
5332.
message = "<span class='test-message'>" + message + "</span>";
5333.
message += "<span class='runtime'>@ " + details.runtime + " ms</span>";
5334.
5335.
// The pushFailure doesn't provide details.expected
5336.
// when it calls, it's implicit to also not show expected and diff stuff
5337.
// Also, we need to check details.expected existence, as it can exist and be undefined
5338.
if (!details.result && hasOwn$$1.call(details, "expected")) {
5339.
if (details.negative) {
5340.
expected = "NOT " + QUnit.dump.parse(details.expected);
5341.
} else {
5342.
expected = QUnit.dump.parse(details.expected);
5343.
}
5344.
5345.
actual = QUnit.dump.parse(details.actual);
5346.
message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + escapeText(expected) + "</pre></td></tr>";
5347.
5348.
if (actual !== expected) {
5349.
5350.
message += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText(actual) + "</pre></td></tr>";
5351.
5352.
if (typeof details.actual === "number" && typeof details.expected === "number") {
5353.
if (!isNaN(details.actual) && !isNaN(details.expected)) {
5354.
showDiff = true;
5355.
diff$$1 = details.actual - details.expected;
5356.
diff$$1 = (diff$$1 > 0 ? "+" : "") + diff$$1;
5357.
}
5358.
} else if (typeof details.actual !== "boolean" && typeof details.expected !== "boolean") {
5359.
diff$$1 = QUnit.diff(expected, actual);
5360.
5361.
// don't show diff if there is zero overlap
5362.
showDiff = stripHtml(diff$$1).length !== stripHtml(expected).length + stripHtml(actual).length;
5363.
}
5364.
5365.
if (showDiff) {
5366.
message += "<tr class='test-diff'><th>Diff: </th><td><pre>" + diff$$1 + "</pre></td></tr>";
5367.
}
5368.
} else if (expected.indexOf("[object Array]") !== -1 || expected.indexOf("[object Object]") !== -1) {
5369.
message += "<tr class='test-message'><th>Message: </th><td>" + "Diff suppressed as the depth of object is more than current max depth (" + QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " + " run with a higher max depth or <a href='" + escapeText(setUrl({ maxDepth: -1 })) + "'>" + "Rerun</a> without max depth.</p></td></tr>";
5370.
} else {
5371.
message += "<tr class='test-message'><th>Message: </th><td>" + "Diff suppressed as the expected and actual results have an equivalent" + " serialization</td></tr>";
5372.
}
5373.
5374.
if (details.source) {
5375.
message += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText(details.source) + "</pre></td></tr>";
5376.
}
5377.
5378.
message += "</table>";
5379.
5380.
// This occurs when pushFailure is set and we have an extracted stack trace
5381.
} else if (!details.result && details.source) {
5382.
message += "<table>" + "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText(details.source) + "</pre></td></tr>" + "</table>";
5383.
}
5384.
5385.
assertList = testItem.getElementsByTagName("ol")[0];
5386.
5387.
assertLi = document.createElement("li");
5388.
assertLi.className = details.result ? "pass" : "fail";
5389.
assertLi.innerHTML = message;
5390.
assertList.appendChild(assertLi);
5391.
});
5392.
5393.
QUnit.testDone(function (details) {
5394.
var testTitle,
5395.
time,
5396.
testItem,
5397.
assertList,
5398.
status,
5399.
good,
5400.
bad,
5401.
testCounts,
5402.
skipped,
5403.
sourceName,
5404.
tests = id("qunit-tests");
5405.
5406.
if (!tests) {
5407.
return;
5408.
}
5409.
5410.
testItem = id("qunit-test-output-" + details.testId);
5411.
5412.
removeClass(testItem, "running");
5413.
5414.
if (details.failed > 0) {
5415.
status = "failed";
5416.
} else if (details.todo) {
5417.
status = "todo";
5418.
} else {
5419.
status = details.skipped ? "skipped" : "passed";
5420.
}
5421.
5422.
assertList = testItem.getElementsByTagName("ol")[0];
5423.
5424.
good = details.passed;
5425.
bad = details.failed;
5426.
5427.
// This test passed if it has no unexpected failed assertions
5428.
var testPassed = details.failed > 0 ? details.todo : !details.todo;
5429.
5430.
if (testPassed) {
5431.
5432.
// Collapse the passing tests
5433.
addClass(assertList, "qunit-collapsed");
5434.
} else if (config.collapse) {
5435.
if (!collapseNext) {
5436.
5437.
// Skip collapsing the first failing test
5438.
collapseNext = true;
5439.
} else {
5440.
5441.
// Collapse remaining tests
5442.
addClass(assertList, "qunit-collapsed");
5443.
}
5444.
}
5445.
5446.
// The testItem.firstChild is the test name
5447.
testTitle = testItem.firstChild;
5448.
5449.
testCounts = bad ? "<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " : "";
5450.
5451.
testTitle.innerHTML += " <b class='counts'>(" + testCounts + details.assertions.length + ")</b>";
5452.
5453.
if (details.skipped) {
5454.
stats.skippedTests++;
5455.
5456.
testItem.className = "skipped";
5457.
skipped = document.createElement("em");
5458.
skipped.className = "qunit-skipped-label";
5459.
skipped.innerHTML = "skipped";
5460.
testItem.insertBefore(skipped, testTitle);
5461.
} else {
5462.
addEvent(testTitle, "click", function () {
5463.
toggleClass(assertList, "qunit-collapsed");
5464.
});
5465.
5466.
testItem.className = testPassed ? "pass" : "fail";
5467.
5468.
if (details.todo) {
5469.
var todoLabel = document.createElement("em");
5470.
todoLabel.className = "qunit-todo-label";
5471.
todoLabel.innerHTML = "todo";
5472.
testItem.className += " todo";
5473.
testItem.insertBefore(todoLabel, testTitle);
5474.
}
5475.
5476.
time = document.createElement("span");
5477.
time.className = "runtime";
5478.
time.innerHTML = details.runtime + " ms";
5479.
testItem.insertBefore(time, assertList);
5480.
5481.
if (!testPassed) {
5482.
stats.failedTests++;
5483.
} else if (details.todo) {
5484.
stats.todoTests++;
5485.
} else {
5486.
stats.passedTests++;
5487.
}
5488.
}
5489.
5490.
// Show the source of the test when showing assertions
5491.
if (details.source) {
5492.
sourceName = document.createElement("p");
5493.
sourceName.innerHTML = "<strong>Source: </strong>" + escapeText(details.source);
5494.
addClass(sourceName, "qunit-source");
5495.
if (testPassed) {
5496.
addClass(sourceName, "qunit-collapsed");
5497.
}
5498.
addEvent(testTitle, "click", function () {
5499.
toggleClass(sourceName, "qunit-collapsed");
5500.
});
5501.
testItem.appendChild(sourceName);
5502.
}
5503.
5504.
if (config.hidepassed && status === "passed") {
5505.
5506.
// use removeChild instead of remove because of support
5507.
hiddenTests.push(testItem);
5508.
5509.
tests.removeChild(testItem);
5510.
}
5511.
});
5512.
5513.
// Avoid readyState issue with phantomjs
5514.
// Ref: #818
5515.
var notPhantom = function (p) {
5516.
return !(p && p.version && p.version.major > 0);
5517.
}(window$1.phantom);
5518.
5519.
if (notPhantom && document.readyState === "complete") {
5520.
QUnit.load();
5521.
} else {
5522.
addEvent(window$1, "load", QUnit.load);
5523.
}
5524.
5525.
// Wrap window.onerror. We will call the original window.onerror to see if
5526.
// the existing handler fully handles the error; if not, we will call the
5527.
// QUnit.onError function.
5528.
var originalWindowOnError = window$1.onerror;
5529.
5530.
// Cover uncaught exceptions
5531.
// Returning true will suppress the default browser handler,
5532.
// returning false will let it run.
5533.
window$1.onerror = function (message, fileName, lineNumber, columnNumber, errorObj) {
5534.
var ret = false;
5535.
if (originalWindowOnError) {
5536.
for (var _len = arguments.length, args = Array(_len > 5 ? _len - 5 : 0), _key = 5; _key < _len; _key++) {
5537.
args[_key - 5] = arguments[_key];
5538.
}
5539.
5540.
ret = originalWindowOnError.call.apply(originalWindowOnError, [this, message, fileName, lineNumber, columnNumber, errorObj].concat(args));
5541.
}
5542.
5543.
// Treat return value as window.onerror itself does,
5544.
// Only do our handling if not suppressed.
5545.
if (ret !== true) {
5546.
var error = {
5547.
message: message,
5548.
fileName: fileName,
5549.
lineNumber: lineNumber
5550.
};
5551.
5552.
// According to
5553.
// https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror,
5554.
// most modern browsers support an errorObj argument; use that to
5555.
// get a full stack trace if it's available.
5556.
if (errorObj && errorObj.stack) {
5557.
error.stacktrace = extractStacktrace(errorObj, 0);
5558.
}
5559.
5560.
ret = QUnit.onError(error);
5561.
}
5562.
5563.
return ret;
5564.
};
5565.
5566.
// Listen for unhandled rejections, and call QUnit.onUnhandledRejection
5567.
window$1.addEventListener("unhandledrejection", function (event) {
5568.
QUnit.onUnhandledRejection(event.reason);
5569.
});
5570.
})();
5571.
5572.
/*
5573.
* This file is a modified version of google-diff-match-patch's JavaScript implementation
5574.
* (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
5575.
* modifications are licensed as more fully set forth in LICENSE.txt.
5576.
*
5577.
* The original source of google-diff-match-patch is attributable and licensed as follows:
5578.
*
5579.
* Copyright 2006 Google Inc.
5580.
* https://code.google.com/p/google-diff-match-patch/
5581.
*
5582.
* Licensed under the Apache License, Version 2.0 (the "License");
5583.
* you may not use this file except in compliance with the License.
5584.
* You may obtain a copy of the License at
5585.
*
5586.
* https://www.apache.org/licenses/LICENSE-2.0
5587.
*
5588.
* Unless required by applicable law or agreed to in writing, software
5589.
* distributed under the License is distributed on an "AS IS" BASIS,
5590.
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5591.
* See the License for the specific language governing permissions and
5592.
* limitations under the License.
5593.
*
5594.
* More Info:
5595.
* https://code.google.com/p/google-diff-match-patch/
5596.
*
5597.
* Usage: QUnit.diff(expected, actual)
5598.
*
5599.
*/
5600.
QUnit.diff = function () {
5601.
function DiffMatchPatch() {}
5602.
5603.
// DIFF FUNCTIONS
5604.
5605.
/**
5606.
* The data structure representing a diff is an array of tuples:
5607.
* [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
5608.
* which means: delete 'Hello', add 'Goodbye' and keep ' world.'
5609.
*/
5610.
var DIFF_DELETE = -1,
5611.
DIFF_INSERT = 1,
5612.
DIFF_EQUAL = 0;
5613.
5614.
/**
5615.
* Find the differences between two texts. Simplifies the problem by stripping
5616.
* any common prefix or suffix off the texts before diffing.
5617.
* @param {string} text1 Old string to be diffed.
5618.
* @param {string} text2 New string to be diffed.
5619.
* @param {boolean=} optChecklines Optional speedup flag. If present and false,
5620.
* then don't run a line-level diff first to identify the changed areas.
5621.
* Defaults to true, which does a faster, slightly less optimal diff.
5622.
* @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
5623.
*/
5624.
DiffMatchPatch.prototype.DiffMain = function (text1, text2, optChecklines) {
5625.
var deadline, checklines, commonlength, commonprefix, commonsuffix, diffs;
5626.
5627.
// The diff must be complete in up to 1 second.
5628.
deadline = new Date().getTime() + 1000;
5629.
5630.
// Check for null inputs.
5631.
if (text1 === null || text2 === null) {
5632.
throw new Error("Null input. (DiffMain)");
5633.
}
5634.
5635.
// Check for equality (speedup).
5636.
if (text1 === text2) {
5637.
if (text1) {
5638.
return [[DIFF_EQUAL, text1]];
5639.
}
5640.
return [];
5641.
}
5642.
5643.
if (typeof optChecklines === "undefined") {
5644.
optChecklines = true;
5645.
}
5646.
5647.
checklines = optChecklines;
5648.
5649.
// Trim off common prefix (speedup).
5650.
commonlength = this.diffCommonPrefix(text1, text2);
5651.
commonprefix = text1.substring(0, commonlength);
5652.
text1 = text1.substring(commonlength);
5653.
text2 = text2.substring(commonlength);
5654.
5655.
// Trim off common suffix (speedup).
5656.
commonlength = this.diffCommonSuffix(text1, text2);
5657.
commonsuffix = text1.substring(text1.length - commonlength);
5658.
text1 = text1.substring(0, text1.length - commonlength);
5659.
text2 = text2.substring(0, text2.length - commonlength);
5660.
5661.
// Compute the diff on the middle block.
5662.
diffs = this.diffCompute(text1, text2, checklines, deadline);
5663.
5664.
// Restore the prefix and suffix.
5665.
if (commonprefix) {
5666.
diffs.unshift([DIFF_EQUAL, commonprefix]);
5667.
}
5668.
if (commonsuffix) {
5669.
diffs.push([DIFF_EQUAL, commonsuffix]);
5670.
}
5671.
this.diffCleanupMerge(diffs);
5672.
return diffs;
5673.
};
5674.
5675.
/**
5676.
* Reduce the number of edits by eliminating operationally trivial equalities.
5677.
* @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
5678.
*/
5679.
DiffMatchPatch.prototype.diffCleanupEfficiency = function (diffs) {
5680.
var changes, equalities, equalitiesLength, lastequality, pointer, preIns, preDel, postIns, postDel;
5681.
changes = false;
5682.
equalities = []; // Stack of indices where equalities are found.
5683.
equalitiesLength = 0; // Keeping our own length var is faster in JS.
5684.
/** @type {?string} */
5685.
lastequality = null;
5686.
5687.
// Always equal to diffs[equalities[equalitiesLength - 1]][1]
5688.
pointer = 0; // Index of current position.
5689.
5690.
// Is there an insertion operation before the last equality.
5691.
preIns = false;
5692.
5693.
// Is there a deletion operation before the last equality.
5694.
preDel = false;
5695.
5696.
// Is there an insertion operation after the last equality.
5697.
postIns = false;
5698.
5699.
// Is there a deletion operation after the last equality.
5700.
postDel = false;
5701.
while (pointer < diffs.length) {
5702.
5703.
// Equality found.
5704.
if (diffs[pointer][0] === DIFF_EQUAL) {
5705.
if (diffs[pointer][1].length < 4 && (postIns || postDel)) {
5706.
5707.
// Candidate found.
5708.
equalities[equalitiesLength++] = pointer;
5709.
preIns = postIns;
5710.
preDel = postDel;
5711.
lastequality = diffs[pointer][1];
5712.
} else {
5713.
5714.
// Not a candidate, and can never become one.
5715.
equalitiesLength = 0;
5716.
lastequality = null;
5717.
}
5718.
postIns = postDel = false;
5719.
5720.
// An insertion or deletion.
5721.
} else {
5722.
5723.
if (diffs[pointer][0] === DIFF_DELETE) {
5724.
postDel = true;
5725.
} else {
5726.
postIns = true;
5727.
}
5728.
5729.
/*
5730.
* Five types to be split:
5731.
* <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
5732.
* <ins>A</ins>X<ins>C</ins><del>D</del>
5733.
* <ins>A</ins><del>B</del>X<ins>C</ins>
5734.
* <ins>A</del>X<ins>C</ins><del>D</del>
5735.
* <ins>A</ins><del>B</del>X<del>C</del>
5736.
*/
5737.
if (lastequality && (preIns && preDel && postIns && postDel || lastequality.length < 2 && preIns + preDel + postIns + postDel === 3)) {
5738.
5739.
// Duplicate record.
5740.
diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]);
5741.
5742.
// Change second copy to insert.
5743.
diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
5744.
equalitiesLength--; // Throw away the equality we just deleted;
5745.
lastequality = null;
5746.
if (preIns && preDel) {
5747.
5748.
// No changes made which could affect previous entry, keep going.
5749.
postIns = postDel = true;
5750.
equalitiesLength = 0;
5751.
} else {
5752.
equalitiesLength--; // Throw away the previous equality.
5753.
pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
5754.
postIns = postDel = false;
5755.
}
5756.
changes = true;
5757.
}
5758.
}
5759.
pointer++;
5760.
}
5761.
5762.
if (changes) {
5763.
this.diffCleanupMerge(diffs);
5764.
}
5765.
};
5766.
5767.
/**
5768.
* Convert a diff array into a pretty HTML report.
5769.
* @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
5770.
* @param {integer} string to be beautified.
5771.
* @return {string} HTML representation.
5772.
*/
5773.
DiffMatchPatch.prototype.diffPrettyHtml = function (diffs) {
5774.
var op,
5775.
data,
5776.
x,
5777.
html = [];
5778.
for (x = 0; x < diffs.length; x++) {
5779.
op = diffs[x][0]; // Operation (insert, delete, equal)
5780.
data = diffs[x][1]; // Text of change.
5781.
switch (op) {
5782.
case DIFF_INSERT:
5783.
html[x] = "<ins>" + escapeText(data) + "</ins>";
5784.
break;
5785.
case DIFF_DELETE:
5786.
html[x] = "<del>" + escapeText(data) + "</del>";
5787.
break;
5788.
case DIFF_EQUAL:
5789.
html[x] = "<span>" + escapeText(data) + "</span>";
5790.
break;
5791.
}
5792.
}
5793.
return html.join("");
5794.
};
5795.
5796.
/**
5797.
* Determine the common prefix of two strings.
5798.
* @param {string} text1 First string.
5799.
* @param {string} text2 Second string.
5800.
* @return {number} The number of characters common to the start of each
5801.
* string.
5802.
*/
5803.
DiffMatchPatch.prototype.diffCommonPrefix = function (text1, text2) {
5804.
var pointermid, pointermax, pointermin, pointerstart;
5805.
5806.
// Quick check for common null cases.
5807.
if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) {
5808.
return 0;
5809.
}
5810.
5811.
// Binary search.
5812.
// Performance analysis: https://neil.fraser.name/news/2007/10/09/
5813.
pointermin = 0;
5814.
pointermax = Math.min(text1.length, text2.length);
5815.
pointermid = pointermax;
5816.
pointerstart = 0;
5817.
while (pointermin < pointermid) {
5818.
if (text1.substring(pointerstart, pointermid) === text2.substring(pointerstart, pointermid)) {
5819.
pointermin = pointermid;
5820.
pointerstart = pointermin;
5821.
} else {
5822.
pointermax = pointermid;
5823.
}
5824.
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
5825.
}
5826.
return pointermid;
5827.
};
5828.
5829.
/**
5830.
* Determine the common suffix of two strings.
5831.
* @param {string} text1 First string.
5832.
* @param {string} text2 Second string.
5833.
* @return {number} The number of characters common to the end of each string.
5834.
*/
5835.
DiffMatchPatch.prototype.diffCommonSuffix = function (text1, text2) {
5836.
var pointermid, pointermax, pointermin, pointerend;
5837.
5838.
// Quick check for common null cases.
5839.
if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) {
5840.
return 0;
5841.
}
5842.
5843.
// Binary search.
5844.
// Performance analysis: https://neil.fraser.name/news/2007/10/09/
5845.
pointermin = 0;
5846.
pointermax = Math.min(text1.length, text2.length);
5847.
pointermid = pointermax;
5848.
pointerend = 0;
5849.
while (pointermin < pointermid) {
5850.
if (text1.substring(text1.length - pointermid, text1.length - pointerend) === text2.substring(text2.length - pointermid, text2.length - pointerend)) {
5851.
pointermin = pointermid;
5852.
pointerend = pointermin;
5853.
} else {
5854.
pointermax = pointermid;
5855.
}
5856.
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
5857.
}
5858.
return pointermid;
5859.
};
5860.
5861.
/**
5862.
* Find the differences between two texts. Assumes that the texts do not
5863.
* have any common prefix or suffix.
5864.
* @param {string} text1 Old string to be diffed.
5865.
* @param {string} text2 New string to be diffed.
5866.
* @param {boolean} checklines Speedup flag. If false, then don't run a
5867.
* line-level diff first to identify the changed areas.
5868.
* If true, then run a faster, slightly less optimal diff.
5869.
* @param {number} deadline Time when the diff should be complete by.
5870.
* @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
5871.
* @private
5872.
*/
5873.
DiffMatchPatch.prototype.diffCompute = function (text1, text2, checklines, deadline) {
5874.
var diffs, longtext, shorttext, i, hm, text1A, text2A, text1B, text2B, midCommon, diffsA, diffsB;
5875.
5876.
if (!text1) {
5877.
5878.
// Just add some text (speedup).
5879.
return [[DIFF_INSERT, text2]];
5880.
}
5881.
5882.
if (!text2) {
5883.
5884.
// Just delete some text (speedup).
5885.
return [[DIFF_DELETE, text1]];
5886.
}
5887.
5888.
longtext = text1.length > text2.length ? text1 : text2;
5889.
shorttext = text1.length > text2.length ? text2 : text1;
5890.
i = longtext.indexOf(shorttext);
5891.
if (i !== -1) {
5892.
5893.
// Shorter text is inside the longer text (speedup).
5894.
diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]];
5895.
5896.
// Swap insertions for deletions if diff is reversed.
5897.
if (text1.length > text2.length) {
5898.
diffs[0][0] = diffs[2][0] = DIFF_DELETE;
5899.
}
5900.
return diffs;
5901.
}
5902.
5903.
if (shorttext.length === 1) {
5904.
5905.
// Single character string.
5906.
// After the previous speedup, the character can't be an equality.
5907.
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
5908.
}
5909.
5910.
// Check to see if the problem can be split in two.
5911.
hm = this.diffHalfMatch(text1, text2);
5912.
if (hm) {
5913.
5914.
// A half-match was found, sort out the return data.
5915.
text1A = hm[0];
5916.
text1B = hm[1];
5917.
text2A = hm[2];
5918.
text2B = hm[3];
5919.
midCommon = hm[4];
5920.
5921.
// Send both pairs off for separate processing.
5922.
diffsA = this.DiffMain(text1A, text2A, checklines, deadline);
5923.
diffsB = this.DiffMain(text1B, text2B, checklines, deadline);
5924.
5925.
// Merge the results.
5926.
return diffsA.concat([[DIFF_EQUAL, midCommon]], diffsB);
5927.
}
5928.
5929.
if (checklines && text1.length > 100 && text2.length > 100) {
5930.
return this.diffLineMode(text1, text2, deadline);
5931.
}
5932.
5933.
return this.diffBisect(text1, text2, deadline);
5934.
};
5935.
5936.
/**
5937.
* Do the two texts share a substring which is at least half the length of the
5938.
* longer text?
5939.
* This speedup can produce non-minimal diffs.
5940.
* @param {string} text1 First string.
5941.
* @param {string} text2 Second string.
5942.
* @return {Array.<string>} Five element Array, containing the prefix of
5943.
* text1, the suffix of text1, the prefix of text2, the suffix of
5944.
* text2 and the common middle. Or null if there was no match.
5945.
* @private
5946.
*/
5947.
DiffMatchPatch.prototype.diffHalfMatch = function (text1, text2) {
5948.
var longtext, shorttext, dmp, text1A, text2B, text2A, text1B, midCommon, hm1, hm2, hm;
5949.
5950.
longtext = text1.length > text2.length ? text1 : text2;
5951.
shorttext = text1.length > text2.length ? text2 : text1;
5952.
if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {
5953.
return null; // Pointless.
5954.
}
5955.
dmp = this; // 'this' becomes 'window' in a closure.
5956.
5957.
/**
5958.
* Does a substring of shorttext exist within longtext such that the substring
5959.
* is at least half the length of longtext?
5960.
* Closure, but does not reference any external variables.
5961.
* @param {string} longtext Longer string.
5962.
* @param {string} shorttext Shorter string.
5963.
* @param {number} i Start index of quarter length substring within longtext.
5964.
* @return {Array.<string>} Five element Array, containing the prefix of
5965.
* longtext, the suffix of longtext, the prefix of shorttext, the suffix
5966.
* of shorttext and the common middle. Or null if there was no match.
5967.
* @private
5968.
*/
5969.
function diffHalfMatchI(longtext, shorttext, i) {
5970.
var seed, j, bestCommon, prefixLength, suffixLength, bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
5971.
5972.
// Start with a 1/4 length substring at position i as a seed.
5973.
seed = longtext.substring(i, i + Math.floor(longtext.length / 4));
5974.
j = -1;
5975.
bestCommon = "";
5976.
while ((j = shorttext.indexOf(seed, j + 1)) !== -1) {
5977.
prefixLength = dmp.diffCommonPrefix(longtext.substring(i), shorttext.substring(j));
5978.
suffixLength = dmp.diffCommonSuffix(longtext.substring(0, i), shorttext.substring(0, j));
5979.
if (bestCommon.length < suffixLength + prefixLength) {
5980.
bestCommon = shorttext.substring(j - suffixLength, j) + shorttext.substring(j, j + prefixLength);
5981.
bestLongtextA = longtext.substring(0, i - suffixLength);
5982.
bestLongtextB = longtext.substring(i + prefixLength);
5983.
bestShorttextA = shorttext.substring(0, j - suffixLength);
5984.
bestShorttextB = shorttext.substring(j + prefixLength);
5985.
}
5986.
}
5987.
if (bestCommon.length * 2 >= longtext.length) {
5988.
return [bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB, bestCommon];
5989.
} else {
5990.
return null;
5991.
}
5992.
}
5993.
5994.
// First check if the second quarter is the seed for a half-match.
5995.
hm1 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 4));
5996.
5997.
// Check again based on the third quarter.
5998.
hm2 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 2));
5999.
if (!hm1 && !hm2) {
6000.
return null;
6001.
} else if (!hm2) {
6002.
hm = hm1;
6003.
} else if (!hm1) {
6004.
hm = hm2;
6005.
} else {
6006.
6007.
// Both matched. Select the longest.
6008.
hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
6009.
}
6010.
6011.
// A half-match was found, sort out the return data.
6012.
if (text1.length > text2.length) {
6013.
text1A = hm[0];
6014.
text1B = hm[1];
6015.
text2A = hm[2];
6016.
text2B = hm[3];
6017.
} else {
6018.
text2A = hm[0];
6019.
text2B = hm[1];
6020.
text1A = hm[2];
6021.
text1B = hm[3];
6022.
}
6023.
midCommon = hm[4];
6024.
return [text1A, text1B, text2A, text2B, midCommon];
6025.
};
6026.
6027.
/**
6028.
* Do a quick line-level diff on both strings, then rediff the parts for
6029.
* greater accuracy.
6030.
* This speedup can produce non-minimal diffs.
6031.
* @param {string} text1 Old string to be diffed.
6032.
* @param {string} text2 New string to be diffed.
6033.
* @param {number} deadline Time when the diff should be complete by.
6034.
* @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
6035.
* @private
6036.
*/
6037.
DiffMatchPatch.prototype.diffLineMode = function (text1, text2, deadline) {
6038.
var a, diffs, linearray, pointer, countInsert, countDelete, textInsert, textDelete, j;
6039.
6040.
// Scan the text on a line-by-line basis first.
6041.
a = this.diffLinesToChars(text1, text2);
6042.
text1 = a.chars1;
6043.
text2 = a.chars2;
6044.
linearray = a.lineArray;
6045.
6046.
diffs = this.DiffMain(text1, text2, false, deadline);
6047.
6048.
// Convert the diff back to original text.
6049.
this.diffCharsToLines(diffs, linearray);
6050.
6051.
// Eliminate freak matches (e.g. blank lines)
6052.
this.diffCleanupSemantic(diffs);
6053.
6054.
// Rediff any replacement blocks, this time character-by-character.
6055.
// Add a dummy entry at the end.
6056.
diffs.push([DIFF_EQUAL, ""]);
6057.
pointer = 0;
6058.
countDelete = 0;
6059.
countInsert = 0;
6060.
textDelete = "";
6061.
textInsert = "";
6062.
while (pointer < diffs.length) {
6063.
switch (diffs[pointer][0]) {
6064.
case DIFF_INSERT:
6065.
countInsert++;
6066.
textInsert += diffs[pointer][1];
6067.
break;
6068.
case DIFF_DELETE:
6069.
countDelete++;
6070.
textDelete += diffs[pointer][1];
6071.
break;
6072.
case DIFF_EQUAL:
6073.
6074.
// Upon reaching an equality, check for prior redundancies.
6075.
if (countDelete >= 1 && countInsert >= 1) {
6076.
6077.
// Delete the offending records and add the merged ones.
6078.
diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert);
6079.
pointer = pointer - countDelete - countInsert;
6080.
a = this.DiffMain(textDelete, textInsert, false, deadline);
6081.
for (j = a.length - 1; j >= 0; j--) {
6082.
diffs.splice(pointer, 0, a[j]);
6083.
}
6084.
pointer = pointer + a.length;
6085.
}
6086.
countInsert = 0;
6087.
countDelete = 0;
6088.
textDelete = "";
6089.
textInsert = "";
6090.
break;
6091.
}
6092.
pointer++;
6093.
}
6094.
diffs.pop(); // Remove the dummy entry at the end.
6095.
6096.
return diffs;
6097.
};
6098.
6099.
/**
6100.
* Find the 'middle snake' of a diff, split the problem in two
6101.
* and return the recursively constructed diff.
6102.
* See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
6103.
* @param {string} text1 Old string to be diffed.
6104.
* @param {string} text2 New string to be diffed.
6105.
* @param {number} deadline Time at which to bail if not yet complete.
6106.
* @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
6107.
* @private
6108.
*/
6109.
DiffMatchPatch.prototype.diffBisect = function (text1, text2, deadline) {
6110.
var text1Length, text2Length, maxD, vOffset, vLength, v1, v2, x, delta, front, k1start, k1end, k2start, k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
6111.
6112.
// Cache the text lengths to prevent multiple calls.
6113.
text1Length = text1.length;
6114.
text2Length = text2.length;
6115.
maxD = Math.ceil((text1Length + text2Length) / 2);
6116.
vOffset = maxD;
6117.
vLength = 2 * maxD;
6118.
v1 = new Array(vLength);
6119.
v2 = new Array(vLength);
6120.
6121.
// Setting all elements to -1 is faster in Chrome & Firefox than mixing
6122.
// integers and undefined.
6123.
for (x = 0; x < vLength; x++) {
6124.
v1[x] = -1;
6125.
v2[x] = -1;
6126.
}
6127.
v1[vOffset + 1] = 0;
6128.
v2[vOffset + 1] = 0;
6129.
delta = text1Length - text2Length;
6130.
6131.
// If the total number of characters is odd, then the front path will collide
6132.
// with the reverse path.
6133.
front = delta % 2 !== 0;
6134.
6135.
// Offsets for start and end of k loop.
6136.
// Prevents mapping of space beyond the grid.
6137.
k1start = 0;
6138.
k1end = 0;
6139.
k2start = 0;
6140.
k2end = 0;
6141.
for (d = 0; d < maxD; d++) {
6142.
6143.
// Bail out if deadline is reached.
6144.
if (new Date().getTime() > deadline) {
6145.
break;
6146.
}
6147.
6148.
// Walk the front path one step.
6149.
for (k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
6150.
k1Offset = vOffset + k1;
6151.
if (k1 === -d || k1 !== d && v1[k1Offset - 1] < v1[k1Offset + 1]) {
6152.
x1 = v1[k1Offset + 1];
6153.
} else {
6154.
x1 = v1[k1Offset - 1] + 1;
6155.
}
6156.
y1 = x1 - k1;
6157.
while (x1 < text1Length && y1 < text2Length && text1.charAt(x1) === text2.charAt(y1)) {
6158.
x1++;
6159.
y1++;
6160.
}
6161.
v1[k1Offset] = x1;
6162.
if (x1 > text1Length) {
6163.
6164.
// Ran off the right of the graph.
6165.
k1end += 2;
6166.
} else if (y1 > text2Length) {
6167.
6168.
// Ran off the bottom of the graph.
6169.
k1start += 2;
6170.
} else if (front) {
6171.
k2Offset = vOffset + delta - k1;
6172.
if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
6173.
6174.
// Mirror x2 onto top-left coordinate system.
6175.
x2 = text1Length - v2[k2Offset];
6176.
if (x1 >= x2) {
6177.
6178.
// Overlap detected.
6179.
return this.diffBisectSplit(text1, text2, x1, y1, deadline);
6180.
}
6181.
}
6182.
}
6183.
}
6184.
6185.
// Walk the reverse path one step.
6186.
for (k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
6187.
k2Offset = vOffset + k2;
6188.
if (k2 === -d || k2 !== d && v2[k2Offset - 1] < v2[k2Offset + 1]) {
6189.
x2 = v2[k2Offset + 1];
6190.
} else {
6191.
x2 = v2[k2Offset - 1] + 1;
6192.
}
6193.
y2 = x2 - k2;
6194.
while (x2 < text1Length && y2 < text2Length && text1.charAt(text1Length - x2 - 1) === text2.charAt(text2Length - y2 - 1)) {
6195.
x2++;
6196.
y2++;
6197.
}
6198.
v2[k2Offset] = x2;
6199.
if (x2 > text1Length) {
6200.
6201.
// Ran off the left of the graph.
6202.
k2end += 2;
6203.
} else if (y2 > text2Length) {
6204.
6205.
// Ran off the top of the graph.
6206.
k2start += 2;
6207.
} else if (!front) {
6208.
k1Offset = vOffset + delta - k2;
6209.
if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
6210.
x1 = v1[k1Offset];
6211.
y1 = vOffset + x1 - k1Offset;
6212.
6213.
// Mirror x2 onto top-left coordinate system.
6214.
x2 = text1Length - x2;
6215.
if (x1 >= x2) {
6216.
6217.
// Overlap detected.
6218.
return this.diffBisectSplit(text1, text2, x1, y1, deadline);
6219.
}
6220.
}
6221.
}
6222.
}
6223.
}
6224.
6225.
// Diff took too long and hit the deadline or
6226.
// number of diffs equals number of characters, no commonality at all.
6227.
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
6228.
};
6229.
6230.
/**
6231.
* Given the location of the 'middle snake', split the diff in two parts
6232.
* and recurse.
6233.
* @param {string} text1 Old string to be diffed.
6234.
* @param {string} text2 New string to be diffed.
6235.
* @param {number} x Index of split point in text1.
6236.
* @param {number} y Index of split point in text2.
6237.
* @param {number} deadline Time at which to bail if not yet complete.
6238.
* @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
6239.
* @private
6240.
*/
6241.
DiffMatchPatch.prototype.diffBisectSplit = function (text1, text2, x, y, deadline) {
6242.
var text1a, text1b, text2a, text2b, diffs, diffsb;
6243.
text1a = text1.substring(0, x);
6244.
text2a = text2.substring(0, y);
6245.
text1b = text1.substring(x);
6246.
text2b = text2.substring(y);
6247.
6248.
// Compute both diffs serially.
6249.
diffs = this.DiffMain(text1a, text2a, false, deadline);
6250.
diffsb = this.DiffMain(text1b, text2b, false, deadline);
6251.
6252.
return diffs.concat(diffsb);
6253.
};
6254.
6255.
/**
6256.
* Reduce the number of edits by eliminating semantically trivial equalities.
6257.
* @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
6258.
*/
6259.
DiffMatchPatch.prototype.diffCleanupSemantic = function (diffs) {
6260.
var changes, equalities, equalitiesLength, lastequality, pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1, lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
6261.
changes = false;
6262.
equalities = []; // Stack of indices where equalities are found.
6263.
equalitiesLength = 0; // Keeping our own length var is faster in JS.
6264.
/** @type {?string} */
6265.
lastequality = null;
6266.
6267.
// Always equal to diffs[equalities[equalitiesLength - 1]][1]
6268.
pointer = 0; // Index of current position.
6269.
6270.
// Number of characters that changed prior to the equality.
6271.
lengthInsertions1 = 0;
6272.
lengthDeletions1 = 0;
6273.
6274.
// Number of characters that changed after the equality.
6275.
lengthInsertions2 = 0;
6276.
lengthDeletions2 = 0;
6277.
while (pointer < diffs.length) {
6278.
if (diffs[pointer][0] === DIFF_EQUAL) {
6279.
// Equality found.
6280.
equalities[equalitiesLength++] = pointer;
6281.
lengthInsertions1 = lengthInsertions2;
6282.
lengthDeletions1 = lengthDeletions2;
6283.
lengthInsertions2 = 0;
6284.
lengthDeletions2 = 0;
6285.
lastequality = diffs[pointer][1];
6286.
} else {
6287.
// An insertion or deletion.
6288.
if (diffs[pointer][0] === DIFF_INSERT) {
6289.
lengthInsertions2 += diffs[pointer][1].length;
6290.
} else {
6291.
lengthDeletions2 += diffs[pointer][1].length;
6292.
}
6293.
6294.
// Eliminate an equality that is smaller or equal to the edits on both
6295.
// sides of it.
6296.
if (lastequality && lastequality.length <= Math.max(lengthInsertions1, lengthDeletions1) && lastequality.length <= Math.max(lengthInsertions2, lengthDeletions2)) {
6297.
6298.
// Duplicate record.
6299.
diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]);
6300.
6301.
// Change second copy to insert.
6302.
diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
6303.
6304.
// Throw away the equality we just deleted.
6305.
equalitiesLength--;
6306.
6307.
// Throw away the previous equality (it needs to be reevaluated).
6308.
equalitiesLength--;
6309.
pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
6310.
6311.
// Reset the counters.
6312.
lengthInsertions1 = 0;
6313.
lengthDeletions1 = 0;
6314.
lengthInsertions2 = 0;
6315.
lengthDeletions2 = 0;
6316.
lastequality = null;
6317.
changes = true;
6318.
}
6319.
}
6320.
pointer++;
6321.
}
6322.
6323.
// Normalize the diff.
6324.
if (changes) {
6325.
this.diffCleanupMerge(diffs);
6326.
}
6327.
6328.
// Find any overlaps between deletions and insertions.
6329.
// e.g: <del>abcxxx</del><ins>xxxdef</ins>
6330.
// -> <del>abc</del>xxx<ins>def</ins>
6331.
// e.g: <del>xxxabc</del><ins>defxxx</ins>
6332.
// -> <ins>def</ins>xxx<del>abc</del>
6333.
// Only extract an overlap if it is as big as the edit ahead or behind it.
6334.
pointer = 1;
6335.
while (pointer < diffs.length) {
6336.
if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
6337.
deletion = diffs[pointer - 1][1];
6338.
insertion = diffs[pointer][1];
6339.
overlapLength1 = this.diffCommonOverlap(deletion, insertion);
6340.
overlapLength2 = this.diffCommonOverlap(insertion, deletion);
6341.
if (overlapLength1 >= overlapLength2) {
6342.
if (overlapLength1 >= deletion.length / 2 || overlapLength1 >= insertion.length / 2) {
6343.
6344.
// Overlap found. Insert an equality and trim the surrounding edits.
6345.
diffs.splice(pointer, 0, [DIFF_EQUAL, insertion.substring(0, overlapLength1)]);
6346.
diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlapLength1);
6347.
diffs[pointer + 1][1] = insertion.substring(overlapLength1);
6348.
pointer++;
6349.
}
6350.
} else {
6351.
if (overlapLength2 >= deletion.length / 2 || overlapLength2 >= insertion.length / 2) {
6352.
6353.
// Reverse overlap found.
6354.
// Insert an equality and swap and trim the surrounding edits.
6355.
diffs.splice(pointer, 0, [DIFF_EQUAL, deletion.substring(0, overlapLength2)]);
6356.
6357.
diffs[pointer - 1][0] = DIFF_INSERT;
6358.
diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlapLength2);
6359.
diffs[pointer + 1][0] = DIFF_DELETE;
6360.
diffs[pointer + 1][1] = deletion.substring(overlapLength2);
6361.
pointer++;
6362.
}
6363.
}
6364.
pointer++;
6365.
}
6366.
pointer++;
6367.
}
6368.
};
6369.
6370.
/**
6371.
* Determine if the suffix of one string is the prefix of another.
6372.
* @param {string} text1 First string.
6373.
* @param {string} text2 Second string.
6374.
* @return {number} The number of characters common to the end of the first
6375.
* string and the start of the second string.
6376.
* @private
6377.
*/
6378.
DiffMatchPatch.prototype.diffCommonOverlap = function (text1, text2) {
6379.
var text1Length, text2Length, textLength, best, length, pattern, found;
6380.
6381.
// Cache the text lengths to prevent multiple calls.
6382.
text1Length = text1.length;
6383.
text2Length = text2.length;
6384.
6385.
// Eliminate the null case.
6386.
if (text1Length === 0 || text2Length === 0) {
6387.
return 0;
6388.
}
6389.
6390.
// Truncate the longer string.
6391.
if (text1Length > text2Length) {
6392.
text1 = text1.substring(text1Length - text2Length);
6393.
} else if (text1Length < text2Length) {
6394.
text2 = text2.substring(0, text1Length);
6395.
}
6396.
textLength = Math.min(text1Length, text2Length);
6397.
6398.
// Quick check for the worst case.
6399.
if (text1 === text2) {
6400.
return textLength;
6401.
}
6402.
6403.
// Start by looking for a single character match
6404.
// and increase length until no match is found.
6405.
// Performance analysis: https://neil.fraser.name/news/2010/11/04/
6406.
best = 0;
6407.
length = 1;
6408.
while (true) {
6409.
pattern = text1.substring(textLength - length);
6410.
found = text2.indexOf(pattern);
6411.
if (found === -1) {
6412.
return best;
6413.
}
6414.
length += found;
6415.
if (found === 0 || text1.substring(textLength - length) === text2.substring(0, length)) {
6416.
best = length;
6417.
length++;
6418.
}
6419.
}
6420.
};
6421.
6422.
/**
6423.
* Split two texts into an array of strings. Reduce the texts to a string of
6424.
* hashes where each Unicode character represents one line.
6425.
* @param {string} text1 First string.
6426.
* @param {string} text2 Second string.
6427.
* @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
6428.
* An object containing the encoded text1, the encoded text2 and
6429.
* the array of unique strings.
6430.
* The zeroth element of the array of unique strings is intentionally blank.
6431.
* @private
6432.
*/
6433.
DiffMatchPatch.prototype.diffLinesToChars = function (text1, text2) {
6434.
var lineArray, lineHash, chars1, chars2;
6435.
lineArray = []; // E.g. lineArray[4] === 'Hello\n'
6436.
lineHash = {}; // E.g. lineHash['Hello\n'] === 4
6437.
6438.
// '\x00' is a valid character, but various debuggers don't like it.
6439.
// So we'll insert a junk entry to avoid generating a null character.
6440.
lineArray[0] = "";
6441.
6442.
/**
6443.
* Split a text into an array of strings. Reduce the texts to a string of
6444.
* hashes where each Unicode character represents one line.
6445.
* Modifies linearray and linehash through being a closure.
6446.
* @param {string} text String to encode.
6447.
* @return {string} Encoded string.
6448.
* @private
6449.
*/
6450.
function diffLinesToCharsMunge(text) {
6451.
var chars, lineStart, lineEnd, lineArrayLength, line;
6452.
chars = "";
6453.
6454.
// Walk the text, pulling out a substring for each line.
6455.
// text.split('\n') would would temporarily double our memory footprint.
6456.
// Modifying text would create many large strings to garbage collect.
6457.
lineStart = 0;
6458.
lineEnd = -1;
6459.
6460.
// Keeping our own length variable is faster than looking it up.
6461.
lineArrayLength = lineArray.length;
6462.
while (lineEnd < text.length - 1) {
6463.
lineEnd = text.indexOf("\n", lineStart);
6464.
if (lineEnd === -1) {
6465.
lineEnd = text.length - 1;
6466.
}
6467.
line = text.substring(lineStart, lineEnd + 1);
6468.
lineStart = lineEnd + 1;
6469.
6470.
var lineHashExists = lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== undefined;
6471.
6472.
if (lineHashExists) {
6473.
chars += String.fromCharCode(lineHash[line]);
6474.
} else {
6475.
chars += String.fromCharCode(lineArrayLength);
6476.
lineHash[line] = lineArrayLength;
6477.
lineArray[lineArrayLength++] = line;
6478.
}
6479.
}
6480.
return chars;
6481.
}
6482.
6483.
chars1 = diffLinesToCharsMunge(text1);
6484.
chars2 = diffLinesToCharsMunge(text2);
6485.
return {
6486.
chars1: chars1,
6487.
chars2: chars2,
6488.
lineArray: lineArray
6489.
};
6490.
};
6491.
6492.
/**
6493.
* Rehydrate the text in a diff from a string of line hashes to real lines of
6494.
* text.
6495.
* @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
6496.
* @param {!Array.<string>} lineArray Array of unique strings.
6497.
* @private
6498.
*/
6499.
DiffMatchPatch.prototype.diffCharsToLines = function (diffs, lineArray) {
6500.
var x, chars, text, y;
6501.
for (x = 0; x < diffs.length; x++) {
6502.
chars = diffs[x][1];
6503.
text = [];
6504.
for (y = 0; y < chars.length; y++) {
6505.
text[y] = lineArray[chars.charCodeAt(y)];
6506.
}
6507.
diffs[x][1] = text.join("");
6508.
}
6509.
};
6510.
6511.
/**
6512.
* Reorder and merge like edit sections. Merge equalities.
6513.
* Any edit section can move as long as it doesn't cross an equality.
6514.
* @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
6515.
*/
6516.
DiffMatchPatch.prototype.diffCleanupMerge = function (diffs) {
6517.
var pointer, countDelete, countInsert, textInsert, textDelete, commonlength, changes, diffPointer, position;
6518.
diffs.push([DIFF_EQUAL, ""]); // Add a dummy entry at the end.
6519.
pointer = 0;
6520.
countDelete = 0;
6521.
countInsert = 0;
6522.
textDelete = "";
6523.
textInsert = "";
6524.
6525.
while (pointer < diffs.length) {
6526.
switch (diffs[pointer][0]) {
6527.
case DIFF_INSERT:
6528.
countInsert++;
6529.
textInsert += diffs[pointer][1];
6530.
pointer++;
6531.
break;
6532.
case DIFF_DELETE:
6533.
countDelete++;
6534.
textDelete += diffs[pointer][1];
6535.
pointer++;
6536.
break;
6537.
case DIFF_EQUAL:
6538.
6539.
// Upon reaching an equality, check for prior redundancies.
6540.
if (countDelete + countInsert > 1) {
6541.
if (countDelete !== 0 && countInsert !== 0) {
6542.
6543.
// Factor out any common prefixes.
6544.
commonlength = this.diffCommonPrefix(textInsert, textDelete);
6545.
if (commonlength !== 0) {
6546.
if (pointer - countDelete - countInsert > 0 && diffs[pointer - countDelete - countInsert - 1][0] === DIFF_EQUAL) {
6547.
diffs[pointer - countDelete - countInsert - 1][1] += textInsert.substring(0, commonlength);
6548.
} else {
6549.
diffs.splice(0, 0, [DIFF_EQUAL, textInsert.substring(0, commonlength)]);
6550.
pointer++;
6551.
}
6552.
textInsert = textInsert.substring(commonlength);
6553.
textDelete = textDelete.substring(commonlength);
6554.
}
6555.
6556.
// Factor out any common suffixies.
6557.
commonlength = this.diffCommonSuffix(textInsert, textDelete);
6558.
if (commonlength !== 0) {
6559.
diffs[pointer][1] = textInsert.substring(textInsert.length - commonlength) + diffs[pointer][1];
6560.
textInsert = textInsert.substring(0, textInsert.length - commonlength);
6561.
textDelete = textDelete.substring(0, textDelete.length - commonlength);
6562.
}
6563.
}
6564.
6565.
// Delete the offending records and add the merged ones.
6566.
if (countDelete === 0) {
6567.
diffs.splice(pointer - countInsert, countDelete + countInsert, [DIFF_INSERT, textInsert]);
6568.
} else if (countInsert === 0) {
6569.
diffs.splice(pointer - countDelete, countDelete + countInsert, [DIFF_DELETE, textDelete]);
6570.
} else {
6571.
diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert, [DIFF_DELETE, textDelete], [DIFF_INSERT, textInsert]);
6572.
}
6573.
pointer = pointer - countDelete - countInsert + (countDelete ? 1 : 0) + (countInsert ? 1 : 0) + 1;
6574.
} else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {
6575.
6576.
// Merge this equality with the previous one.
6577.
diffs[pointer - 1][1] += diffs[pointer][1];
6578.
diffs.splice(pointer, 1);
6579.
} else {
6580.
pointer++;
6581.
}
6582.
countInsert = 0;
6583.
countDelete = 0;
6584.
textDelete = "";
6585.
textInsert = "";
6586.
break;
6587.
}
6588.
}
6589.
if (diffs[diffs.length - 1][1] === "") {
6590.
diffs.pop(); // Remove the dummy entry at the end.
6591.
}
6592.
6593.
// Second pass: look for single edits surrounded on both sides by equalities
6594.
// which can be shifted sideways to eliminate an equality.
6595.
// e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
6596.
changes = false;
6597.
pointer = 1;
6598.
6599.
// Intentionally ignore the first and last element (don't need checking).
6600.
while (pointer < diffs.length - 1) {
6601.
if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) {
6602.
6603.
diffPointer = diffs[pointer][1];
6604.
position = diffPointer.substring(diffPointer.length - diffs[pointer - 1][1].length);
6605.
6606.
// This is a single edit surrounded by equalities.
6607.
if (position === diffs[pointer - 1][1]) {
6608.
6609.
// Shift the edit over the previous equality.
6610.
diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length);
6611.
diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
6612.
diffs.splice(pointer - 1, 1);
6613.
changes = true;
6614.
} else if (diffPointer.substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1]) {
6615.
6616.
// Shift the edit over the next equality.
6617.
diffs[pointer - 1][1] += diffs[pointer + 1][1];
6618.
diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1];
6619.
diffs.splice(pointer + 1, 1);
6620.
changes = true;
6621.
}
6622.
}
6623.
pointer++;
6624.
}
6625.
6626.
// If shifts were made, the diff needs reordering and another shift sweep.
6627.
if (changes) {
6628.
this.diffCleanupMerge(diffs);
6629.
}
6630.
};
6631.
6632.
return function (o, n) {
6633.
var diff, output, text;
6634.
diff = new DiffMatchPatch();
6635.
output = diff.DiffMain(o, n);
6636.
diff.diffCleanupEfficiency(output);
6637.
text = diff.diffPrettyHtml(output);
6638.
6639.
return text;
6640.
};
6641.
}();
6642.
6643.
}((function() { return this; }())));
6644.