Current section
Files
Jump to
Current section
Files
priv/static/assets/test-support.js
/*! * QUnit 2.3.0 * https://qunitjs.com/ * * Copyright jQuery Foundation and other contributors * Released under the MIT license * https://jquery.org/license * * Date: 2017-03-29T15:13Z */(function (global$1) { 'use strict'; global$1 = 'default' in global$1 ? global$1['default'] : global$1; var window = global$1.window; var console = global$1.console; var setTimeout = global$1.setTimeout; var clearTimeout = global$1.clearTimeout; var document = window && window.document; var navigator = window && window.navigator; var localSessionStorage = function () { var x = "qunit-test-string"; try { global$1.sessionStorage.setItem(x, x); global$1.sessionStorage.removeItem(x); return global$1.sessionStorage; } catch (e) { return undefined; } }(); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; var toString = Object.prototype.toString; var hasOwn = Object.prototype.hasOwnProperty; var now = Date.now || function () { return new Date().getTime(); }; var defined = { document: window && window.document !== undefined, setTimeout: setTimeout !== undefined }; // Returns a new Array with the elements that are in a but not in b function diff(a, b) { var i, j, result = a.slice(); for (i = 0; i < result.length; i++) { for (j = 0; j < b.length; j++) { if (result[i] === b[j]) { result.splice(i, 1); i--; break; } } } return result; } /** * Determines whether an element exists in a given array or not. * * @method inArray * @param {Any} elem * @param {Array} array * @return {Boolean} */ function inArray(elem, array) { return array.indexOf(elem) !== -1; } /** * Makes a clone of an object using only Array or Object as base, * and copies over the own enumerable properties. * * @param {Object} obj * @return {Object} New object with only the own properties (recursively). */ function objectValues(obj) { var key, val, vals = is("array", obj) ? [] : {}; for (key in obj) { if (hasOwn.call(obj, key)) { val = obj[key]; vals[key] = val === Object(val) ? objectValues(val) : val; } } return vals; } function extend(a, b, undefOnly) { for (var prop in b) { if (hasOwn.call(b, prop)) { if (b[prop] === undefined) { delete a[prop]; } else if (!(undefOnly && typeof a[prop] !== "undefined")) { a[prop] = b[prop]; } } } return a; } function objectType(obj) { if (typeof obj === "undefined") { return "undefined"; } // Consider: typeof null === object if (obj === null) { return "null"; } var match = toString.call(obj).match(/^\[object\s(.*)\]$/), type = match && match[1]; switch (type) { case "Number": if (isNaN(obj)) { return "nan"; } return "number"; case "String": case "Boolean": case "Array": case "Set": case "Map": case "Date": case "RegExp": case "Function": case "Symbol": return type.toLowerCase(); } if ((typeof obj === "undefined" ? "undefined" : _typeof(obj)) === "object") { return "object"; } } // Safe object type checking function is(type, obj) { return objectType(obj) === type; } // Based on Java's String.hashCode, a simple but not // rigorously collision resistant hashing function function generateHash(module, testName) { var str = module + "\x1C" + testName; var hash = 0; for (var i = 0; i < str.length; i++) { hash = (hash << 5) - hash + str.charCodeAt(i); hash |= 0; } // Convert the possibly negative integer hash code into an 8 character hex string, which isn't // strictly necessary but increases user understanding that the id is a SHA-like hash var hex = (0x100000000 + hash).toString(16); if (hex.length < 8) { hex = "0000000" + hex; } return hex.slice(-8); } // Test for equality any JavaScript type. // Authors: Philippe Rathé <prathe@gmail.com>, David Chan <david@troi.org> var equiv = (function () { // Value pairs queued for comparison. Used for breadth-first processing order, recursion // detection and avoiding repeated comparison (see below for details). // Elements are { a: val, b: val }. var pairs = []; var getProto = Object.getPrototypeOf || function (obj) { return obj.__proto__; }; function useStrictEquality(a, b) { // This only gets called if a and b are not strict equal, and is used to compare on // the primitive values inside object wrappers. For example: // `var i = 1;` // `var j = new Number(1);` // Neither a nor b can be null, as a !== b and they have the same type. if ((typeof a === "undefined" ? "undefined" : _typeof(a)) === "object") { a = a.valueOf(); } if ((typeof b === "undefined" ? "undefined" : _typeof(b)) === "object") { b = b.valueOf(); } return a === b; } function compareConstructors(a, b) { var protoA = getProto(a); var protoB = getProto(b); // Comparing constructors is more strict than using `instanceof` if (a.constructor === b.constructor) { return true; } // Ref #851 // If the obj prototype descends from a null constructor, treat it // as a null prototype. if (protoA && protoA.constructor === null) { protoA = null; } if (protoB && protoB.constructor === null) { protoB = null; } // Allow objects with no prototype to be equivalent to // objects with Object as their constructor. if (protoA === null && protoB === Object.prototype || protoB === null && protoA === Object.prototype) { return true; } return false; } function getRegExpFlags(regexp) { return "flags" in regexp ? regexp.flags : regexp.toString().match(/[gimuy]*$/)[0]; } function isContainer(val) { return ["object", "array", "map", "set"].indexOf(objectType(val)) !== -1; } function breadthFirstCompareChild(a, b) { // If a is a container not reference-equal to b, postpone the comparison to the // end of the pairs queue -- unless (a, b) has been seen before, in which case skip // over the pair. if (a === b) { return true; } if (!isContainer(a)) { return typeEquiv(a, b); } if (pairs.every(function (pair) { return pair.a !== a || pair.b !== b; })) { // Not yet started comparing this pair pairs.push({ a: a, b: b }); } return true; } var callbacks = { "string": useStrictEquality, "boolean": useStrictEquality, "number": useStrictEquality, "null": useStrictEquality, "undefined": useStrictEquality, "symbol": useStrictEquality, "date": useStrictEquality, "nan": function nan() { return true; }, "regexp": function regexp(a, b) { return a.source === b.source && // Include flags in the comparison getRegExpFlags(a) === getRegExpFlags(b); }, // abort (identical references / instance methods were skipped earlier) "function": function _function() { return false; }, "array": function array(a, b) { var i, len; len = a.length; if (len !== b.length) { // Safe and faster return false; } for (i = 0; i < len; i++) { // Compare non-containers; queue non-reference-equal containers if (!breadthFirstCompareChild(a[i], b[i])) { return false; } } return true; }, // Define sets a and b to be equivalent if for each element aVal in a, there // is some element bVal in b such that aVal and bVal are equivalent. Element // repetitions are not counted, so these are equivalent: // a = new Set( [ {}, [], [] ] ); // b = new Set( [ {}, {}, [] ] ); "set": function set$$1(a, b) { var innerEq, outerEq = true; if (a.size !== b.size) { // This optimization has certain quirks because of the lack of // repetition counting. For instance, adding the same // (reference-identical) element to two equivalent sets can // make them non-equivalent. return false; } a.forEach(function (aVal) { // Short-circuit if the result is already known. (Using for...of // with a break clause would be cleaner here, but it would cause // a syntax error on older Javascript implementations even if // Set is unused) if (!outerEq) { return; } innerEq = false; b.forEach(function (bVal) { var parentPairs; // Likewise, short-circuit if the result is already known if (innerEq) { return; } // Swap out the global pairs list, as the nested call to // innerEquiv will clobber its contents parentPairs = pairs; if (innerEquiv(bVal, aVal)) { innerEq = true; } // Replace the global pairs list pairs = parentPairs; }); if (!innerEq) { outerEq = false; } }); return outerEq; }, // Define maps a and b to be equivalent if for each key-value pair (aKey, aVal) // in a, there is some key-value pair (bKey, bVal) in b such that // [ aKey, aVal ] and [ bKey, bVal ] are equivalent. Key repetitions are not // counted, so these are equivalent: // a = new Map( [ [ {}, 1 ], [ {}, 1 ], [ [], 1 ] ] ); // b = new Map( [ [ {}, 1 ], [ [], 1 ], [ [], 1 ] ] ); "map": function map(a, b) { var innerEq, outerEq = true; if (a.size !== b.size) { // This optimization has certain quirks because of the lack of // repetition counting. For instance, adding the same // (reference-identical) key-value pair to two equivalent maps // can make them non-equivalent. return false; } a.forEach(function (aVal, aKey) { // Short-circuit if the result is already known. (Using for...of // with a break clause would be cleaner here, but it would cause // a syntax error on older Javascript implementations even if // Map is unused) if (!outerEq) { return; } innerEq = false; b.forEach(function (bVal, bKey) { var parentPairs; // Likewise, short-circuit if the result is already known if (innerEq) { return; } // Swap out the global pairs list, as the nested call to // innerEquiv will clobber its contents parentPairs = pairs; if (innerEquiv([bVal, bKey], [aVal, aKey])) { innerEq = true; } // Replace the global pairs list pairs = parentPairs; }); if (!innerEq) { outerEq = false; } }); return outerEq; }, "object": function object(a, b) { var i, aProperties = [], bProperties = []; if (compareConstructors(a, b) === false) { return false; } // Be strict: don't ensure hasOwnProperty and go deep for (i in a) { // Collect a's properties aProperties.push(i); // Skip OOP methods that look the same if (a.constructor !== Object && typeof a.constructor !== "undefined" && typeof a[i] === "function" && typeof b[i] === "function" && a[i].toString() === b[i].toString()) { continue; } // Compare non-containers; queue non-reference-equal containers if (!breadthFirstCompareChild(a[i], b[i])) { return false; } } for (i in b) { // Collect b's properties bProperties.push(i); } // Ensures identical properties name return typeEquiv(aProperties.sort(), bProperties.sort()); } }; function typeEquiv(a, b) { var type = objectType(a); // Callbacks for containers will append to the pairs queue to achieve breadth-first // search order. The pairs queue is also used to avoid reprocessing any pair of // containers that are reference-equal to a previously visited pair (a special case // this being recursion detection). // // Because of this approach, once typeEquiv returns a false value, it should not be // called again without clearing the pair queue else it may wrongly report a visited // pair as being equivalent. return objectType(b) === type && callbacks[type](a, b); } function innerEquiv(a, b) { var i, pair; // We're done when there's nothing more to compare if (arguments.length < 2) { return true; } // Clear the global pair queue and add the top-level values being compared pairs = [{ a: a, b: b }]; for (i = 0; i < pairs.length; i++) { pair = pairs[i]; // Perform type-specific comparison on any pairs that are not strictly // equal. For container types, that comparison will postpone comparison // of any sub-container pair to the end of the pair queue. This gives // breadth-first search order. It also avoids the reprocessing of // reference-equal siblings, cousins etc, which can have a significant speed // impact when comparing a container of small objects each of which has a // reference to the same (singleton) large object. if (pair.a !== pair.b && !typeEquiv(pair.a, pair.b)) { return false; } } // ...across all consecutive argument pairs return arguments.length === 2 || innerEquiv.apply(this, [].slice.call(arguments, 1)); } return innerEquiv; })(); /** * Config object: Maintain internal state * Later exposed as QUnit.config * `config` initialized at top of scope */ var config = { // The queue of tests to run queue: [], // Block until document ready blocking: true, // By default, run previously failed tests first // very useful in combination with "Hide passed tests" checked reorder: true, // By default, modify document.title when suite is done altertitle: true, // HTML Reporter: collapse every test except the first failing test // If false, all failing tests will be expanded collapse: true, // By default, scroll to top of the page when suite is done scrolltop: true, // Depth up-to which object will be dumped maxDepth: 5, // When enabled, all tests must call expect() requireExpects: false, // Placeholder for user-configurable form-exposed URL parameters urlConfig: [], // Set of all modules. modules: [], // The first unnamed module currentModule: { name: "", tests: [], childModules: [], testsRun: 0 }, callbacks: {}, // The storage module to use for reordering tests storage: localSessionStorage }; // take a predefined QUnit.config and extend the defaults var globalConfig = window && window.QUnit && window.QUnit.config; // only extend the global config if there is no QUnit overload if (window && window.QUnit && !window.QUnit.version) { extend(config, globalConfig); } // Push a loose unnamed module to the modules collection config.modules.push(config.currentModule); // Based on jsDump by Ariel Flesler // http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html var dump = (function () { function quote(str) { return "\"" + str.toString().replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\""; } function literal(o) { return o + ""; } function join(pre, arr, post) { var s = dump.separator(), base = dump.indent(), inner = dump.indent(1); if (arr.join) { arr = arr.join("," + s + inner); } if (!arr) { return pre + post; } return [pre, inner + arr, base + post].join(s); } function array(arr, stack) { var i = arr.length, ret = new Array(i); if (dump.maxDepth && dump.depth > dump.maxDepth) { return "[object Array]"; } this.up(); while (i--) { ret[i] = this.parse(arr[i], undefined, stack); } this.down(); return join("[", ret, "]"); } function isArray(obj) { return ( //Native Arrays toString.call(obj) === "[object Array]" || // NodeList objects typeof obj.length === "number" && obj.item !== undefined && (obj.length ? obj.item(0) === obj[0] : obj.item(0) === null && obj[0] === undefined) ); } var reName = /^function (\w+)/, dump = { // The objType is used mostly internally, you can fix a (custom) type in advance parse: function parse(obj, objType, stack) { stack = stack || []; var res, parser, parserType, objIndex = stack.indexOf(obj); if (objIndex !== -1) { return "recursion(" + (objIndex - stack.length) + ")"; } objType = objType || this.typeOf(obj); parser = this.parsers[objType]; parserType = typeof parser === "undefined" ? "undefined" : _typeof(parser); if (parserType === "function") { stack.push(obj); res = parser.call(this, obj, stack); stack.pop(); return res; } return parserType === "string" ? parser : this.parsers.error; }, typeOf: function typeOf(obj) { var type; if (obj === null) { type = "null"; } else if (typeof obj === "undefined") { type = "undefined"; } else if (is("regexp", obj)) { type = "regexp"; } else if (is("date", obj)) { type = "date"; } else if (is("function", obj)) { type = "function"; } else if (obj.setInterval !== undefined && obj.document !== undefined && obj.nodeType === undefined) { type = "window"; } else if (obj.nodeType === 9) { type = "document"; } else if (obj.nodeType) { type = "node"; } else if (isArray(obj)) { type = "array"; } else if (obj.constructor === Error.prototype.constructor) { type = "error"; } else { type = typeof obj === "undefined" ? "undefined" : _typeof(obj); } return type; }, separator: function separator() { if (this.multiline) { return this.HTML ? "<br />" : "\n"; } else { return this.HTML ? " " : " "; } }, // Extra can be a number, shortcut for increasing-calling-decreasing indent: function indent(extra) { if (!this.multiline) { return ""; } var chr = this.indentChar; if (this.HTML) { chr = chr.replace(/\t/g, " ").replace(/ /g, " "); } return new Array(this.depth + (extra || 0)).join(chr); }, up: function up(a) { this.depth += a || 1; }, down: function down(a) { this.depth -= a || 1; }, setParser: function setParser(name, parser) { this.parsers[name] = parser; }, // The next 3 are exposed so you can use them quote: quote, literal: literal, join: join, depth: 1, maxDepth: config.maxDepth, // This is the list of parsers, to modify them, use dump.setParser parsers: { window: "[Window]", document: "[Document]", error: function error(_error) { return "Error(\"" + _error.message + "\")"; }, unknown: "[Unknown]", "null": "null", "undefined": "undefined", "function": function _function(fn) { var ret = "function", // Functions never have name in IE name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1]; if (name) { ret += " " + name; } ret += "("; ret = [ret, dump.parse(fn, "functionArgs"), "){"].join(""); return join(ret, dump.parse(fn, "functionCode"), "}"); }, array: array, nodelist: array, "arguments": array, object: function object(map, stack) { var keys, key, val, i, nonEnumerableProperties, ret = []; if (dump.maxDepth && dump.depth > dump.maxDepth) { return "[object Object]"; } dump.up(); keys = []; for (key in map) { keys.push(key); } // Some properties are not always enumerable on Error objects. nonEnumerableProperties = ["message", "name"]; for (i in nonEnumerableProperties) { key = nonEnumerableProperties[i]; if (key in map && !inArray(key, keys)) { keys.push(key); } } keys.sort(); for (i = 0; i < keys.length; i++) { key = keys[i]; val = map[key]; ret.push(dump.parse(key, "key") + ": " + dump.parse(val, undefined, stack)); } dump.down(); return join("{", ret, "}"); }, node: function node(_node) { var len, i, val, open = dump.HTML ? "<" : "<", close = dump.HTML ? ">" : ">", tag = _node.nodeName.toLowerCase(), ret = open + tag, attrs = _node.attributes; if (attrs) { for (i = 0, len = attrs.length; i < len; i++) { val = attrs[i].nodeValue; // IE6 includes all attributes in .attributes, even ones not explicitly // set. Those have values like undefined, null, 0, false, "" or // "inherit". if (val && val !== "inherit") { ret += " " + attrs[i].nodeName + "=" + dump.parse(val, "attribute"); } } } ret += close; // Show content of TextNode or CDATASection if (_node.nodeType === 3 || _node.nodeType === 4) { ret += _node.nodeValue; } return ret + open + "/" + tag + close; }, // Function calls it internally, it's the arguments part of the function functionArgs: function functionArgs(fn) { var args, l = fn.length; if (!l) { return ""; } args = new Array(l); while (l--) { // 97 is 'a' args[l] = String.fromCharCode(97 + l); } return " " + args.join(", ") + " "; }, // Object calls it internally, the key part of an item in a map key: quote, // Function calls it internally, it's the content of the function functionCode: "[code]", // Node calls it internally, it's a html attribute value attribute: quote, string: quote, date: quote, regexp: literal, number: literal, "boolean": literal, symbol: function symbol(sym) { return sym.toString(); } }, // If true, entities are escaped ( <, >, \t, space and \n ) HTML: false, // Indentation unit indentChar: " ", // If true, items in a collection, are separated by a \n, else just a space. multiline: true }; return dump; })(); var LISTENERS = Object.create(null); var SUPPORTED_EVENTS = ["runStart", "suiteStart", "testStart", "assertion", "testEnd", "suiteEnd", "runEnd"]; /** * Emits an event with the specified data to all currently registered listeners. * Callbacks will fire in the order in which they are registered (FIFO). This * function is not exposed publicly; it is used by QUnit internals to emit * logging events. * * @private * @method emit * @param {String} eventName * @param {Object} data * @return {Void} */ function emit(eventName, data) { if (objectType(eventName) !== "string") { throw new TypeError("eventName must be a string when emitting an event"); } // Clone the callbacks in case one of them registers a new callback var originalCallbacks = LISTENERS[eventName]; var callbacks = originalCallbacks ? [].concat(toConsumableArray(originalCallbacks)) : []; for (var i = 0; i < callbacks.length; i++) { callbacks[i](data); } } /** * Registers a callback as a listener to the specified event. * * @public * @method on * @param {String} eventName * @param {Function} callback * @return {Void} */ function on(eventName, callback) { if (objectType(eventName) !== "string") { throw new TypeError("eventName must be a string when registering a listener"); } else if (!inArray(eventName, SUPPORTED_EVENTS)) { var events = SUPPORTED_EVENTS.join(", "); throw new Error("\"" + eventName + "\" is not a valid event; must be one of: " + events + "."); } else if (objectType(callback) !== "function") { throw new TypeError("callback must be a function when registering a listener"); } if (!LISTENERS[eventName]) { LISTENERS[eventName] = []; } // Don't register the same callback more than once if (!inArray(callback, LISTENERS[eventName])) { LISTENERS[eventName].push(callback); } } // Register logging callbacks function registerLoggingCallbacks(obj) { var i, l, key, callbackNames = ["begin", "done", "log", "testStart", "testDone", "moduleStart", "moduleDone"]; function registerLoggingCallback(key) { var loggingCallback = function loggingCallback(callback) { if (objectType(callback) !== "function") { throw new Error("QUnit logging methods require a callback function as their first parameters."); } config.callbacks[key].push(callback); }; return loggingCallback; } for (i = 0, l = callbackNames.length; i < l; i++) { key = callbackNames[i]; // Initialize key collection of logging callback if (objectType(config.callbacks[key]) === "undefined") { config.callbacks[key] = []; } obj[key] = registerLoggingCallback(key); } } function runLoggingCallbacks(key, args) { var i, l, callbacks; callbacks = config.callbacks[key]; for (i = 0, l = callbacks.length; i < l; i++) { callbacks[i](args); } } // Doesn't support IE9, it will return undefined on these browsers // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack var fileName = (sourceFromStacktrace(0) || "").replace(/(:\d+)+\)?/, "").replace(/.+\//, ""); function extractStacktrace(e, offset) { offset = offset === undefined ? 4 : offset; var stack, include, i; if (e && e.stack) { stack = e.stack.split("\n"); if (/^error$/i.test(stack[0])) { stack.shift(); } if (fileName) { include = []; for (i = offset; i < stack.length; i++) { if (stack[i].indexOf(fileName) !== -1) { break; } include.push(stack[i]); } if (include.length) { return include.join("\n"); } } return stack[offset]; } } function sourceFromStacktrace(offset) { var error = new Error(); // Support: Safari <=7 only, IE <=10 - 11 only // Not all browsers generate the `stack` property for `new Error()`, see also #636 if (!error.stack) { try { throw error; } catch (err) { error = err; } } return extractStacktrace(error, offset); } var priorityCount = 0; var unitSampler = void 0; /** * Advances the ProcessingQueue to the next item if it is ready. * @param {Boolean} last */ function advance() { var start = now(); config.depth = (config.depth || 0) + 1; while (config.queue.length && !config.blocking) { var elapsedTime = now() - start; if (!defined.setTimeout || config.updateRate <= 0 || elapsedTime < config.updateRate) { if (config.current) { // Reset async tracking for each phase of the Test lifecycle config.current.usedAsync = false; } if (priorityCount > 0) { priorityCount--; } config.queue.shift()(); } else { setTimeout(advance, 13); break; } } config.depth--; if (!config.blocking && !config.queue.length && config.depth === 0) { done(); } } function addToQueueImmediate(callback) { if (objectType(callback) === "array") { while (callback.length) { addToQueueImmediate(callback.pop()); } return; } config.queue.unshift(callback); priorityCount++; } /** * Adds a function to the ProcessingQueue for execution. * @param {Function|Array} callback * @param {Boolean} priority * @param {String} seed */ function addToQueue(callback, prioritize, seed) { if (prioritize) { config.queue.splice(priorityCount++, 0, callback); } else if (seed) { if (!unitSampler) { unitSampler = unitSamplerGenerator(seed); } // Insert into a random position after all prioritized items var index = Math.floor(unitSampler() * (config.queue.length - priorityCount + 1)); config.queue.splice(priorityCount + index, 0, callback); } else { config.queue.push(callback); } } /** * Creates a seeded "sample" generator which is used for randomizing tests. */ function unitSamplerGenerator(seed) { // 32-bit xorshift, requires only a nonzero seed // http://excamera.com/sphinx/article-xorshift.html var sample = parseInt(generateHash(seed), 16) || -1; return function () { sample ^= sample << 13; sample ^= sample >>> 17; sample ^= sample << 5; // ECMAScript has no unsigned number type if (sample < 0) { sample += 0x100000000; } return sample / 0x100000000; }; } /** * This function is called when the ProcessingQueue is done processing all * items. It handles emitting the final run events. */ function done() { var storage = config.storage; ProcessingQueue.finished = true; var runtime = now() - config.started; var passed = config.stats.all - config.stats.bad; emit("runEnd", globalSuite.end(true)); runLoggingCallbacks("done", { passed: passed, failed: config.stats.bad, total: config.stats.all, runtime: runtime }); // Clear own storage items if all tests passed if (storage && config.stats.bad === 0) { for (var i = storage.length - 1; i >= 0; i--) { var key = storage.key(i); if (key.indexOf("qunit-test-") === 0) { storage.removeItem(key); } } } } var ProcessingQueue = { finished: false, add: addToQueue, addImmediate: addToQueueImmediate, advance: advance }; var TestReport = function () { function TestReport(name, suite, options) { classCallCheck(this, TestReport); this.name = name; this.suiteName = suite.name; this.fullName = suite.fullName.concat(name); this.runtime = 0; this.assertions = []; this.skipped = !!options.skip; this.todo = !!options.todo; this.testInstance = options.testInstance; this._startTime = 0; this._endTime = 0; suite.pushTest(this); } createClass(TestReport, [{ key: "isValid", value: function isValid() { return this.testInstance.valid(); } }, { key: "start", value: function start(recordTime) { if (recordTime) { this._startTime = Date.now(); } return { name: this.name, suiteName: this.suiteName, fullName: this.fullName.slice() }; } }, { key: "end", value: function end(recordTime) { if (recordTime) { this._endTime = Date.now(); } return extend(this.start(), { runtime: this.getRuntime(), status: this.getStatus(), errors: this.getFailedAssertions(), assertions: this.getAssertions() }); } }, { key: "pushAssertion", value: function pushAssertion(assertion) { this.assertions.push(assertion); } }, { key: "getRuntime", value: function getRuntime() { return this._endTime - this._startTime; } }, { key: "getStatus", value: function getStatus() { if (this.skipped) { return "skipped"; } var testPassed = this.getFailedAssertions().length > 0 ? this.todo : !this.todo; if (!testPassed) { return "failed"; } else if (this.todo) { return "todo"; } else { return "passed"; } } }, { key: "getFailedAssertions", value: function getFailedAssertions() { return this.assertions.filter(function (assertion) { return !assertion.passed; }); } }, { key: "getAssertions", value: function getAssertions() { return this.assertions.slice(); } }]); return TestReport; }(); var focused = false; function Test(settings) { var i, l; ++Test.count; this.expected = null; extend(this, settings); this.assertions = []; this.semaphore = 0; this.usedAsync = false; this.module = config.currentModule; this.stack = sourceFromStacktrace(3); this.steps = []; this.testReport = new TestReport(settings.testName, this.module.suiteReport, { todo: settings.todo, skip: settings.skip, testInstance: this }); // Register unique strings for (i = 0, l = this.module.tests; i < l.length; i++) { if (this.module.tests[i].name === this.testName) { this.testName += " "; } } this.testId = generateHash(this.module.name, this.testName); this.module.tests.push({ name: this.testName, testId: this.testId }); if (settings.skip) { // Skipped tests will fully ignore any sent callback this.callback = function () {}; this.async = false; this.expected = 0; } else { this.assert = new Assert(this); } } Test.count = 0; function getNotStartedModules(startModule) { var module = startModule, modules = []; while (module && module.testsRun === 0) { modules.push(module); module = module.parentModule; } return modules; } Test.prototype = { before: function before() { var i, startModule, module = this.module, notStartedModules = getNotStartedModules(module); for (i = notStartedModules.length - 1; i >= 0; i--) { startModule = notStartedModules[i]; startModule.stats = { all: 0, bad: 0, started: now() }; emit("suiteStart", startModule.suiteReport.start(true)); runLoggingCallbacks("moduleStart", { name: startModule.name, tests: startModule.tests }); } config.current = this; this.testEnvironment = extend({}, module.testEnvironment); this.started = now(); emit("testStart", this.testReport.start(true)); runLoggingCallbacks("testStart", { name: this.testName, module: module.name, testId: this.testId, previousFailure: this.previousFailure }); if (!config.pollution) { saveGlobal(); } }, run: function run() { var promise; config.current = this; this.callbackStarted = now(); if (config.notrycatch) { runTest(this); return; } try { runTest(this); } catch (e) { this.pushFailure("Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + (e.message || e), extractStacktrace(e, 0)); // Else next test will carry the responsibility saveGlobal(); // Restart the tests if they're blocking if (config.blocking) { internalRecover(this); } } function runTest(test) { promise = test.callback.call(test.testEnvironment, test.assert); test.resolvePromise(promise); } }, after: function after() { checkPollution(); }, queueHook: function queueHook(hook, hookName, hookOwner) { var promise, test = this; return function runHook() { if (hookName === "before") { if (hookOwner.testsRun !== 0) { return; } test.preserveEnvironment = true; } if (hookName === "after" && hookOwner.testsRun !== numberOfTests(hookOwner) - 1 && config.queue.length > 2) { return; } config.current = test; if (config.notrycatch) { callHook(); return; } try { callHook(); } catch (error) { test.pushFailure(hookName + " failed on " + test.testName + ": " + (error.message || error), extractStacktrace(error, 0)); } function callHook() { promise = hook.call(test.testEnvironment, test.assert); test.resolvePromise(promise, hookName); } }; }, // Currently only used for module level hooks, can be used to add global level ones hooks: function hooks(handler) { var hooks = []; function processHooks(test, module) { if (module.parentModule) { processHooks(test, module.parentModule); } if (module.hooks && objectType(module.hooks[handler]) === "function") { hooks.push(test.queueHook(module.hooks[handler], handler, module)); } } // Hooks are ignored on skipped tests if (!this.skip) { processHooks(this, this.module); } return hooks; }, finish: function finish() { config.current = this; if (config.requireExpects && this.expected === null) { this.pushFailure("Expected number of assertions to be defined, but expect() was " + "not called.", this.stack); } else if (this.expected !== null && this.expected !== this.assertions.length) { this.pushFailure("Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack); } else if (this.expected === null && !this.assertions.length) { this.pushFailure("Expected at least one assertion, but none were run - call " + "expect(0) to accept zero assertions.", this.stack); } var i, module = this.module, moduleName = module.name, testName = this.testName, skipped = !!this.skip, todo = !!this.todo, bad = 0, storage = config.storage; this.runtime = now() - this.started; config.stats.all += this.assertions.length; module.stats.all += this.assertions.length; for (i = 0; i < this.assertions.length; i++) { if (!this.assertions[i].result) { bad++; config.stats.bad++; module.stats.bad++; } } notifyTestsRan(module); // Store result when possible if (storage) { if (bad) { storage.setItem("qunit-test-" + moduleName + "-" + testName, bad); } else { storage.removeItem("qunit-test-" + moduleName + "-" + testName); } } emit("testEnd", this.testReport.end(true)); runLoggingCallbacks("testDone", { name: testName, module: moduleName, skipped: skipped, todo: todo, failed: bad, passed: this.assertions.length - bad, total: this.assertions.length, runtime: skipped ? 0 : this.runtime, // HTML Reporter use assertions: this.assertions, testId: this.testId, // Source of Test source: this.stack }); if (module.testsRun === numberOfTests(module)) { emit("suiteEnd", module.suiteReport.end(true)); runLoggingCallbacks("moduleDone", { name: module.name, tests: module.tests, failed: module.stats.bad, passed: module.stats.all - module.stats.bad, total: module.stats.all, runtime: now() - module.stats.started }); } config.current = undefined; }, preserveTestEnvironment: function preserveTestEnvironment() { if (this.preserveEnvironment) { this.module.testEnvironment = this.testEnvironment; this.testEnvironment = extend({}, this.module.testEnvironment); } }, queue: function queue() { var test = this; if (!this.valid()) { return; } function runTest() { // Each of these can by async ProcessingQueue.addImmediate([function () { test.before(); }, test.hooks("before"), function () { test.preserveTestEnvironment(); }, test.hooks("beforeEach"), function () { test.run(); }, test.hooks("afterEach").reverse(), test.hooks("after").reverse(), function () { test.after(); }, function () { test.finish(); }]); } var previousFailCount = config.storage && +config.storage.getItem("qunit-test-" + this.module.name + "-" + this.testName); // Prioritize previously failed tests, detected from storage var prioritize = config.reorder && !!previousFailCount; this.previousFailure = !!previousFailCount; ProcessingQueue.add(runTest, prioritize, config.seed); // If the queue has already finished, we manually process the new test if (ProcessingQueue.finished) { ProcessingQueue.advance(); } }, pushResult: function pushResult(resultInfo) { // Destructure of resultInfo = { result, actual, expected, message, negative } var source, details = { module: this.module.name, name: this.testName, result: resultInfo.result, message: resultInfo.message, actual: resultInfo.actual, expected: resultInfo.expected, testId: this.testId, negative: resultInfo.negative || false, runtime: now() - this.started, todo: !!this.todo }; if (!resultInfo.result) { source = resultInfo.source || sourceFromStacktrace(); if (source) { details.source = source; } } this.logAssertion(details); this.assertions.push({ result: !!resultInfo.result, message: resultInfo.message }); }, pushFailure: function pushFailure(message, source, actual) { if (!(this instanceof Test)) { throw new Error("pushFailure() assertion outside test context, was " + sourceFromStacktrace(2)); } this.pushResult({ result: false, message: message || "error", actual: actual || null, expected: null, source: source }); }, /** * Log assertion details using both the old QUnit.log interface and * QUnit.on( "assertion" ) interface. * * @private */ logAssertion: function logAssertion(details) { runLoggingCallbacks("log", details); var assertion = { passed: details.result, actual: details.actual, expected: details.expected, message: details.message, stack: details.source, todo: details.todo }; this.testReport.pushAssertion(assertion); emit("assertion", assertion); }, resolvePromise: function resolvePromise(promise, phase) { var then, resume, message, test = this; if (promise != null) { then = promise.then; if (objectType(then) === "function") { resume = internalStop(test); then.call(promise, function () { resume(); }, function (error) { message = "Promise rejected " + (!phase ? "during" : phase.replace(/Each$/, "")) + " \"" + test.testName + "\": " + (error && error.message || error); test.pushFailure(message, extractStacktrace(error, 0)); // Else next test will carry the responsibility saveGlobal(); // Unblock resume(); }); } } }, valid: function valid() { var filter = config.filter, regexFilter = /^(!?)\/([\w\W]*)\/(i?$)/.exec(filter), module = config.module && config.module.toLowerCase(), fullName = this.module.name + ": " + this.testName; function moduleChainNameMatch(testModule) { var testModuleName = testModule.name ? testModule.name.toLowerCase() : null; if (testModuleName === module) { return true; } else if (testModule.parentModule) { return moduleChainNameMatch(testModule.parentModule); } else { return false; } } function moduleChainIdMatch(testModule) { return inArray(testModule.moduleId, config.moduleId) || testModule.parentModule && moduleChainIdMatch(testModule.parentModule); } // Internally-generated tests are always valid if (this.callback && this.callback.validTest) { return true; } if (config.moduleId && config.moduleId.length > 0 && !moduleChainIdMatch(this.module)) { return false; } if (config.testId && config.testId.length > 0 && !inArray(this.testId, config.testId)) { return false; } if (module && !moduleChainNameMatch(this.module)) { return false; } if (!filter) { return true; } return regexFilter ? this.regexFilter(!!regexFilter[1], regexFilter[2], regexFilter[3], fullName) : this.stringFilter(filter, fullName); }, regexFilter: function regexFilter(exclude, pattern, flags, fullName) { var regex = new RegExp(pattern, flags); var match = regex.test(fullName); return match !== exclude; }, stringFilter: function stringFilter(filter, fullName) { filter = filter.toLowerCase(); fullName = fullName.toLowerCase(); var include = filter.charAt(0) !== "!"; if (!include) { filter = filter.slice(1); } // If the filter matches, we need to honour include if (fullName.indexOf(filter) !== -1) { return include; } // Otherwise, do the opposite return !include; } }; function pushFailure() { if (!config.current) { throw new Error("pushFailure() assertion outside test context, in " + sourceFromStacktrace(2)); } // Gets current test obj var currentTest = config.current; return currentTest.pushFailure.apply(currentTest, arguments); } function saveGlobal() { config.pollution = []; if (config.noglobals) { for (var key in global$1) { if (hasOwn.call(global$1, key)) { // In Opera sometimes DOM element ids show up here, ignore them if (/^qunit-test-output/.test(key)) { continue; } config.pollution.push(key); } } } } function checkPollution() { var newGlobals, deletedGlobals, old = config.pollution; saveGlobal(); newGlobals = diff(config.pollution, old); if (newGlobals.length > 0) { pushFailure("Introduced global variable(s): " + newGlobals.join(", ")); } deletedGlobals = diff(old, config.pollution); if (deletedGlobals.length > 0) { pushFailure("Deleted global variable(s): " + deletedGlobals.join(", ")); } } // Will be exposed as QUnit.test function test(testName, callback) { if (focused) { return; } var newTest = new Test({ testName: testName, callback: callback }); newTest.queue(); } function todo(testName, callback) { if (focused) { return; } var newTest = new Test({ testName: testName, callback: callback, todo: true }); newTest.queue(); } // Will be exposed as QUnit.skip function skip(testName) { if (focused) { return; } var test = new Test({ testName: testName, skip: true }); test.queue(); } // Will be exposed as QUnit.only function only(testName, callback) { if (focused) { return; } config.queue.length = 0; focused = true; var newTest = new Test({ testName: testName, callback: callback }); newTest.queue(); } // Put a hold on processing and return a function that will release it. function internalStop(test) { var released = false; test.semaphore += 1; config.blocking = true; // Set a recovery timeout, if so configured. if (config.testTimeout && defined.setTimeout) { clearTimeout(config.timeout); config.timeout = setTimeout(function () { pushFailure("Test timed out", sourceFromStacktrace(2)); internalRecover(test); }, config.testTimeout); } return function resume() { if (released) { return; } released = true; test.semaphore -= 1; internalStart(test); }; } // Forcefully release all processing holds. function internalRecover(test) { test.semaphore = 0; internalStart(test); } // Release a processing hold, scheduling a resumption attempt if no holds remain. function internalStart(test) { // If semaphore is non-numeric, throw error if (isNaN(test.semaphore)) { test.semaphore = 0; pushFailure("Invalid value on test.semaphore", sourceFromStacktrace(2)); return; } // Don't start until equal number of stop-calls if (test.semaphore > 0) { return; } // Throw an Error if start is called more often than stop if (test.semaphore < 0) { test.semaphore = 0; pushFailure("Tried to restart test while already started (test's semaphore was 0 already)", sourceFromStacktrace(2)); return; } // Add a slight delay to allow more assertions etc. if (defined.setTimeout) { if (config.timeout) { clearTimeout(config.timeout); } config.timeout = setTimeout(function () { if (test.semaphore > 0) { return; } if (config.timeout) { clearTimeout(config.timeout); } begin(); }, 13); } else { begin(); } } function numberOfTests(module) { var count = module.tests.length; var modules = [].concat(toConsumableArray(module.childModules)); // Do a breadth-first traversal of the child modules while (modules.length) { var nextModule = modules.shift(); count += nextModule.tests.length; modules.push.apply(modules, toConsumableArray(nextModule.childModules)); } return count; } function notifyTestsRan(module) { module.testsRun++; while (module = module.parentModule) { module.testsRun++; } } /** * Returns a function that proxies to the given method name on the globals * console object. The proxy will also detect if the console doesn't exist and * will appropriately no-op. This allows support for IE9, which doesn't have a * console if the developer tools are not open. */ function consoleProxy(method) { return function () { if (console) { console[method].apply(console, arguments); } }; } var Logger = { warn: consoleProxy("warn") }; var Assert = function () { function Assert(testContext) { classCallCheck(this, Assert); this.test = testContext; } // Assert helpers // Documents a "step", which is a string value, in a test as a passing assertion createClass(Assert, [{ key: "step", value: function step(message) { var result = !!message; this.test.steps.push(message); return this.pushResult({ result: result, message: message || "You must provide a message to assert.step" }); } // Verifies the steps in a test match a given array of string values }, { key: "verifySteps", value: function verifySteps(steps, message) { this.deepEqual(this.test.steps, steps, message); } // Specify the number of expected assertions to guarantee that failed test // (no assertions are run at all) don't slip through. }, { key: "expect", value: function expect(asserts) { if (arguments.length === 1) { this.test.expected = asserts; } else { return this.test.expected; } } // Put a hold on processing and return a function that will release it a maximum of once. }, { key: "async", value: function async(count) { var test$$1 = this.test; var popped = false, acceptCallCount = count; if (typeof acceptCallCount === "undefined") { acceptCallCount = 1; } test$$1.usedAsync = true; var resume = internalStop(test$$1); return function done() { if (popped) { test$$1.pushFailure("Too many calls to the `assert.async` callback", sourceFromStacktrace(2)); return; } acceptCallCount -= 1; if (acceptCallCount > 0) { return; } popped = true; resume(); }; } // Exports test.push() to the user API // Alias of pushResult. }, { key: "push", value: function push(result, actual, expected, message, negative) { Logger.warn("assert.push is deprecated and will be removed in QUnit 3.0." + " Please use assert.pushResult instead (http://api.qunitjs.com/pushResult/)."); var currentAssert = this instanceof Assert ? this : config.current.assert; return currentAssert.pushResult({ result: result, actual: actual, expected: expected, message: message, negative: negative }); } }, { key: "pushResult", value: function pushResult(resultInfo) { // Destructure of resultInfo = { result, actual, expected, message, negative } var assert = this; var currentTest = assert instanceof Assert && assert.test || config.current; // Backwards compatibility fix. // Allows the direct use of global exported assertions and QUnit.assert.* // Although, it's use is not recommended as it can leak assertions // to other tests from async tests, because we only get a reference to the current test, // not exactly the test where assertion were intended to be called. if (!currentTest) { throw new Error("assertion outside test context, in " + sourceFromStacktrace(2)); } if (currentTest.usedAsync === true && currentTest.semaphore === 0) { currentTest.pushFailure("Assertion after the final `assert.async` was resolved", sourceFromStacktrace(2)); // Allow this assertion to continue running anyway... } if (!(assert instanceof Assert)) { assert = currentTest.assert; } return assert.test.pushResult(resultInfo); } }, { key: "ok", value: function ok(result, message) { if (!message) { message = result ? "okay" : "failed, expected argument to be truthy, was: " + dump.parse(result); } this.pushResult({ result: !!result, actual: result, expected: true, message: message }); } }, { key: "notOk", value: function notOk(result, message) { if (!message) { message = !result ? "okay" : "failed, expected argument to be falsy, was: " + dump.parse(result); } this.pushResult({ result: !result, actual: result, expected: false, message: message }); } }, { key: "equal", value: function equal(actual, expected, message) { // eslint-disable-next-line eqeqeq var result = expected == actual; this.pushResult({ result: result, actual: actual, expected: expected, message: message }); } }, { key: "notEqual", value: function notEqual(actual, expected, message) { // eslint-disable-next-line eqeqeq var result = expected != actual; this.pushResult({ result: result, actual: actual, expected: expected, message: message, negative: true }); } }, { key: "propEqual", value: function propEqual(actual, expected, message) { actual = objectValues(actual); expected = objectValues(expected); this.pushResult({ result: equiv(actual, expected), actual: actual, expected: expected, message: message }); } }, { key: "notPropEqual", value: function notPropEqual(actual, expected, message) { actual = objectValues(actual); expected = objectValues(expected); this.pushResult({ result: !equiv(actual, expected), actual: actual, expected: expected, message: message, negative: true }); } }, { key: "deepEqual", value: function deepEqual(actual, expected, message) { this.pushResult({ result: equiv(actual, expected), actual: actual, expected: expected, message: message }); } }, { key: "notDeepEqual", value: function notDeepEqual(actual, expected, message) { this.pushResult({ result: !equiv(actual, expected), actual: actual, expected: expected, message: message, negative: true }); } }, { key: "strictEqual", value: function strictEqual(actual, expected, message) { this.pushResult({ result: expected === actual, actual: actual, expected: expected, message: message }); } }, { key: "notStrictEqual", value: function notStrictEqual(actual, expected, message) { this.pushResult({ result: expected !== actual, actual: actual, expected: expected, message: message, negative: true }); } }, { key: "throws", value: function throws(block, expected, message) { var actual = void 0, result = false; var currentTest = this instanceof Assert && this.test || config.current; // 'expected' is optional unless doing string comparison if (objectType(expected) === "string") { if (message == null) { message = expected; expected = null; } else { 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."); } } currentTest.ignoreGlobalErrors = true; try { block.call(currentTest.testEnvironment); } catch (e) { actual = e; } currentTest.ignoreGlobalErrors = false; if (actual) { var expectedType = objectType(expected); // We don't want to validate thrown error if (!expected) { result = true; expected = null; // Expected is a regexp } else if (expectedType === "regexp") { result = expected.test(errorString(actual)); // Expected is a constructor, maybe an Error constructor } else if (expectedType === "function" && actual instanceof expected) { result = true; // Expected is an Error object } else if (expectedType === "object") { result = actual instanceof expected.constructor && actual.name === expected.name && actual.message === expected.message; // Expected is a validation function which returns true if validation passed } else if (expectedType === "function" && expected.call({}, actual) === true) { expected = null; result = true; } } currentTest.assert.pushResult({ result: result, actual: actual, expected: expected, message: message }); } }]); return Assert; }(); // Provide an alternative to assert.throws(), for environments that consider throws a reserved word // Known to us are: Closure Compiler, Narwhal // eslint-disable-next-line dot-notation Assert.prototype.raises = Assert.prototype["throws"]; /** * Converts an error into a simple string for comparisons. * * @param {Error} error * @return {String} */ function errorString(error) { var resultErrorString = error.toString(); if (resultErrorString.substring(0, 7) === "[object") { var name = error.name ? error.name.toString() : "Error"; var message = error.message ? error.message.toString() : ""; if (name && message) { return name + ": " + message; } else if (name) { return name; } else if (message) { return message; } else { return "Error"; } } else { return resultErrorString; } } /* global module, exports, define */ function exportQUnit(QUnit) { if (defined.document) { // QUnit may be defined when it is preconfigured but then only QUnit and QUnit.config may be defined. if (window.QUnit && window.QUnit.version) { throw new Error("QUnit has already been defined."); } window.QUnit = QUnit; } // For nodejs if (typeof module !== "undefined" && module && module.exports) { module.exports = QUnit; // For consistency with CommonJS environments' exports module.exports.QUnit = QUnit; } // For CommonJS with exports, but without module.exports, like Rhino if (typeof exports !== "undefined" && exports) { exports.QUnit = QUnit; } if (typeof define === "function" && define.amd) { define(function () { return QUnit; }); QUnit.config.autostart = false; } } var SuiteReport = function () { function SuiteReport(name, parentSuite) { classCallCheck(this, SuiteReport); this.name = name; this.fullName = parentSuite ? parentSuite.fullName.concat(name) : []; this.tests = []; this.childSuites = []; if (parentSuite) { parentSuite.pushChildSuite(this); } } createClass(SuiteReport, [{ key: "start", value: function start(recordTime) { if (recordTime) { this._startTime = Date.now(); } return { name: this.name, fullName: this.fullName.slice(), tests: this.tests.map(function (test) { return test.start(); }), childSuites: this.childSuites.map(function (suite) { return suite.start(); }), testCounts: { total: this.getTestCounts().total } }; } }, { key: "end", value: function end(recordTime) { if (recordTime) { this._endTime = Date.now(); } return { name: this.name, fullName: this.fullName.slice(), tests: this.tests.map(function (test) { return test.end(); }), childSuites: this.childSuites.map(function (suite) { return suite.end(); }), testCounts: this.getTestCounts(), runtime: this.getRuntime(), status: this.getStatus() }; } }, { key: "pushChildSuite", value: function pushChildSuite(suite) { this.childSuites.push(suite); } }, { key: "pushTest", value: function pushTest(test) { this.tests.push(test); } }, { key: "getRuntime", value: function getRuntime() { return this._endTime - this._startTime; } }, { key: "getTestCounts", value: function getTestCounts() { var counts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { passed: 0, failed: 0, skipped: 0, todo: 0, total: 0 }; counts = this.tests.reduce(function (counts, test) { if (test.isValid()) { counts[test.getStatus()]++; counts.total++; } return counts; }, counts); return this.childSuites.reduce(function (counts, suite) { return suite.getTestCounts(counts); }, counts); } }, { key: "getStatus", value: function getStatus() { var _getTestCounts = this.getTestCounts(), total = _getTestCounts.total, failed = _getTestCounts.failed, skipped = _getTestCounts.skipped, todo = _getTestCounts.todo; if (failed) { return "failed"; } else { if (skipped === total) { return "skipped"; } else if (todo === total) { return "todo"; } else { return "passed"; } } } }]); return SuiteReport; }(); // Handle an unhandled exception. By convention, returns true if further // error handling should be suppressed and false otherwise. // In this case, we will only suppress further error handling if the // "ignoreGlobalErrors" configuration option is enabled. function onError(error) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } if (config.current) { if (config.current.ignoreGlobalErrors) { return true; } pushFailure.apply(undefined, [error.message, error.fileName + ":" + error.lineNumber].concat(args)); } else { test("global failure", extend(function () { pushFailure.apply(undefined, [error.message, error.fileName + ":" + error.lineNumber].concat(args)); }, { validTest: true })); } return false; } var QUnit = {}; var globalSuite = new SuiteReport(); // The initial "currentModule" represents the global (or top-level) module that // is not explicitly defined by the user, therefore we add the "globalSuite" to // it since each module has a suiteReport associated with it. config.currentModule.suiteReport = globalSuite; var moduleStack = []; var globalStartCalled = false; var runStarted = false; // Figure out if we're running the tests from a server or not QUnit.isLocal = !(defined.document && window.location.protocol !== "file:"); // Expose the current QUnit version QUnit.version = "2.3.0"; function createModule(name, testEnvironment) { var parentModule = moduleStack.length ? moduleStack.slice(-1)[0] : null; var moduleName = parentModule !== null ? [parentModule.name, name].join(" > ") : name; var parentSuite = parentModule ? parentModule.suiteReport : globalSuite; var module = { name: moduleName, parentModule: parentModule, tests: [], moduleId: generateHash(moduleName), testsRun: 0, childModules: [], suiteReport: new SuiteReport(name, parentSuite) }; var env = {}; if (parentModule) { parentModule.childModules.push(module); extend(env, parentModule.testEnvironment); } extend(env, testEnvironment); module.testEnvironment = env; config.modules.push(module); return module; } extend(QUnit, { on: on, // Call on start of module test to prepend name to all tests module: function module(name, testEnvironment, executeNow) { if (arguments.length === 2) { if (objectType(testEnvironment) === "function") { executeNow = testEnvironment; testEnvironment = undefined; } } var module = createModule(name, testEnvironment); // Move any hooks to a 'hooks' object if (module.testEnvironment) { module.hooks = { before: module.testEnvironment.before, beforeEach: module.testEnvironment.beforeEach, afterEach: module.testEnvironment.afterEach, after: module.testEnvironment.after }; delete module.testEnvironment.before; delete module.testEnvironment.beforeEach; delete module.testEnvironment.afterEach; delete module.testEnvironment.after; } var moduleFns = { before: setHook(module, "before"), beforeEach: setHook(module, "beforeEach"), afterEach: setHook(module, "afterEach"), after: setHook(module, "after") }; var currentModule = config.currentModule; if (objectType(executeNow) === "function") { moduleStack.push(module); config.currentModule = module; executeNow.call(module.testEnvironment, moduleFns); moduleStack.pop(); module = module.parentModule || currentModule; } config.currentModule = module; }, test: test, todo: todo, skip: skip, only: only, start: function start(count) { var globalStartAlreadyCalled = globalStartCalled; if (!config.current) { globalStartCalled = true; if (runStarted) { throw new Error("Called start() while test already started running"); } else if (globalStartAlreadyCalled || count > 1) { throw new Error("Called start() outside of a test context too many times"); } else if (config.autostart) { throw new Error("Called start() outside of a test context when " + "QUnit.config.autostart was true"); } else if (!config.pageLoaded) { // The page isn't completely loaded yet, so we set autostart and then // load if we're in Node or wait for the browser's load event. config.autostart = true; // Starts from Node even if .load was not previously called. We still return // early otherwise we'll wind up "beginning" twice. if (!defined.document) { QUnit.load(); } return; } } else { throw new Error("QUnit.start cannot be called inside a test context."); } scheduleBegin(); }, config: config, is: is, objectType: objectType, extend: extend, load: function load() { config.pageLoaded = true; // Initialize the configuration options extend(config, { stats: { all: 0, bad: 0 }, started: 0, updateRate: 1000, autostart: true, filter: "" }, true); if (!runStarted) { config.blocking = false; if (config.autostart) { scheduleBegin(); } } }, stack: function stack(offset) { offset = (offset || 0) + 2; return sourceFromStacktrace(offset); }, onError: onError }); QUnit.pushFailure = pushFailure; QUnit.assert = Assert.prototype; QUnit.equiv = equiv; QUnit.dump = dump; registerLoggingCallbacks(QUnit); function scheduleBegin() { runStarted = true; // Add a slight delay to allow definition of more modules and tests. if (defined.setTimeout) { setTimeout(function () { begin(); }, 13); } else { begin(); } } function begin() { var i, l, modulesLog = []; // If the test run hasn't officially begun yet if (!config.started) { // Record the time of the test run's beginning config.started = now(); // Delete the loose unnamed module if unused. if (config.modules[0].name === "" && config.modules[0].tests.length === 0) { config.modules.shift(); } // Avoid unnecessary information by not logging modules' test environments for (i = 0, l = config.modules.length; i < l; i++) { modulesLog.push({ name: config.modules[i].name, tests: config.modules[i].tests }); } // The test run is officially beginning now emit("runStart", globalSuite.start(true)); runLoggingCallbacks("begin", { totalTests: Test.count, modules: modulesLog }); } config.blocking = false; ProcessingQueue.advance(); } function setHook(module, hookName) { if (!module.hooks) { module.hooks = {}; } return function (callback) { module.hooks[hookName] = callback; }; } exportQUnit(QUnit); (function () { if (typeof window === "undefined" || typeof document === "undefined") { return; } var config = QUnit.config, hasOwn = Object.prototype.hasOwnProperty; // Stores fixture HTML for resetting later function storeFixture() { // Avoid overwriting user-defined values if (hasOwn.call(config, "fixture")) { return; } var fixture = document.getElementById("qunit-fixture"); if (fixture) { config.fixture = fixture.innerHTML; } } QUnit.begin(storeFixture); // Resets the fixture DOM element if available. function resetFixture() { if (config.fixture == null) { return; } var fixture = document.getElementById("qunit-fixture"); if (fixture) { fixture.innerHTML = config.fixture; } } QUnit.testStart(resetFixture); })(); (function () { // Only interact with URLs via window.location var location = typeof window !== "undefined" && window.location; if (!location) { return; } var urlParams = getUrlParams(); QUnit.urlParams = urlParams; // Match module/test by inclusion in an array QUnit.config.moduleId = [].concat(urlParams.moduleId || []); QUnit.config.testId = [].concat(urlParams.testId || []); // Exact case-insensitive match of the module name QUnit.config.module = urlParams.module; // Regular expression or case-insenstive substring match against "moduleName: testName" QUnit.config.filter = urlParams.filter; // Test order randomization if (urlParams.seed === true) { // Generate a random seed if the option is specified without a value QUnit.config.seed = Math.random().toString(36).slice(2); } else if (urlParams.seed) { QUnit.config.seed = urlParams.seed; } // Add URL-parameter-mapped config values with UI form rendering data QUnit.config.urlConfig.push({ id: "hidepassed", label: "Hide passed tests", tooltip: "Only show tests and assertions that fail. Stored as query-strings." }, { id: "noglobals", label: "Check for Globals", tooltip: "Enabling this will test if any test introduces new properties on the " + "global object (`window` in Browsers). Stored as query-strings." }, { id: "notrycatch", label: "No try-catch", tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " + "exceptions in IE reasonable. Stored as query-strings." }); QUnit.begin(function () { var i, option, urlConfig = QUnit.config.urlConfig; for (i = 0; i < urlConfig.length; i++) { // Options can be either strings or objects with nonempty "id" properties option = QUnit.config.urlConfig[i]; if (typeof option !== "string") { option = option.id; } if (QUnit.config[option] === undefined) { QUnit.config[option] = urlParams[option]; } } }); function getUrlParams() { var i, param, name, value; var urlParams = Object.create(null); var params = location.search.slice(1).split("&"); var length = params.length; for (i = 0; i < length; i++) { if (params[i]) { param = params[i].split("="); name = decodeQueryParam(param[0]); // Allow just a key to turn on a flag, e.g., test.html?noglobals value = param.length === 1 || decodeQueryParam(param.slice(1).join("=")); if (name in urlParams) { urlParams[name] = [].concat(urlParams[name], value); } else { urlParams[name] = value; } } } return urlParams; } function decodeQueryParam(param) { return decodeURIComponent(param.replace(/\+/g, "%20")); } })(); var stats = { passedTests: 0, failedTests: 0, skippedTests: 0, todoTests: 0 }; // Escape text for attribute or text content. function escapeText(s) { if (!s) { return ""; } s = s + ""; // Both single quotes and double quotes (for attributes) return s.replace(/['"<>&]/g, function (s) { switch (s) { case "'": return "'"; case "\"": return """; case "<": return "<"; case ">": return ">"; case "&": return "&"; } }); } (function () { // Don't load the HTML Reporter on non-browser environments if (typeof window === "undefined" || !window.document) { return; } var config = QUnit.config, document$$1 = window.document, collapseNext = false, hasOwn = Object.prototype.hasOwnProperty, unfilteredUrl = setUrl({ filter: undefined, module: undefined, moduleId: undefined, testId: undefined }), modulesList = []; function addEvent(elem, type, fn) { elem.addEventListener(type, fn, false); } function removeEvent(elem, type, fn) { elem.removeEventListener(type, fn, false); } function addEvents(elems, type, fn) { var i = elems.length; while (i--) { addEvent(elems[i], type, fn); } } function hasClass(elem, name) { return (" " + elem.className + " ").indexOf(" " + name + " ") >= 0; } function addClass(elem, name) { if (!hasClass(elem, name)) { elem.className += (elem.className ? " " : "") + name; } } function toggleClass(elem, name, force) { if (force || typeof force === "undefined" && !hasClass(elem, name)) { addClass(elem, name); } else { removeClass(elem, name); } } function removeClass(elem, name) { var set = " " + elem.className + " "; // Class name may appear multiple times while (set.indexOf(" " + name + " ") >= 0) { set = set.replace(" " + name + " ", " "); } // Trim for prettiness elem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\s+|\s+$/g, ""); } function id(name) { return document$$1.getElementById && document$$1.getElementById(name); } function abortTests() { var abortButton = id("qunit-abort-tests-button"); if (abortButton) { abortButton.disabled = true; abortButton.innerHTML = "Aborting..."; } QUnit.config.queue.length = 0; return false; } function interceptNavigation(ev) { applyUrlParams(); if (ev && ev.preventDefault) { ev.preventDefault(); } return false; } function getUrlConfigHtml() { var i, j, val, escaped, escapedTooltip, selection = false, urlConfig = config.urlConfig, urlConfigHtml = ""; for (i = 0; i < urlConfig.length; i++) { // Options can be either strings or objects with nonempty "id" properties val = config.urlConfig[i]; if (typeof val === "string") { val = { id: val, label: val }; } escaped = escapeText(val.id); escapedTooltip = escapeText(val.tooltip); if (!val.value || typeof val.value === "string") { 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>"; } else { urlConfigHtml += "<label for='qunit-urlconfig-" + escaped + "' title='" + escapedTooltip + "'>" + val.label + ": </label><select id='qunit-urlconfig-" + escaped + "' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>"; if (QUnit.is("array", val.value)) { for (j = 0; j < val.value.length; j++) { escaped = escapeText(val.value[j]); urlConfigHtml += "<option value='" + escaped + "'" + (config[val.id] === val.value[j] ? (selection = true) && " selected='selected'" : "") + ">" + escaped + "</option>"; } } else { for (j in val.value) { if (hasOwn.call(val.value, j)) { urlConfigHtml += "<option value='" + escapeText(j) + "'" + (config[val.id] === j ? (selection = true) && " selected='selected'" : "") + ">" + escapeText(val.value[j]) + "</option>"; } } } if (config[val.id] && !selection) { escaped = escapeText(config[val.id]); urlConfigHtml += "<option value='" + escaped + "' selected='selected' disabled='disabled'>" + escaped + "</option>"; } urlConfigHtml += "</select>"; } } return urlConfigHtml; } // Handle "click" events on toolbar checkboxes and "change" for select menus. // Updates the URL with the new state of `config.urlConfig` values. function toolbarChanged() { var updatedUrl, value, tests, field = this, params = {}; // Detect if field is a select menu or a checkbox if ("selectedIndex" in field) { value = field.options[field.selectedIndex].value || undefined; } else { value = field.checked ? field.defaultValue || true : undefined; } params[field.name] = value; updatedUrl = setUrl(params); // Check if we can apply the change without a page refresh if ("hidepassed" === field.name && "replaceState" in window.history) { QUnit.urlParams[field.name] = value; config[field.name] = value || false; tests = id("qunit-tests"); if (tests) { toggleClass(tests, "hidepass", value || false); } window.history.replaceState(null, "", updatedUrl); } else { window.location = updatedUrl; } } function setUrl(params) { var key, arrValue, i, querystring = "?", location = window.location; params = QUnit.extend(QUnit.extend({}, QUnit.urlParams), params); for (key in params) { // Skip inherited or undefined properties if (hasOwn.call(params, key) && params[key] !== undefined) { // Output a parameter for each value of this key (but usually just one) arrValue = [].concat(params[key]); for (i = 0; i < arrValue.length; i++) { querystring += encodeURIComponent(key); if (arrValue[i] !== true) { querystring += "=" + encodeURIComponent(arrValue[i]); } querystring += "&"; } } } return location.protocol + "//" + location.host + location.pathname + querystring.slice(0, -1); } function applyUrlParams() { var i, selectedModules = [], modulesList = id("qunit-modulefilter-dropdown-list").getElementsByTagName("input"), filter = id("qunit-filter-input").value; for (i = 0; i < modulesList.length; i++) { if (modulesList[i].checked) { selectedModules.push(modulesList[i].value); } } window.location = setUrl({ filter: filter === "" ? undefined : filter, moduleId: selectedModules.length === 0 ? undefined : selectedModules, // Remove module and testId filter module: undefined, testId: undefined }); } function toolbarUrlConfigContainer() { var urlConfigContainer = document$$1.createElement("span"); urlConfigContainer.innerHTML = getUrlConfigHtml(); addClass(urlConfigContainer, "qunit-url-config"); addEvents(urlConfigContainer.getElementsByTagName("input"), "change", toolbarChanged); addEvents(urlConfigContainer.getElementsByTagName("select"), "change", toolbarChanged); return urlConfigContainer; } function abortTestsButton() { var button = document$$1.createElement("button"); button.id = "qunit-abort-tests-button"; button.innerHTML = "Abort"; addEvent(button, "click", abortTests); return button; } function toolbarLooseFilter() { var filter = document$$1.createElement("form"), label = document$$1.createElement("label"), input = document$$1.createElement("input"), button = document$$1.createElement("button"); addClass(filter, "qunit-filter"); label.innerHTML = "Filter: "; input.type = "text"; input.value = config.filter || ""; input.name = "filter"; input.id = "qunit-filter-input"; button.innerHTML = "Go"; label.appendChild(input); filter.appendChild(label); filter.appendChild(document$$1.createTextNode(" ")); filter.appendChild(button); addEvent(filter, "submit", interceptNavigation); return filter; } function moduleListHtml() { var i, checked, html = ""; for (i = 0; i < config.modules.length; i++) { if (config.modules[i].name !== "") { checked = config.moduleId.indexOf(config.modules[i].moduleId) > -1; 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>"; } } return html; } function toolbarModuleFilter() { var allCheckbox, commit, reset, moduleFilter = document$$1.createElement("form"), label = document$$1.createElement("label"), moduleSearch = document$$1.createElement("input"), dropDown = document$$1.createElement("div"), actions = document$$1.createElement("span"), dropDownList = document$$1.createElement("ul"), dirty = false; moduleSearch.id = "qunit-modulefilter-search"; addEvent(moduleSearch, "input", searchInput); addEvent(moduleSearch, "input", searchFocus); addEvent(moduleSearch, "focus", searchFocus); addEvent(moduleSearch, "click", searchFocus); label.id = "qunit-modulefilter-search-container"; label.innerHTML = "Module: "; label.appendChild(moduleSearch); actions.id = "qunit-modulefilter-actions"; actions.innerHTML = "<button style='display:none'>Apply</button>" + "<button type='reset' style='display:none'>Reset</button>" + "<label class='clickable" + (config.moduleId.length ? "" : " checked") + "'><input type='checkbox'" + (config.moduleId.length ? "" : " checked='checked'") + ">All modules</label>"; allCheckbox = actions.lastChild.firstChild; commit = actions.firstChild; reset = commit.nextSibling; addEvent(commit, "click", applyUrlParams); dropDownList.id = "qunit-modulefilter-dropdown-list"; dropDownList.innerHTML = moduleListHtml(); dropDown.id = "qunit-modulefilter-dropdown"; dropDown.style.display = "none"; dropDown.appendChild(actions); dropDown.appendChild(dropDownList); addEvent(dropDown, "change", selectionChange); selectionChange(); moduleFilter.id = "qunit-modulefilter"; moduleFilter.appendChild(label); moduleFilter.appendChild(dropDown); addEvent(moduleFilter, "submit", interceptNavigation); addEvent(moduleFilter, "reset", function () { // Let the reset happen, then update styles window.setTimeout(selectionChange); }); // Enables show/hide for the dropdown function searchFocus() { if (dropDown.style.display !== "none") { return; } dropDown.style.display = "block"; addEvent(document$$1, "click", hideHandler); addEvent(document$$1, "keydown", hideHandler); // Hide on Escape keydown or outside-container click function hideHandler(e) { var inContainer = moduleFilter.contains(e.target); if (e.keyCode === 27 || !inContainer) { if (e.keyCode === 27 && inContainer) { moduleSearch.focus(); } dropDown.style.display = "none"; removeEvent(document$$1, "click", hideHandler); removeEvent(document$$1, "keydown", hideHandler); moduleSearch.value = ""; searchInput(); } } } // Processes module search box input function searchInput() { var i, item, searchText = moduleSearch.value.toLowerCase(), listItems = dropDownList.children; for (i = 0; i < listItems.length; i++) { item = listItems[i]; if (!searchText || item.textContent.toLowerCase().indexOf(searchText) > -1) { item.style.display = ""; } else { item.style.display = "none"; } } } // Processes selection changes function selectionChange(evt) { var i, item, checkbox = evt && evt.target || allCheckbox, modulesList = dropDownList.getElementsByTagName("input"), selectedNames = []; toggleClass(checkbox.parentNode, "checked", checkbox.checked); dirty = false; if (checkbox.checked && checkbox !== allCheckbox) { allCheckbox.checked = false; removeClass(allCheckbox.parentNode, "checked"); } for (i = 0; i < modulesList.length; i++) { item = modulesList[i]; if (!evt) { toggleClass(item.parentNode, "checked", item.checked); } else if (checkbox === allCheckbox && checkbox.checked) { item.checked = false; removeClass(item.parentNode, "checked"); } dirty = dirty || item.checked !== item.defaultChecked; if (item.checked) { selectedNames.push(item.parentNode.textContent); } } commit.style.display = reset.style.display = dirty ? "" : "none"; moduleSearch.placeholder = selectedNames.join(", ") || allCheckbox.parentNode.textContent; moduleSearch.title = "Type to filter list. Current selection:\n" + (selectedNames.join("\n") || allCheckbox.parentNode.textContent); } return moduleFilter; } function appendToolbar() { var toolbar = id("qunit-testrunner-toolbar"); if (toolbar) { toolbar.appendChild(toolbarUrlConfigContainer()); toolbar.appendChild(toolbarModuleFilter()); toolbar.appendChild(toolbarLooseFilter()); toolbar.appendChild(document$$1.createElement("div")).className = "clearfix"; } } function appendHeader() { var header = id("qunit-header"); if (header) { header.innerHTML = "<a href='" + escapeText(unfilteredUrl) + "'>" + header.innerHTML + "</a> "; } } function appendBanner() { var banner = id("qunit-banner"); if (banner) { banner.className = ""; } } function appendTestResults() { var tests = id("qunit-tests"), result = id("qunit-testresult"), controls; if (result) { result.parentNode.removeChild(result); } if (tests) { tests.innerHTML = ""; result = document$$1.createElement("p"); result.id = "qunit-testresult"; result.className = "result"; tests.parentNode.insertBefore(result, tests); result.innerHTML = "<div id=\"qunit-testresult-display\">Running...<br /> </div>" + "<div id=\"qunit-testresult-controls\"></div>" + "<div class=\"clearfix\"></div>"; controls = id("qunit-testresult-controls"); } if (controls) { controls.appendChild(abortTestsButton()); } } function appendFilteredTest() { var testId = QUnit.config.testId; if (!testId || testId.length <= 0) { return ""; } return "<div id='qunit-filteredTest'>Rerunning selected tests: " + escapeText(testId.join(", ")) + " <a id='qunit-clearFilter' href='" + escapeText(unfilteredUrl) + "'>Run all tests</a></div>"; } function appendUserAgent() { var userAgent = id("qunit-userAgent"); if (userAgent) { userAgent.innerHTML = ""; userAgent.appendChild(document$$1.createTextNode("QUnit " + QUnit.version + "; " + navigator.userAgent)); } } function appendInterface() { var qunit = id("qunit"); if (qunit) { qunit.innerHTML = "<h1 id='qunit-header'>" + escapeText(document$$1.title) + "</h1>" + "<h2 id='qunit-banner'></h2>" + "<div id='qunit-testrunner-toolbar'></div>" + appendFilteredTest() + "<h2 id='qunit-userAgent'></h2>" + "<ol id='qunit-tests'></ol>"; } appendHeader(); appendBanner(); appendTestResults(); appendUserAgent(); appendToolbar(); } function appendTestsList(modules) { var i, l, x, z, test, moduleObj; for (i = 0, l = modules.length; i < l; i++) { moduleObj = modules[i]; for (x = 0, z = moduleObj.tests.length; x < z; x++) { test = moduleObj.tests[x]; appendTest(test.name, test.testId, moduleObj.name); } } } function appendTest(name, testId, moduleName) { var title, rerunTrigger, testBlock, assertList, tests = id("qunit-tests"); if (!tests) { return; } title = document$$1.createElement("strong"); title.innerHTML = getNameHtml(name, moduleName); rerunTrigger = document$$1.createElement("a"); rerunTrigger.innerHTML = "Rerun"; rerunTrigger.href = setUrl({ testId: testId }); testBlock = document$$1.createElement("li"); testBlock.appendChild(title); testBlock.appendChild(rerunTrigger); testBlock.id = "qunit-test-output-" + testId; assertList = document$$1.createElement("ol"); assertList.className = "qunit-assert-list"; testBlock.appendChild(assertList); tests.appendChild(testBlock); } // HTML Reporter initialization and load QUnit.begin(function (details) { var i, moduleObj, tests; // Sort modules by name for the picker for (i = 0; i < details.modules.length; i++) { moduleObj = details.modules[i]; if (moduleObj.name) { modulesList.push(moduleObj.name); } } modulesList.sort(function (a, b) { return a.localeCompare(b); }); // Initialize QUnit elements appendInterface(); appendTestsList(details.modules); tests = id("qunit-tests"); if (tests && config.hidepassed) { addClass(tests, "hidepass"); } }); QUnit.done(function (details) { var banner = id("qunit-banner"), tests = id("qunit-tests"), abortButton = id("qunit-abort-tests-button"), totalTests = stats.passedTests + stats.skippedTests + stats.todoTests + stats.failedTests, 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(""), test, assertLi, assertList; // Update remaing tests to aborted if (abortButton && abortButton.disabled) { html = "Tests aborted after " + details.runtime + " milliseconds."; for (var i = 0; i < tests.children.length; i++) { test = tests.children[i]; if (test.className === "" || test.className === "running") { test.className = "aborted"; assertList = test.getElementsByTagName("ol")[0]; assertLi = document$$1.createElement("li"); assertLi.className = "fail"; assertLi.innerHTML = "Test aborted."; assertList.appendChild(assertLi); } } } if (banner && (!abortButton || abortButton.disabled === false)) { banner.className = stats.failedTests ? "qunit-fail" : "qunit-pass"; } if (abortButton) { abortButton.parentNode.removeChild(abortButton); } if (tests) { id("qunit-testresult-display").innerHTML = html; } if (config.altertitle && document$$1.title) { // Show ✖ for good, ✔ for bad suite result in title // use escape sequences in case file gets loaded with non-utf-8-charset document$$1.title = [stats.failedTests ? "\u2716" : "\u2714", document$$1.title.replace(/^[\u2714\u2716] /i, "")].join(" "); } // Scroll back to top to show results if (config.scrolltop && window.scrollTo) { window.scrollTo(0, 0); } }); function getNameHtml(name, module) { var nameHtml = ""; if (module) { nameHtml = "<span class='module-name'>" + escapeText(module) + "</span>: "; } nameHtml += "<span class='test-name'>" + escapeText(name) + "</span>"; return nameHtml; } QUnit.testStart(function (details) { var running, testBlock, bad; testBlock = id("qunit-test-output-" + details.testId); if (testBlock) { testBlock.className = "running"; } else { // Report later registered tests appendTest(details.name, details.testId, details.module); } running = id("qunit-testresult-display"); if (running) { bad = QUnit.config.reorder && details.previousFailure; running.innerHTML = (bad ? "Rerunning previously failed test: <br />" : "Running: <br />") + getNameHtml(details.name, details.module); } }); function stripHtml(string) { // Strip tags, html entity and whitespaces return string.replace(/<\/?[^>]+(>|$)/g, "").replace(/\"/g, "").replace(/\s+/g, ""); } QUnit.log(function (details) { var assertList, assertLi, message, expected, actual, diff, showDiff = false, testItem = id("qunit-test-output-" + details.testId); if (!testItem) { return; } message = escapeText(details.message) || (details.result ? "okay" : "failed"); message = "<span class='test-message'>" + message + "</span>"; message += "<span class='runtime'>@ " + details.runtime + " ms</span>"; // The pushFailure doesn't provide details.expected // when it calls, it's implicit to also not show expected and diff stuff // Also, we need to check details.expected existence, as it can exist and be undefined if (!details.result && hasOwn.call(details, "expected")) { if (details.negative) { expected = "NOT " + QUnit.dump.parse(details.expected); } else { expected = QUnit.dump.parse(details.expected); } actual = QUnit.dump.parse(details.actual); message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + escapeText(expected) + "</pre></td></tr>"; if (actual !== expected) { message += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText(actual) + "</pre></td></tr>"; // Don't show diff if actual or expected are booleans if (!/^(true|false)$/.test(actual) && !/^(true|false)$/.test(expected)) { diff = QUnit.diff(expected, actual); showDiff = stripHtml(diff).length !== stripHtml(expected).length + stripHtml(actual).length; } // Don't show diff if expected and actual are totally different if (showDiff) { message += "<tr class='test-diff'><th>Diff: </th><td><pre>" + diff + "</pre></td></tr>"; } } else if (expected.indexOf("[object Array]") !== -1 || expected.indexOf("[object Object]") !== -1) { 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>"; } else { message += "<tr class='test-message'><th>Message: </th><td>" + "Diff suppressed as the expected and actual results have an equivalent" + " serialization</td></tr>"; } if (details.source) { message += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText(details.source) + "</pre></td></tr>"; } message += "</table>"; // This occurs when pushFailure is set and we have an extracted stack trace } else if (!details.result && details.source) { message += "<table>" + "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText(details.source) + "</pre></td></tr>" + "</table>"; } assertList = testItem.getElementsByTagName("ol")[0]; assertLi = document$$1.createElement("li"); assertLi.className = details.result ? "pass" : "fail"; assertLi.innerHTML = message; assertList.appendChild(assertLi); }); QUnit.testDone(function (details) { var testTitle, time, testItem, assertList, good, bad, testCounts, skipped, sourceName, tests = id("qunit-tests"); if (!tests) { return; } testItem = id("qunit-test-output-" + details.testId); assertList = testItem.getElementsByTagName("ol")[0]; good = details.passed; bad = details.failed; // This test passed if it has no unexpected failed assertions var testPassed = details.failed > 0 ? details.todo : !details.todo; if (testPassed) { // Collapse the passing tests addClass(assertList, "qunit-collapsed"); } else if (config.collapse) { if (!collapseNext) { // Skip collapsing the first failing test collapseNext = true; } else { // Collapse remaining tests addClass(assertList, "qunit-collapsed"); } } // The testItem.firstChild is the test name testTitle = testItem.firstChild; testCounts = bad ? "<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " : ""; testTitle.innerHTML += " <b class='counts'>(" + testCounts + details.assertions.length + ")</b>"; if (details.skipped) { stats.skippedTests++; testItem.className = "skipped"; skipped = document$$1.createElement("em"); skipped.className = "qunit-skipped-label"; skipped.innerHTML = "skipped"; testItem.insertBefore(skipped, testTitle); } else { addEvent(testTitle, "click", function () { toggleClass(assertList, "qunit-collapsed"); }); testItem.className = testPassed ? "pass" : "fail"; if (details.todo) { var todoLabel = document$$1.createElement("em"); todoLabel.className = "qunit-todo-label"; todoLabel.innerHTML = "todo"; testItem.className += " todo"; testItem.insertBefore(todoLabel, testTitle); } time = document$$1.createElement("span"); time.className = "runtime"; time.innerHTML = details.runtime + " ms"; testItem.insertBefore(time, assertList); if (!testPassed) { stats.failedTests++; } else if (details.todo) { stats.todoTests++; } else { stats.passedTests++; } } // Show the source of the test when showing assertions if (details.source) { sourceName = document$$1.createElement("p"); sourceName.innerHTML = "<strong>Source: </strong>" + details.source; addClass(sourceName, "qunit-source"); if (testPassed) { addClass(sourceName, "qunit-collapsed"); } addEvent(testTitle, "click", function () { toggleClass(sourceName, "qunit-collapsed"); }); testItem.appendChild(sourceName); } }); // Avoid readyState issue with phantomjs // Ref: #818 var notPhantom = function (p) { return !(p && p.version && p.version.major > 0); }(window.phantom); if (notPhantom && document$$1.readyState === "complete") { QUnit.load(); } else { addEvent(window, "load", QUnit.load); } // Wrap window.onerror. We will call the original window.onerror to see if // the existing handler fully handles the error; if not, we will call the // QUnit.onError function. var originalWindowOnError = window.onerror; // Cover uncaught exceptions // Returning true will suppress the default browser handler, // returning false will let it run. window.onerror = function (message, fileName, lineNumber) { var ret = false; if (originalWindowOnError) { for (var _len = arguments.length, args = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) { args[_key - 3] = arguments[_key]; } ret = originalWindowOnError.call.apply(originalWindowOnError, [this, message, fileName, lineNumber].concat(args)); } // Treat return value as window.onerror itself does, // Only do our handling if not suppressed. if (ret !== true) { var error = { message: message, fileName: fileName, lineNumber: lineNumber }; ret = QUnit.onError(error); } return ret; }; })(); /* * This file is a modified version of google-diff-match-patch's JavaScript implementation * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js), * modifications are licensed as more fully set forth in LICENSE.txt. * * The original source of google-diff-match-patch is attributable and licensed as follows: * * Copyright 2006 Google Inc. * https://code.google.com/p/google-diff-match-patch/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * More Info: * https://code.google.com/p/google-diff-match-patch/ * * Usage: QUnit.diff(expected, actual) * */ QUnit.diff = function () { function DiffMatchPatch() {} // DIFF FUNCTIONS /** * The data structure representing a diff is an array of tuples: * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']] * which means: delete 'Hello', add 'Goodbye' and keep ' world.' */ var DIFF_DELETE = -1, DIFF_INSERT = 1, DIFF_EQUAL = 0; /** * Find the differences between two texts. Simplifies the problem by stripping * any common prefix or suffix off the texts before diffing. * @param {string} text1 Old string to be diffed. * @param {string} text2 New string to be diffed. * @param {boolean=} optChecklines Optional speedup flag. If present and false, * then don't run a line-level diff first to identify the changed areas. * Defaults to true, which does a faster, slightly less optimal diff. * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples. */ DiffMatchPatch.prototype.DiffMain = function (text1, text2, optChecklines) { var deadline, checklines, commonlength, commonprefix, commonsuffix, diffs; // The diff must be complete in up to 1 second. deadline = new Date().getTime() + 1000; // Check for null inputs. if (text1 === null || text2 === null) { throw new Error("Null input. (DiffMain)"); } // Check for equality (speedup). if (text1 === text2) { if (text1) { return [[DIFF_EQUAL, text1]]; } return []; } if (typeof optChecklines === "undefined") { optChecklines = true; } checklines = optChecklines; // Trim off common prefix (speedup). commonlength = this.diffCommonPrefix(text1, text2); commonprefix = text1.substring(0, commonlength); text1 = text1.substring(commonlength); text2 = text2.substring(commonlength); // Trim off common suffix (speedup). commonlength = this.diffCommonSuffix(text1, text2); commonsuffix = text1.substring(text1.length - commonlength); text1 = text1.substring(0, text1.length - commonlength); text2 = text2.substring(0, text2.length - commonlength); // Compute the diff on the middle block. diffs = this.diffCompute(text1, text2, checklines, deadline); // Restore the prefix and suffix. if (commonprefix) { diffs.unshift([DIFF_EQUAL, commonprefix]); } if (commonsuffix) { diffs.push([DIFF_EQUAL, commonsuffix]); } this.diffCleanupMerge(diffs); return diffs; }; /** * Reduce the number of edits by eliminating operationally trivial equalities. * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples. */ DiffMatchPatch.prototype.diffCleanupEfficiency = function (diffs) { var changes, equalities, equalitiesLength, lastequality, pointer, preIns, preDel, postIns, postDel; changes = false; equalities = []; // Stack of indices where equalities are found. equalitiesLength = 0; // Keeping our own length var is faster in JS. /** @type {?string} */ lastequality = null; // Always equal to diffs[equalities[equalitiesLength - 1]][1] pointer = 0; // Index of current position. // Is there an insertion operation before the last equality. preIns = false; // Is there a deletion operation before the last equality. preDel = false; // Is there an insertion operation after the last equality. postIns = false; // Is there a deletion operation after the last equality. postDel = false; while (pointer < diffs.length) { // Equality found. if (diffs[pointer][0] === DIFF_EQUAL) { if (diffs[pointer][1].length < 4 && (postIns || postDel)) { // Candidate found. equalities[equalitiesLength++] = pointer; preIns = postIns; preDel = postDel; lastequality = diffs[pointer][1]; } else { // Not a candidate, and can never become one. equalitiesLength = 0; lastequality = null; } postIns = postDel = false; // An insertion or deletion. } else { if (diffs[pointer][0] === DIFF_DELETE) { postDel = true; } else { postIns = true; } /* * Five types to be split: * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del> * <ins>A</ins>X<ins>C</ins><del>D</del> * <ins>A</ins><del>B</del>X<ins>C</ins> * <ins>A</del>X<ins>C</ins><del>D</del> * <ins>A</ins><del>B</del>X<del>C</del> */ if (lastequality && (preIns && preDel && postIns && postDel || lastequality.length < 2 && preIns + preDel + postIns + postDel === 3)) { // Duplicate record. diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]); // Change second copy to insert. diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; equalitiesLength--; // Throw away the equality we just deleted; lastequality = null; if (preIns && preDel) { // No changes made which could affect previous entry, keep going. postIns = postDel = true; equalitiesLength = 0; } else { equalitiesLength--; // Throw away the previous equality. pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; postIns = postDel = false; } changes = true; } } pointer++; } if (changes) { this.diffCleanupMerge(diffs); } }; /** * Convert a diff array into a pretty HTML report. * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples. * @param {integer} string to be beautified. * @return {string} HTML representation. */ DiffMatchPatch.prototype.diffPrettyHtml = function (diffs) { var op, data, x, html = []; for (x = 0; x < diffs.length; x++) { op = diffs[x][0]; // Operation (insert, delete, equal) data = diffs[x][1]; // Text of change. switch (op) { case DIFF_INSERT: html[x] = "<ins>" + escapeText(data) + "</ins>"; break; case DIFF_DELETE: html[x] = "<del>" + escapeText(data) + "</del>"; break; case DIFF_EQUAL: html[x] = "<span>" + escapeText(data) + "</span>"; break; } } return html.join(""); }; /** * Determine the common prefix of two strings. * @param {string} text1 First string. * @param {string} text2 Second string. * @return {number} The number of characters common to the start of each * string. */ DiffMatchPatch.prototype.diffCommonPrefix = function (text1, text2) { var pointermid, pointermax, pointermin, pointerstart; // Quick check for common null cases. if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) { return 0; } // Binary search. // Performance analysis: https://neil.fraser.name/news/2007/10/09/ pointermin = 0; pointermax = Math.min(text1.length, text2.length); pointermid = pointermax; pointerstart = 0; while (pointermin < pointermid) { if (text1.substring(pointerstart, pointermid) === text2.substring(pointerstart, pointermid)) { pointermin = pointermid; pointerstart = pointermin; } else { pointermax = pointermid; } pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); } return pointermid; }; /** * Determine the common suffix of two strings. * @param {string} text1 First string. * @param {string} text2 Second string. * @return {number} The number of characters common to the end of each string. */ DiffMatchPatch.prototype.diffCommonSuffix = function (text1, text2) { var pointermid, pointermax, pointermin, pointerend; // Quick check for common null cases. if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) { return 0; } // Binary search. // Performance analysis: https://neil.fraser.name/news/2007/10/09/ pointermin = 0; pointermax = Math.min(text1.length, text2.length); pointermid = pointermax; pointerend = 0; while (pointermin < pointermid) { if (text1.substring(text1.length - pointermid, text1.length - pointerend) === text2.substring(text2.length - pointermid, text2.length - pointerend)) { pointermin = pointermid; pointerend = pointermin; } else { pointermax = pointermid; } pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); } return pointermid; }; /** * Find the differences between two texts. Assumes that the texts do not * have any common prefix or suffix. * @param {string} text1 Old string to be diffed. * @param {string} text2 New string to be diffed. * @param {boolean} checklines Speedup flag. If false, then don't run a * line-level diff first to identify the changed areas. * If true, then run a faster, slightly less optimal diff. * @param {number} deadline Time when the diff should be complete by. * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples. * @private */ DiffMatchPatch.prototype.diffCompute = function (text1, text2, checklines, deadline) { var diffs, longtext, shorttext, i, hm, text1A, text2A, text1B, text2B, midCommon, diffsA, diffsB; if (!text1) { // Just add some text (speedup). return [[DIFF_INSERT, text2]]; } if (!text2) { // Just delete some text (speedup). return [[DIFF_DELETE, text1]]; } longtext = text1.length > text2.length ? text1 : text2; shorttext = text1.length > text2.length ? text2 : text1; i = longtext.indexOf(shorttext); if (i !== -1) { // Shorter text is inside the longer text (speedup). diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]]; // Swap insertions for deletions if diff is reversed. if (text1.length > text2.length) { diffs[0][0] = diffs[2][0] = DIFF_DELETE; } return diffs; } if (shorttext.length === 1) { // Single character string. // After the previous speedup, the character can't be an equality. return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; } // Check to see if the problem can be split in two. hm = this.diffHalfMatch(text1, text2); if (hm) { // A half-match was found, sort out the return data. text1A = hm[0]; text1B = hm[1]; text2A = hm[2]; text2B = hm[3]; midCommon = hm[4]; // Send both pairs off for separate processing. diffsA = this.DiffMain(text1A, text2A, checklines, deadline); diffsB = this.DiffMain(text1B, text2B, checklines, deadline); // Merge the results. return diffsA.concat([[DIFF_EQUAL, midCommon]], diffsB); } if (checklines && text1.length > 100 && text2.length > 100) { return this.diffLineMode(text1, text2, deadline); } return this.diffBisect(text1, text2, deadline); }; /** * Do the two texts share a substring which is at least half the length of the * longer text? * This speedup can produce non-minimal diffs. * @param {string} text1 First string. * @param {string} text2 Second string. * @return {Array.<string>} Five element Array, containing the prefix of * text1, the suffix of text1, the prefix of text2, the suffix of * text2 and the common middle. Or null if there was no match. * @private */ DiffMatchPatch.prototype.diffHalfMatch = function (text1, text2) { var longtext, shorttext, dmp, text1A, text2B, text2A, text1B, midCommon, hm1, hm2, hm; longtext = text1.length > text2.length ? text1 : text2; shorttext = text1.length > text2.length ? text2 : text1; if (longtext.length < 4 || shorttext.length * 2 < longtext.length) { return null; // Pointless. } dmp = this; // 'this' becomes 'window' in a closure. /** * Does a substring of shorttext exist within longtext such that the substring * is at least half the length of longtext? * Closure, but does not reference any external variables. * @param {string} longtext Longer string. * @param {string} shorttext Shorter string. * @param {number} i Start index of quarter length substring within longtext. * @return {Array.<string>} Five element Array, containing the prefix of * longtext, the suffix of longtext, the prefix of shorttext, the suffix * of shorttext and the common middle. Or null if there was no match. * @private */ function diffHalfMatchI(longtext, shorttext, i) { var seed, j, bestCommon, prefixLength, suffixLength, bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB; // Start with a 1/4 length substring at position i as a seed. seed = longtext.substring(i, i + Math.floor(longtext.length / 4)); j = -1; bestCommon = ""; while ((j = shorttext.indexOf(seed, j + 1)) !== -1) { prefixLength = dmp.diffCommonPrefix(longtext.substring(i), shorttext.substring(j)); suffixLength = dmp.diffCommonSuffix(longtext.substring(0, i), shorttext.substring(0, j)); if (bestCommon.length < suffixLength + prefixLength) { bestCommon = shorttext.substring(j - suffixLength, j) + shorttext.substring(j, j + prefixLength); bestLongtextA = longtext.substring(0, i - suffixLength); bestLongtextB = longtext.substring(i + prefixLength); bestShorttextA = shorttext.substring(0, j - suffixLength); bestShorttextB = shorttext.substring(j + prefixLength); } } if (bestCommon.length * 2 >= longtext.length) { return [bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB, bestCommon]; } else { return null; } } // First check if the second quarter is the seed for a half-match. hm1 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 4)); // Check again based on the third quarter. hm2 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 2)); if (!hm1 && !hm2) { return null; } else if (!hm2) { hm = hm1; } else if (!hm1) { hm = hm2; } else { // Both matched. Select the longest. hm = hm1[4].length > hm2[4].length ? hm1 : hm2; } // A half-match was found, sort out the return data. if (text1.length > text2.length) { text1A = hm[0]; text1B = hm[1]; text2A = hm[2]; text2B = hm[3]; } else { text2A = hm[0]; text2B = hm[1]; text1A = hm[2]; text1B = hm[3]; } midCommon = hm[4]; return [text1A, text1B, text2A, text2B, midCommon]; }; /** * Do a quick line-level diff on both strings, then rediff the parts for * greater accuracy. * This speedup can produce non-minimal diffs. * @param {string} text1 Old string to be diffed. * @param {string} text2 New string to be diffed. * @param {number} deadline Time when the diff should be complete by. * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples. * @private */ DiffMatchPatch.prototype.diffLineMode = function (text1, text2, deadline) { var a, diffs, linearray, pointer, countInsert, countDelete, textInsert, textDelete, j; // Scan the text on a line-by-line basis first. a = this.diffLinesToChars(text1, text2); text1 = a.chars1; text2 = a.chars2; linearray = a.lineArray; diffs = this.DiffMain(text1, text2, false, deadline); // Convert the diff back to original text. this.diffCharsToLines(diffs, linearray); // Eliminate freak matches (e.g. blank lines) this.diffCleanupSemantic(diffs); // Rediff any replacement blocks, this time character-by-character. // Add a dummy entry at the end. diffs.push([DIFF_EQUAL, ""]); pointer = 0; countDelete = 0; countInsert = 0; textDelete = ""; textInsert = ""; while (pointer < diffs.length) { switch (diffs[pointer][0]) { case DIFF_INSERT: countInsert++; textInsert += diffs[pointer][1]; break; case DIFF_DELETE: countDelete++; textDelete += diffs[pointer][1]; break; case DIFF_EQUAL: // Upon reaching an equality, check for prior redundancies. if (countDelete >= 1 && countInsert >= 1) { // Delete the offending records and add the merged ones. diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert); pointer = pointer - countDelete - countInsert; a = this.DiffMain(textDelete, textInsert, false, deadline); for (j = a.length - 1; j >= 0; j--) { diffs.splice(pointer, 0, a[j]); } pointer = pointer + a.length; } countInsert = 0; countDelete = 0; textDelete = ""; textInsert = ""; break; } pointer++; } diffs.pop(); // Remove the dummy entry at the end. return diffs; }; /** * Find the 'middle snake' of a diff, split the problem in two * and return the recursively constructed diff. * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations. * @param {string} text1 Old string to be diffed. * @param {string} text2 New string to be diffed. * @param {number} deadline Time at which to bail if not yet complete. * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples. * @private */ DiffMatchPatch.prototype.diffBisect = function (text1, text2, deadline) { var text1Length, text2Length, maxD, vOffset, vLength, v1, v2, x, delta, front, k1start, k1end, k2start, k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2; // Cache the text lengths to prevent multiple calls. text1Length = text1.length; text2Length = text2.length; maxD = Math.ceil((text1Length + text2Length) / 2); vOffset = maxD; vLength = 2 * maxD; v1 = new Array(vLength); v2 = new Array(vLength); // Setting all elements to -1 is faster in Chrome & Firefox than mixing // integers and undefined. for (x = 0; x < vLength; x++) { v1[x] = -1; v2[x] = -1; } v1[vOffset + 1] = 0; v2[vOffset + 1] = 0; delta = text1Length - text2Length; // If the total number of characters is odd, then the front path will collide // with the reverse path. front = delta % 2 !== 0; // Offsets for start and end of k loop. // Prevents mapping of space beyond the grid. k1start = 0; k1end = 0; k2start = 0; k2end = 0; for (d = 0; d < maxD; d++) { // Bail out if deadline is reached. if (new Date().getTime() > deadline) { break; } // Walk the front path one step. for (k1 = -d + k1start; k1 <= d - k1end; k1 += 2) { k1Offset = vOffset + k1; if (k1 === -d || k1 !== d && v1[k1Offset - 1] < v1[k1Offset + 1]) { x1 = v1[k1Offset + 1]; } else { x1 = v1[k1Offset - 1] + 1; } y1 = x1 - k1; while (x1 < text1Length && y1 < text2Length && text1.charAt(x1) === text2.charAt(y1)) { x1++; y1++; } v1[k1Offset] = x1; if (x1 > text1Length) { // Ran off the right of the graph. k1end += 2; } else if (y1 > text2Length) { // Ran off the bottom of the graph. k1start += 2; } else if (front) { k2Offset = vOffset + delta - k1; if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) { // Mirror x2 onto top-left coordinate system. x2 = text1Length - v2[k2Offset]; if (x1 >= x2) { // Overlap detected. return this.diffBisectSplit(text1, text2, x1, y1, deadline); } } } } // Walk the reverse path one step. for (k2 = -d + k2start; k2 <= d - k2end; k2 += 2) { k2Offset = vOffset + k2; if (k2 === -d || k2 !== d && v2[k2Offset - 1] < v2[k2Offset + 1]) { x2 = v2[k2Offset + 1]; } else { x2 = v2[k2Offset - 1] + 1; } y2 = x2 - k2; while (x2 < text1Length && y2 < text2Length && text1.charAt(text1Length - x2 - 1) === text2.charAt(text2Length - y2 - 1)) { x2++; y2++; } v2[k2Offset] = x2; if (x2 > text1Length) { // Ran off the left of the graph. k2end += 2; } else if (y2 > text2Length) { // Ran off the top of the graph. k2start += 2; } else if (!front) { k1Offset = vOffset + delta - k2; if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) { x1 = v1[k1Offset]; y1 = vOffset + x1 - k1Offset; // Mirror x2 onto top-left coordinate system. x2 = text1Length - x2; if (x1 >= x2) { // Overlap detected. return this.diffBisectSplit(text1, text2, x1, y1, deadline); } } } } } // Diff took too long and hit the deadline or // number of diffs equals number of characters, no commonality at all. return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]]; }; /** * Given the location of the 'middle snake', split the diff in two parts * and recurse. * @param {string} text1 Old string to be diffed. * @param {string} text2 New string to be diffed. * @param {number} x Index of split point in text1. * @param {number} y Index of split point in text2. * @param {number} deadline Time at which to bail if not yet complete. * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples. * @private */ DiffMatchPatch.prototype.diffBisectSplit = function (text1, text2, x, y, deadline) { var text1a, text1b, text2a, text2b, diffs, diffsb; text1a = text1.substring(0, x); text2a = text2.substring(0, y); text1b = text1.substring(x); text2b = text2.substring(y); // Compute both diffs serially. diffs = this.DiffMain(text1a, text2a, false, deadline); diffsb = this.DiffMain(text1b, text2b, false, deadline); return diffs.concat(diffsb); }; /** * Reduce the number of edits by eliminating semantically trivial equalities. * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples. */ DiffMatchPatch.prototype.diffCleanupSemantic = function (diffs) { var changes, equalities, equalitiesLength, lastequality, pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1, lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2; changes = false; equalities = []; // Stack of indices where equalities are found. equalitiesLength = 0; // Keeping our own length var is faster in JS. /** @type {?string} */ lastequality = null; // Always equal to diffs[equalities[equalitiesLength - 1]][1] pointer = 0; // Index of current position. // Number of characters that changed prior to the equality. lengthInsertions1 = 0; lengthDeletions1 = 0; // Number of characters that changed after the equality. lengthInsertions2 = 0; lengthDeletions2 = 0; while (pointer < diffs.length) { if (diffs[pointer][0] === DIFF_EQUAL) { // Equality found. equalities[equalitiesLength++] = pointer; lengthInsertions1 = lengthInsertions2; lengthDeletions1 = lengthDeletions2; lengthInsertions2 = 0; lengthDeletions2 = 0; lastequality = diffs[pointer][1]; } else { // An insertion or deletion. if (diffs[pointer][0] === DIFF_INSERT) { lengthInsertions2 += diffs[pointer][1].length; } else { lengthDeletions2 += diffs[pointer][1].length; } // Eliminate an equality that is smaller or equal to the edits on both // sides of it. if (lastequality && lastequality.length <= Math.max(lengthInsertions1, lengthDeletions1) && lastequality.length <= Math.max(lengthInsertions2, lengthDeletions2)) { // Duplicate record. diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]); // Change second copy to insert. diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; // Throw away the equality we just deleted. equalitiesLength--; // Throw away the previous equality (it needs to be reevaluated). equalitiesLength--; pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; // Reset the counters. lengthInsertions1 = 0; lengthDeletions1 = 0; lengthInsertions2 = 0; lengthDeletions2 = 0; lastequality = null; changes = true; } } pointer++; } // Normalize the diff. if (changes) { this.diffCleanupMerge(diffs); } // Find any overlaps between deletions and insertions. // e.g: <del>abcxxx</del><ins>xxxdef</ins> // -> <del>abc</del>xxx<ins>def</ins> // e.g: <del>xxxabc</del><ins>defxxx</ins> // -> <ins>def</ins>xxx<del>abc</del> // Only extract an overlap if it is as big as the edit ahead or behind it. pointer = 1; while (pointer < diffs.length) { if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) { deletion = diffs[pointer - 1][1]; insertion = diffs[pointer][1]; overlapLength1 = this.diffCommonOverlap(deletion, insertion); overlapLength2 = this.diffCommonOverlap(insertion, deletion); if (overlapLength1 >= overlapLength2) { if (overlapLength1 >= deletion.length / 2 || overlapLength1 >= insertion.length / 2) { // Overlap found. Insert an equality and trim the surrounding edits. diffs.splice(pointer, 0, [DIFF_EQUAL, insertion.substring(0, overlapLength1)]); diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlapLength1); diffs[pointer + 1][1] = insertion.substring(overlapLength1); pointer++; } } else { if (overlapLength2 >= deletion.length / 2 || overlapLength2 >= insertion.length / 2) { // Reverse overlap found. // Insert an equality and swap and trim the surrounding edits. diffs.splice(pointer, 0, [DIFF_EQUAL, deletion.substring(0, overlapLength2)]); diffs[pointer - 1][0] = DIFF_INSERT; diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlapLength2); diffs[pointer + 1][0] = DIFF_DELETE; diffs[pointer + 1][1] = deletion.substring(overlapLength2); pointer++; } } pointer++; } pointer++; } }; /** * Determine if the suffix of one string is the prefix of another. * @param {string} text1 First string. * @param {string} text2 Second string. * @return {number} The number of characters common to the end of the first * string and the start of the second string. * @private */ DiffMatchPatch.prototype.diffCommonOverlap = function (text1, text2) { var text1Length, text2Length, textLength, best, length, pattern, found; // Cache the text lengths to prevent multiple calls. text1Length = text1.length; text2Length = text2.length; // Eliminate the null case. if (text1Length === 0 || text2Length === 0) { return 0; } // Truncate the longer string. if (text1Length > text2Length) { text1 = text1.substring(text1Length - text2Length); } else if (text1Length < text2Length) { text2 = text2.substring(0, text1Length); } textLength = Math.min(text1Length, text2Length); // Quick check for the worst case. if (text1 === text2) { return textLength; } // Start by looking for a single character match // and increase length until no match is found. // Performance analysis: https://neil.fraser.name/news/2010/11/04/ best = 0; length = 1; while (true) { pattern = text1.substring(textLength - length); found = text2.indexOf(pattern); if (found === -1) { return best; } length += found; if (found === 0 || text1.substring(textLength - length) === text2.substring(0, length)) { best = length; length++; } } }; /** * Split two texts into an array of strings. Reduce the texts to a string of * hashes where each Unicode character represents one line. * @param {string} text1 First string. * @param {string} text2 Second string. * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}} * An object containing the encoded text1, the encoded text2 and * the array of unique strings. * The zeroth element of the array of unique strings is intentionally blank. * @private */ DiffMatchPatch.prototype.diffLinesToChars = function (text1, text2) { var lineArray, lineHash, chars1, chars2; lineArray = []; // E.g. lineArray[4] === 'Hello\n' lineHash = {}; // E.g. lineHash['Hello\n'] === 4 // '\x00' is a valid character, but various debuggers don't like it. // So we'll insert a junk entry to avoid generating a null character. lineArray[0] = ""; /** * Split a text into an array of strings. Reduce the texts to a string of * hashes where each Unicode character represents one line. * Modifies linearray and linehash through being a closure. * @param {string} text String to encode. * @return {string} Encoded string. * @private */ function diffLinesToCharsMunge(text) { var chars, lineStart, lineEnd, lineArrayLength, line; chars = ""; // Walk the text, pulling out a substring for each line. // text.split('\n') would would temporarily double our memory footprint. // Modifying text would create many large strings to garbage collect. lineStart = 0; lineEnd = -1; // Keeping our own length variable is faster than looking it up. lineArrayLength = lineArray.length; while (lineEnd < text.length - 1) { lineEnd = text.indexOf("\n", lineStart); if (lineEnd === -1) { lineEnd = text.length - 1; } line = text.substring(lineStart, lineEnd + 1); lineStart = lineEnd + 1; if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== undefined) { chars += String.fromCharCode(lineHash[line]); } else { chars += String.fromCharCode(lineArrayLength); lineHash[line] = lineArrayLength; lineArray[lineArrayLength++] = line; } } return chars; } chars1 = diffLinesToCharsMunge(text1); chars2 = diffLinesToCharsMunge(text2); return { chars1: chars1, chars2: chars2, lineArray: lineArray }; }; /** * Rehydrate the text in a diff from a string of line hashes to real lines of * text. * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples. * @param {!Array.<string>} lineArray Array of unique strings. * @private */ DiffMatchPatch.prototype.diffCharsToLines = function (diffs, lineArray) { var x, chars, text, y; for (x = 0; x < diffs.length; x++) { chars = diffs[x][1]; text = []; for (y = 0; y < chars.length; y++) { text[y] = lineArray[chars.charCodeAt(y)]; } diffs[x][1] = text.join(""); } }; /** * Reorder and merge like edit sections. Merge equalities. * Any edit section can move as long as it doesn't cross an equality. * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples. */ DiffMatchPatch.prototype.diffCleanupMerge = function (diffs) { var pointer, countDelete, countInsert, textInsert, textDelete, commonlength, changes, diffPointer, position; diffs.push([DIFF_EQUAL, ""]); // Add a dummy entry at the end. pointer = 0; countDelete = 0; countInsert = 0; textDelete = ""; textInsert = ""; while (pointer < diffs.length) { switch (diffs[pointer][0]) { case DIFF_INSERT: countInsert++; textInsert += diffs[pointer][1]; pointer++; break; case DIFF_DELETE: countDelete++; textDelete += diffs[pointer][1]; pointer++; break; case DIFF_EQUAL: // Upon reaching an equality, check for prior redundancies. if (countDelete + countInsert > 1) { if (countDelete !== 0 && countInsert !== 0) { // Factor out any common prefixes. commonlength = this.diffCommonPrefix(textInsert, textDelete); if (commonlength !== 0) { if (pointer - countDelete - countInsert > 0 && diffs[pointer - countDelete - countInsert - 1][0] === DIFF_EQUAL) { diffs[pointer - countDelete - countInsert - 1][1] += textInsert.substring(0, commonlength); } else { diffs.splice(0, 0, [DIFF_EQUAL, textInsert.substring(0, commonlength)]); pointer++; } textInsert = textInsert.substring(commonlength); textDelete = textDelete.substring(commonlength); } // Factor out any common suffixies. commonlength = this.diffCommonSuffix(textInsert, textDelete); if (commonlength !== 0) { diffs[pointer][1] = textInsert.substring(textInsert.length - commonlength) + diffs[pointer][1]; textInsert = textInsert.substring(0, textInsert.length - commonlength); textDelete = textDelete.substring(0, textDelete.length - commonlength); } } // Delete the offending records and add the merged ones. if (countDelete === 0) { diffs.splice(pointer - countInsert, countDelete + countInsert, [DIFF_INSERT, textInsert]); } else if (countInsert === 0) { diffs.splice(pointer - countDelete, countDelete + countInsert, [DIFF_DELETE, textDelete]); } else { diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert, [DIFF_DELETE, textDelete], [DIFF_INSERT, textInsert]); } pointer = pointer - countDelete - countInsert + (countDelete ? 1 : 0) + (countInsert ? 1 : 0) + 1; } else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) { // Merge this equality with the previous one. diffs[pointer - 1][1] += diffs[pointer][1]; diffs.splice(pointer, 1); } else { pointer++; } countInsert = 0; countDelete = 0; textDelete = ""; textInsert = ""; break; } } if (diffs[diffs.length - 1][1] === "") { diffs.pop(); // Remove the dummy entry at the end. } // Second pass: look for single edits surrounded on both sides by equalities // which can be shifted sideways to eliminate an equality. // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC changes = false; pointer = 1; // Intentionally ignore the first and last element (don't need checking). while (pointer < diffs.length - 1) { if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) { diffPointer = diffs[pointer][1]; position = diffPointer.substring(diffPointer.length - diffs[pointer - 1][1].length); // This is a single edit surrounded by equalities. if (position === diffs[pointer - 1][1]) { // Shift the edit over the previous equality. diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length); diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; diffs.splice(pointer - 1, 1); changes = true; } else if (diffPointer.substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1]) { // Shift the edit over the next equality. diffs[pointer - 1][1] += diffs[pointer + 1][1]; diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1]; diffs.splice(pointer + 1, 1); changes = true; } } pointer++; } // If shifts were made, the diff needs reordering and another shift sweep. if (changes) { this.diffCleanupMerge(diffs); } }; return function (o, n) { var diff, output, text; diff = new DiffMatchPatch(); output = diff.DiffMain(o, n); diff.diffCleanupEfficiency(output); text = diff.diffPrettyHtml(output); return text; }; }();}((function() { return this; }())));QUnit.notifications = function( options ) { "use strict"; options = options || {}; options.icons = options.icons || {}; options.timeout = options.timeout || 4000; options.titles = options.titles || { passed: "Passed!", failed: "Failed!" }; options.bodies = options.bodies || { passed: "{{passed}} of {{total}} passed", failed: "{{passed}} passed. {{failed}} failed." }; var renderBody = function( body, details ) { [ "passed", "failed", "total", "runtime" ].forEach( function( type ) { body = body.replace( "{{" + type + "}}", details[ type ] ); } ); return body; }; function generateQueryString( params ) { var key, querystring = "?"; params = QUnit.extend( QUnit.extend( {}, QUnit.urlParams ), params ); for ( key in params ) { if ( params.hasOwnProperty( key ) ) { if ( params[ key ] === undefined ) { continue; } querystring += encodeURIComponent( key ); if ( params[ key ] !== true ) { querystring += "=" + encodeURIComponent( params[ key ] ); } querystring += "&"; } } return location.protocol + "//" + location.host + location.pathname + querystring.slice( 0, -1 ); } if ( window.Notification ) { QUnit.done( function( details ) { var title, _options = {}, notification; if ( window.Notification && QUnit.urlParams.notifications ) { if ( details.failed === 0 ) { title = options.titles.passed; _options.body = renderBody( options.bodies.passed, details ); if ( options.icons.passed ) { _options.icon = options.icons.passed; } } else { title = options.titles.failed; _options.body = renderBody( options.bodies.failed, details ); if ( options.icons.failed ) { _options.icon = options.icons.failed; } } notification = new window.Notification( title, _options ); setTimeout( function() { notification.close(); }, options.timeout ); } } ); QUnit.begin( function() { var toolbar = document.getElementById( "qunit-testrunner-toolbar" ); if ( !toolbar ) { return; } var notification = document.createElement( "input" ), label = document.createElement( "label" ), disableCheckbox = function() { notification.checked = false; notification.disabled = true; label.style.opacity = 0.5; label.title = notification.title = "Note: Notifications have been " + "disabled in this browser."; }; notification.type = "checkbox"; notification.id = "qunit-notifications"; label.innerHTML = "Notifications"; label.for = "qunit-notifications"; label.title = "Show notifications."; if ( window.Notification.permission === "denied" ) { disableCheckbox(); } else if ( QUnit.urlParams.notifications ) { notification.checked = true; } notification.addEventListener( "click", function( event ) { if ( event.target.checked ) { if ( window.Notification.permission === "granted" ) { window.location = generateQueryString( { notifications: true } ); } else if ( window.Notification.permission === "denied" ) { disableCheckbox(); } else { window.Notification.requestPermission( function( permission ) { if ( permission === "denied" ) { disableCheckbox(); } else { window.location = generateQueryString( { notifications: true } ); } } ); } } else { window.location = generateQueryString( { notifications: undefined } ); } }, false ); toolbar.appendChild( notification ); toolbar.appendChild( label ); } ); }};/* globals jQuery, QUnit */(function() { QUnit.config.urlConfig.push({ id: 'nocontainer', label: 'Hide container'}); QUnit.config.urlConfig.push({ id: 'nolint', label: 'Disable Linting'}); QUnit.config.urlConfig.push({ id: 'dockcontainer', label: 'Dock container'}); QUnit.config.urlConfig.push({ id: 'devmode', label: 'Development mode' }); QUnit.config.testTimeout = QUnit.urlParams.devmode ? null : 60000; //Default Test Timeout 60 Seconds if (QUnit.notifications) { QUnit.notifications({ icons: { passed: '/assets/passed.png', failed: '/assets/failed.png' } }); } function ready(fn) { if (typeof jQuery === 'function') { jQuery(document).ready(fn); return; } if (document.readyState != 'loading'){ fn(); } else { document.addEventListener('DOMContentLoaded', fn); } } ready(function() { var testContainer = document.getElementById('ember-testing-container'); if (!testContainer) { return; } var params = QUnit.urlParams; var containerVisibility = params.nocontainer ? 'hidden' : 'visible'; var containerPosition = (params.dockcontainer || params.devmode) ? 'absolute' : 'relative'; if (params.devmode) { testContainer.className = ' full-screen'; } testContainer.style.visibility = containerVisibility; testContainer.style.position = containerPosition; });})();/* globals jQuery, QUnit, require, requirejs */(function() { function ready(fn) { if (typeof jQuery === 'function') { jQuery(document).ready(fn); return; } if (document.readyState != 'loading'){ fn(); } else { document.addEventListener('DOMContentLoaded', fn); } } var autostart = QUnit.config.autostart !== false; QUnit.config.autostart = false; ready(function() { var QUnitAdapter = require('ember-qunit').QUnitAdapter; Ember.Test.adapter = QUnitAdapter.create(); var testLoaderModulePath = 'ember-cli-test-loader/test-support/index'; if (!requirejs.entries[testLoaderModulePath]) { testLoaderModulePath = 'ember-cli/test-loader'; } var TestLoaderModule = require(testLoaderModulePath); var TestLoader = TestLoaderModule['default']; var addModuleExcludeMatcher = TestLoaderModule['addModuleExcludeMatcher']; var addModuleIncludeMatcher = TestLoaderModule['addModuleIncludeMatcher']; function excludeModule(moduleName) { return QUnit.urlParams.nolint && moduleName.match(/\.(jshint|lint-test)$/); } function includeModule(moduleName) { return moduleName.match(/\.jshint$/); } if (addModuleExcludeMatcher && addModuleIncludeMatcher) { addModuleExcludeMatcher(excludeModule); addModuleIncludeMatcher(includeModule); } else { TestLoader.prototype.shouldLoadModule = function shouldLoadModule(moduleName) { return (moduleName.match(/[-_]test$/) || includeModule(moduleName)) && !excludeModule(moduleName); }; } var moduleLoadFailures = []; TestLoader.prototype.moduleLoadFailure = function(moduleName, error) { moduleLoadFailures.push(error); QUnit.module('TestLoader Failures'); QUnit.test(moduleName + ': could not be loaded', function() { throw error; }); }; QUnit.done(function() { if (moduleLoadFailures.length) { throw new Error('\n' + moduleLoadFailures.join('\n')); } }); setTimeout(function() { TestLoader.load(); if (autostart) { QUnit.start(); } }, 250); });})();define('ember-cli-test-loader/test-support/index', ['exports'], function (exports) { /* globals requirejs, require */ "use strict"; exports.addModuleIncludeMatcher = addModuleIncludeMatcher; exports.addModuleExcludeMatcher = addModuleExcludeMatcher; exports['default'] = TestLoader; var moduleIncludeMatchers = []; var moduleExcludeMatchers = []; function addModuleIncludeMatcher(fn) { moduleIncludeMatchers.push(fn); } ; function addModuleExcludeMatcher(fn) { moduleExcludeMatchers.push(fn); } ; function checkMatchers(matchers, moduleName) { var matcher; for (var i = 0, l = matchers.length; i < l; i++) { matcher = matchers[i]; if (matcher(moduleName)) { return true; } } return false; } function TestLoader() { this._didLogMissingUnsee = false; } ; TestLoader.prototype = { shouldLoadModule: function shouldLoadModule(moduleName) { return moduleName.match(/[-_]test$/); }, listModules: function listModules() { return Object.keys(requirejs.entries); }, listTestModules: function listTestModules() { var moduleNames = this.listModules(); var testModules = []; var moduleName; for (var i = 0; i < moduleNames.length; i++) { moduleName = moduleNames[i]; if (checkMatchers(moduleExcludeMatchers, moduleName)) { continue; } if (checkMatchers(moduleIncludeMatchers, moduleName) || this.shouldLoadModule(moduleName)) { testModules.push(moduleName); } } return testModules; }, loadModules: function loadModules() { var testModules = this.listTestModules(); var testModule; for (var i = 0; i < testModules.length; i++) { testModule = testModules[i]; this.require(testModule); this.unsee(testModule); } } }; TestLoader.prototype.require = function (moduleName) { try { require(moduleName); } catch (e) { this.moduleLoadFailure(moduleName, e); } }; TestLoader.prototype.unsee = function (moduleName) { if (typeof require.unsee === 'function') { require.unsee(moduleName); } else if (!this._didLogMissingUnsee) { this._didLogMissingUnsee = true; if (typeof console !== 'undefined') { console.warn('unable to require.unsee, please upgrade loader.js to >= v3.3.0'); } } }; TestLoader.prototype.moduleLoadFailure = function (moduleName, error) { console.error('Error loading: ' + moduleName, error.stack); }; TestLoader.load = function () { new TestLoader().loadModules(); };});define('ember-qunit', ['exports', 'ember-qunit/module-for', 'ember-qunit/module-for-component', 'ember-qunit/module-for-model', 'ember-qunit/adapter', 'ember-test-helpers', 'qunit'], function (exports, _emberQunitModuleFor, _emberQunitModuleForComponent, _emberQunitModuleForModel, _emberQunitAdapter, _emberTestHelpers, _qunit) { Object.defineProperty(exports, 'module', { enumerable: true, get: function get() { return _qunit.module; } }); Object.defineProperty(exports, 'test', { enumerable: true, get: function get() { return _qunit.test; } }); Object.defineProperty(exports, 'skip', { enumerable: true, get: function get() { return _qunit.skip; } }); Object.defineProperty(exports, 'only', { enumerable: true, get: function get() { return _qunit.only; } }); Object.defineProperty(exports, 'todo', { enumerable: true, get: function get() { return _qunit.todo; } }); exports.moduleFor = _emberQunitModuleFor['default']; exports.moduleForComponent = _emberQunitModuleForComponent['default']; exports.moduleForModel = _emberQunitModuleForModel['default']; exports.setResolver = _emberTestHelpers.setResolver; exports.QUnitAdapter = _emberQunitAdapter['default'];});define('ember-qunit/adapter', ['exports', 'ember', 'qunit'], function (exports, _ember, _qunit) { exports['default'] = _ember['default'].Test.Adapter.extend({ init: function init() { this.doneCallbacks = []; }, asyncStart: function asyncStart() { this.doneCallbacks.push(_qunit['default'].config.current.assert.async()); }, asyncEnd: function asyncEnd() { this.doneCallbacks.pop()(); }, exception: function exception(error) { _qunit['default'].config.current.assert.ok(false, _ember['default'].inspect(error)); } });});define('ember-qunit/module-for-component', ['exports', 'ember-qunit/qunit-module', 'ember-test-helpers'], function (exports, _emberQunitQunitModule, _emberTestHelpers) { exports['default'] = moduleForComponent; function moduleForComponent(name, description, callbacks) { (0, _emberQunitQunitModule.createModule)(_emberTestHelpers.TestModuleForComponent, name, description, callbacks); }});define('ember-qunit/module-for-model', ['exports', 'ember-qunit/qunit-module', 'ember-test-helpers'], function (exports, _emberQunitQunitModule, _emberTestHelpers) { exports['default'] = moduleForModel; function moduleForModel(name, description, callbacks) { (0, _emberQunitQunitModule.createModule)(_emberTestHelpers.TestModuleForModel, name, description, callbacks); }});define('ember-qunit/module-for', ['exports', 'ember-qunit/qunit-module', 'ember-test-helpers'], function (exports, _emberQunitQunitModule, _emberTestHelpers) { exports['default'] = moduleFor; function moduleFor(name, description, callbacks) { (0, _emberQunitQunitModule.createModule)(_emberTestHelpers.TestModule, name, description, callbacks); }});define('ember-qunit/qunit-module', ['exports', 'ember', 'qunit'], function (exports, _ember, _qunit) { exports.createModule = createModule; function beforeEachCallback(callbacks) { if (typeof callbacks !== 'object') { return; } if (!callbacks) { return; } var beforeEach; if (callbacks.beforeEach) { beforeEach = callbacks.beforeEach; delete callbacks.beforeEach; } return beforeEach; } function afterEachCallback(callbacks) { if (typeof callbacks !== 'object') { return; } if (!callbacks) { return; } var afterEach; if (callbacks.afterEach) { afterEach = callbacks.afterEach; delete callbacks.afterEach; } return afterEach; } function createModule(Constructor, name, description, callbacks) { var _beforeEach = beforeEachCallback(callbacks || description); var _afterEach = afterEachCallback(callbacks || description); var module = new Constructor(name, description, callbacks); (0, _qunit.module)(module.name, { beforeEach: function beforeEach() { var _this = this, _arguments = arguments; // provide the test context to the underlying module module.setContext(this); return module.setup.apply(module, arguments).then(function () { if (_beforeEach) { return _beforeEach.apply(_this, _arguments); } }); }, afterEach: function afterEach() { var _arguments2 = arguments; var result = undefined; if (_afterEach) { result = _afterEach.apply(this, arguments); } return _ember['default'].RSVP.resolve(result).then(function () { return module.teardown.apply(module, _arguments2); }); } }); }});define('ember-test-helpers', ['exports', 'ember', 'ember-test-helpers/test-module', 'ember-test-helpers/test-module-for-acceptance', 'ember-test-helpers/test-module-for-integration', 'ember-test-helpers/test-module-for-component', 'ember-test-helpers/test-module-for-model', 'ember-test-helpers/test-context', 'ember-test-helpers/test-resolver'], function (exports, _ember, _emberTestHelpersTestModule, _emberTestHelpersTestModuleForAcceptance, _emberTestHelpersTestModuleForIntegration, _emberTestHelpersTestModuleForComponent, _emberTestHelpersTestModuleForModel, _emberTestHelpersTestContext, _emberTestHelpersTestResolver) { _ember['default'].testing = true; exports.TestModule = _emberTestHelpersTestModule['default']; exports.TestModuleForAcceptance = _emberTestHelpersTestModuleForAcceptance['default']; exports.TestModuleForIntegration = _emberTestHelpersTestModuleForIntegration['default']; exports.TestModuleForComponent = _emberTestHelpersTestModuleForComponent['default']; exports.TestModuleForModel = _emberTestHelpersTestModuleForModel['default']; exports.getContext = _emberTestHelpersTestContext.getContext; exports.setContext = _emberTestHelpersTestContext.setContext; exports.unsetContext = _emberTestHelpersTestContext.unsetContext; exports.setResolver = _emberTestHelpersTestResolver.setResolver;});define('ember-test-helpers/-legacy-overrides', ['exports', 'ember', 'ember-test-helpers/has-ember-version'], function (exports, _ember, _emberTestHelpersHasEmberVersion) { exports.preGlimmerSetupIntegrationForComponent = preGlimmerSetupIntegrationForComponent; function preGlimmerSetupIntegrationForComponent() { var module = this; var context = this.context; this.actionHooks = {}; context.dispatcher = this.container.lookup('event_dispatcher:main') || _ember['default'].EventDispatcher.create(); context.dispatcher.setup({}, '#ember-testing'); context.actions = module.actionHooks; (this.registry || this.container).register('component:-test-holder', _ember['default'].Component.extend()); context.render = function (template) { // in case `this.render` is called twice, make sure to teardown the first invocation module.teardownComponent(); if (!template) { throw new Error("in a component integration test you must pass a template to `render()`"); } if (_ember['default'].isArray(template)) { template = template.join(''); } if (typeof template === 'string') { template = _ember['default'].Handlebars.compile(template); } module.component = module.container.lookupFactory('component:-test-holder').create({ layout: template }); module.component.set('context', context); module.component.set('controller', context); _ember['default'].run(function () { module.component.appendTo('#ember-testing'); }); context._element = module.component.element; }; context.$ = function () { return module.component.$.apply(module.component, arguments); }; context.set = function (key, value) { var ret = _ember['default'].run(function () { return _ember['default'].set(context, key, value); }); if ((0, _emberTestHelpersHasEmberVersion['default'])(2, 0)) { return ret; } }; context.setProperties = function (hash) { var ret = _ember['default'].run(function () { return _ember['default'].setProperties(context, hash); }); if ((0, _emberTestHelpersHasEmberVersion['default'])(2, 0)) { return ret; } }; context.get = function (key) { return _ember['default'].get(context, key); }; context.getProperties = function () { var args = Array.prototype.slice.call(arguments); return _ember['default'].getProperties(context, args); }; context.on = function (actionName, handler) { module.actionHooks[actionName] = handler; }; context.send = function (actionName) { var hook = module.actionHooks[actionName]; if (!hook) { throw new Error("integration testing template received unexpected action " + actionName); } hook.apply(module, Array.prototype.slice.call(arguments, 1)); }; context.clearRender = function () { module.teardownComponent(); }; }});define('ember-test-helpers/abstract-test-module', ['exports', 'ember-test-helpers/wait', 'ember-test-helpers/test-context', 'ember'], function (exports, _emberTestHelpersWait, _emberTestHelpersTestContext, _ember) { var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } // calling this `merge` here because we cannot // actually assume it is like `Object.assign` // with > 2 args var merge = _ember['default'].assign || _ember['default'].merge; var _default = (function () { function _default(name, options) { _classCallCheck(this, _default); this.context = undefined; this.name = name; this.callbacks = options || {}; this.initSetupSteps(); this.initTeardownSteps(); } _createClass(_default, [{ key: 'setup', value: function setup(assert) { var _this = this; return this.invokeSteps(this.setupSteps, this, assert).then(function () { _this.contextualizeCallbacks(); return _this.invokeSteps(_this.contextualizedSetupSteps, _this.context, assert); }); } }, { key: 'teardown', value: function teardown(assert) { var _this2 = this; return this.invokeSteps(this.contextualizedTeardownSteps, this.context, assert).then(function () { return _this2.invokeSteps(_this2.teardownSteps, _this2, assert); }).then(function () { _this2.cache = null; _this2.cachedCalls = null; }); } }, { key: 'initSetupSteps', value: function initSetupSteps() { this.setupSteps = []; this.contextualizedSetupSteps = []; if (this.callbacks.beforeSetup) { this.setupSteps.push(this.callbacks.beforeSetup); delete this.callbacks.beforeSetup; } this.setupSteps.push(this.setupContext); this.setupSteps.push(this.setupTestElements); this.setupSteps.push(this.setupAJAXListeners); if (this.callbacks.setup) { this.contextualizedSetupSteps.push(this.callbacks.setup); delete this.callbacks.setup; } } }, { key: 'invokeSteps', value: function invokeSteps(steps, context, assert) { steps = steps.slice(); function nextStep() { var step = steps.shift(); if (step) { // guard against exceptions, for example missing components referenced from needs. return new _ember['default'].RSVP.Promise(function (resolve) { resolve(step.call(context, assert)); }).then(nextStep); } else { return _ember['default'].RSVP.resolve(); } } return nextStep(); } }, { key: 'contextualizeCallbacks', value: function contextualizeCallbacks() {} }, { key: 'initTeardownSteps', value: function initTeardownSteps() { this.teardownSteps = []; this.contextualizedTeardownSteps = []; if (this.callbacks.teardown) { this.contextualizedTeardownSteps.push(this.callbacks.teardown); delete this.callbacks.teardown; } this.teardownSteps.push(this.teardownContext); this.teardownSteps.push(this.teardownTestElements); this.teardownSteps.push(this.teardownAJAXListeners); if (this.callbacks.afterTeardown) { this.teardownSteps.push(this.callbacks.afterTeardown); delete this.callbacks.afterTeardown; } } }, { key: 'setupTestElements', value: function setupTestElements() { var testEl = document.querySelector('#ember-testing'); if (!testEl) { var element = document.createElement('div'); element.setAttribute('id', 'ember-testing'); document.body.appendChild(element); this.fixtureResetValue = ''; } else { this.fixtureResetValue = testEl.innerHTML; } } }, { key: 'setupContext', value: function setupContext(options) { var context = this.getContext(); merge(context, { dispatcher: null, inject: {} }); merge(context, options); this.setToString(); (0, _emberTestHelpersTestContext.setContext)(context); this.context = context; } }, { key: 'setContext', value: function setContext(context) { this.context = context; } }, { key: 'getContext', value: function getContext() { if (this.context) { return this.context; } return this.context = (0, _emberTestHelpersTestContext.getContext)() || {}; } }, { key: 'setToString', value: function setToString() { var _this3 = this; this.context.toString = function () { if (_this3.subjectName) { return 'test context for: ' + _this3.subjectName; } if (_this3.name) { return 'test context for: ' + _this3.name; } }; } }, { key: 'setupAJAXListeners', value: function setupAJAXListeners() { (0, _emberTestHelpersWait._setupAJAXHooks)(); } }, { key: 'teardownAJAXListeners', value: function teardownAJAXListeners() { (0, _emberTestHelpersWait._teardownAJAXHooks)(); } }, { key: 'teardownTestElements', value: function teardownTestElements() { document.getElementById('ember-testing').innerHTML = this.fixtureResetValue; // Ember 2.0.0 removed Ember.View as public API, so only do this when // Ember.View is present if (_ember['default'].View && _ember['default'].View.views) { _ember['default'].View.views = {}; } } }, { key: 'teardownContext', value: function teardownContext() { var context = this.context; this.context = undefined; (0, _emberTestHelpersTestContext.unsetContext)(); if (context && context.dispatcher && !context.dispatcher.isDestroyed) { _ember['default'].run(function () { context.dispatcher.destroy(); }); } } }]); return _default; })(); exports['default'] = _default;});define('ember-test-helpers/build-registry', ['exports', 'require', 'ember'], function (exports, _require, _ember) { function exposeRegistryMethodsWithoutDeprecations(container) { var methods = ['register', 'unregister', 'resolve', 'normalize', 'typeInjection', 'injection', 'factoryInjection', 'factoryTypeInjection', 'has', 'options', 'optionsForType']; function exposeRegistryMethod(container, method) { if (method in container) { container[method] = function () { return container._registry[method].apply(container._registry, arguments); }; } } for (var i = 0, l = methods.length; i < l; i++) { exposeRegistryMethod(container, methods[i]); } } var Owner = (function () { if (_ember['default']._RegistryProxyMixin && _ember['default']._ContainerProxyMixin) { return _ember['default'].Object.extend(_ember['default']._RegistryProxyMixin, _ember['default']._ContainerProxyMixin); } return _ember['default'].Object.extend(); })(); exports['default'] = function (resolver) { var fallbackRegistry, registry, container; var namespace = _ember['default'].Object.create({ Resolver: { create: function create() { return resolver; } } }); function register(name, factory) { var thingToRegisterWith = registry || container; if (!(container.factoryFor ? container.factoryFor(name) : container.lookupFactory(name))) { thingToRegisterWith.register(name, factory); } } if (_ember['default'].Application.buildRegistry) { fallbackRegistry = _ember['default'].Application.buildRegistry(namespace); fallbackRegistry.register('component-lookup:main', _ember['default'].ComponentLookup); registry = new _ember['default'].Registry({ fallback: fallbackRegistry }); if (_ember['default'].ApplicationInstance && _ember['default'].ApplicationInstance.setupRegistry) { _ember['default'].ApplicationInstance.setupRegistry(registry); } // these properties are set on the fallback registry by `buildRegistry` // and on the primary registry within the ApplicationInstance constructor // but we need to manually recreate them since ApplicationInstance's are not // exposed externally registry.normalizeFullName = fallbackRegistry.normalizeFullName; registry.makeToString = fallbackRegistry.makeToString; registry.describe = fallbackRegistry.describe; var owner = Owner.create({ __registry__: registry, __container__: null }); container = registry.container({ owner: owner }); owner.__container__ = container; exposeRegistryMethodsWithoutDeprecations(container); } else { container = _ember['default'].Application.buildContainer(namespace); container.register('component-lookup:main', _ember['default'].ComponentLookup); } // Ember 1.10.0 did not properly add `view:toplevel` or `view:default` // to the registry in Ember.Application.buildRegistry :( // // Ember 2.0.0 removed Ember.View as public API, so only do this when // Ember.View is present if (_ember['default'].View) { register('view:toplevel', _ember['default'].View.extend()); } // Ember 2.0.0 removed Ember._MetamorphView from the Ember global, so only // do this when present if (_ember['default']._MetamorphView) { register('view:default', _ember['default']._MetamorphView); } var globalContext = typeof global === 'object' && global || self; if (requirejs.entries['ember-data/setup-container']) { // ember-data is a proper ember-cli addon since 2.3; if no 'import // 'ember-data'' is present somewhere in the tests, there is also no `DS` // available on the globalContext and hence ember-data wouldn't be setup // correctly for the tests; that's why we import and call setupContainer // here; also see https://github.com/emberjs/data/issues/4071 for context var setupContainer = (0, _require['default'])('ember-data/setup-container')['default']; setupContainer(registry || container); } else if (globalContext.DS) { var DS = globalContext.DS; if (DS._setupContainer) { DS._setupContainer(registry || container); } else { register('transform:boolean', DS.BooleanTransform); register('transform:date', DS.DateTransform); register('transform:number', DS.NumberTransform); register('transform:string', DS.StringTransform); register('serializer:-default', DS.JSONSerializer); register('serializer:-rest', DS.RESTSerializer); register('adapter:-rest', DS.RESTAdapter); } } return { registry: registry, container: container }; };});/* globals global, self, requirejs */define('ember-test-helpers/has-ember-version', ['exports', 'ember'], function (exports, _ember) { exports['default'] = hasEmberVersion; function hasEmberVersion(major, minor) { var numbers = _ember['default'].VERSION.split('-')[0].split('.'); var actualMajor = parseInt(numbers[0], 10); var actualMinor = parseInt(numbers[1], 10); return actualMajor > major || actualMajor === major && actualMinor >= minor; }});define("ember-test-helpers/test-context", ["exports"], function (exports) { exports.setContext = setContext; exports.getContext = getContext; exports.unsetContext = unsetContext; var __test_context__; function setContext(context) { __test_context__ = context; } function getContext() { return __test_context__; } function unsetContext() { __test_context__ = undefined; }});define('ember-test-helpers/test-module-for-acceptance', ['exports', 'ember-test-helpers/abstract-test-module', 'ember', 'ember-test-helpers/test-context'], function (exports, _emberTestHelpersAbstractTestModule, _ember, _emberTestHelpersTestContext) { var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _default = (function (_AbstractTestModule) { _inherits(_default, _AbstractTestModule); function _default() { _classCallCheck(this, _default); _get(Object.getPrototypeOf(_default.prototype), 'constructor', this).apply(this, arguments); } _createClass(_default, [{ key: 'setupContext', value: function setupContext() { _get(Object.getPrototypeOf(_default.prototype), 'setupContext', this).call(this, { application: this.createApplication() }); } }, { key: 'teardownContext', value: function teardownContext() { _ember['default'].run(function () { (0, _emberTestHelpersTestContext.getContext)().application.destroy(); }); _get(Object.getPrototypeOf(_default.prototype), 'teardownContext', this).call(this); } }, { key: 'createApplication', value: function createApplication() { var _callbacks = this.callbacks; var Application = _callbacks.Application; var config = _callbacks.config; var application = undefined; _ember['default'].run(function () { application = Application.create(config); application.setupForTesting(); application.injectTestHelpers(); }); return application; } }]); return _default; })(_emberTestHelpersAbstractTestModule['default']); exports['default'] = _default;});define('ember-test-helpers/test-module-for-component', ['exports', 'ember-test-helpers/test-module', 'ember', 'ember-test-helpers/has-ember-version', 'ember-test-helpers/-legacy-overrides'], function (exports, _emberTestHelpersTestModule, _ember, _emberTestHelpersHasEmberVersion, _emberTestHelpersLegacyOverrides) { var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; exports.setupComponentIntegrationTest = _setupComponentIntegrationTest; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var ACTION_KEY = undefined; if ((0, _emberTestHelpersHasEmberVersion['default'])(2, 0)) { ACTION_KEY = 'actions'; } else { ACTION_KEY = '_actions'; } var isPreGlimmer = !(0, _emberTestHelpersHasEmberVersion['default'])(1, 13); var getOwner = _ember['default'].getOwner; var _default = (function (_TestModule) { _inherits(_default, _TestModule); function _default(componentName, description, callbacks) { _classCallCheck(this, _default); // Allow `description` to be omitted if (!callbacks && typeof description === 'object') { callbacks = description; description = null; } else if (!callbacks) { callbacks = {}; } var integrationOption = callbacks.integration; var hasNeeds = Array.isArray(callbacks.needs); _get(Object.getPrototypeOf(_default.prototype), 'constructor', this).call(this, 'component:' + componentName, description, callbacks); this.componentName = componentName; if (hasNeeds || callbacks.unit || integrationOption === false) { this.isUnitTest = true; } else if (integrationOption) { this.isUnitTest = false; } else { _ember['default'].deprecate("the component:" + componentName + " test module is implicitly running in unit test mode, " + "which will change to integration test mode by default in an upcoming version of " + "ember-test-helpers. Add `unit: true` or a `needs:[]` list to explicitly opt in to unit " + "test mode.", false, { id: 'ember-test-helpers.test-module-for-component.test-type', until: '0.6.0' }); this.isUnitTest = true; } if (!this.isUnitTest && !this.isLegacy) { callbacks.integration = true; } if (this.isUnitTest || this.isLegacy) { this.setupSteps.push(this.setupComponentUnitTest); } else { this.callbacks.subject = function () { throw new Error("component integration tests do not support `subject()`. Instead, render the component as if it were HTML: `this.render('<my-component foo=true>');`. For more information, read: http://guides.emberjs.com/v2.2.0/testing/testing-components/"); }; this.setupSteps.push(this.setupComponentIntegrationTest); this.teardownSteps.unshift(this.teardownComponent); } if (_ember['default'].View && _ember['default'].View.views) { this.setupSteps.push(this._aliasViewRegistry); this.teardownSteps.unshift(this._resetViewRegistry); } } _createClass(_default, [{ key: 'initIntegration', value: function initIntegration(options) { this.isLegacy = options.integration === 'legacy'; this.isIntegration = options.integration !== 'legacy'; } }, { key: '_aliasViewRegistry', value: function _aliasViewRegistry() { this._originalGlobalViewRegistry = _ember['default'].View.views; var viewRegistry = this.container.lookup('-view-registry:main'); if (viewRegistry) { _ember['default'].View.views = viewRegistry; } } }, { key: '_resetViewRegistry', value: function _resetViewRegistry() { _ember['default'].View.views = this._originalGlobalViewRegistry; } }, { key: 'setupComponentUnitTest', value: function setupComponentUnitTest() { var _this = this; var resolver = this.resolver; var context = this.context; var layoutName = 'template:components/' + this.componentName; var layout = resolver.resolve(layoutName); var thingToRegisterWith = this.registry || this.container; if (layout) { thingToRegisterWith.register(layoutName, layout); thingToRegisterWith.injection(this.subjectName, 'layout', layoutName); } context.dispatcher = this.container.lookup('event_dispatcher:main') || _ember['default'].EventDispatcher.create(); context.dispatcher.setup({}, '#ember-testing'); context._element = null; this.callbacks.render = function () { var subject; _ember['default'].run(function () { subject = context.subject(); subject.appendTo('#ember-testing'); }); context._element = subject.element; _this.teardownSteps.unshift(function () { _ember['default'].run(function () { _ember['default'].tryInvoke(subject, 'destroy'); }); }); }; this.callbacks.append = function () { _ember['default'].deprecate('this.append() is deprecated. Please use this.render() or this.$() instead.', false, { id: 'ember-test-helpers.test-module-for-component.append', until: '0.6.0' }); return context.$(); }; context.$ = function () { this.render(); var subject = this.subject(); return subject.$.apply(subject, arguments); }; } }, { key: 'setupComponentIntegrationTest', value: function setupComponentIntegrationTest() { if (isPreGlimmer) { return _emberTestHelpersLegacyOverrides.preGlimmerSetupIntegrationForComponent.apply(this, arguments); } else { return _setupComponentIntegrationTest.apply(this, arguments); } } }, { key: 'setupContext', value: function setupContext() { _get(Object.getPrototypeOf(_default.prototype), 'setupContext', this).call(this); // only setup the injection if we are running against a version // of Ember that has `-view-registry:main` (Ember >= 1.12) if (this.container.factoryFor ? this.container.factoryFor('-view-registry:main') : this.container.lookupFactory('-view-registry:main')) { (this.registry || this.container).injection('component', '_viewRegistry', '-view-registry:main'); } if (!this.isUnitTest && !this.isLegacy) { this.context.factory = function () {}; } } }, { key: 'teardownComponent', value: function teardownComponent() { var component = this.component; if (component) { _ember['default'].run(component, 'destroy'); this.component = null; } } }]); return _default; })(_emberTestHelpersTestModule['default']); exports['default'] = _default; function _setupComponentIntegrationTest() { var module = this; var context = this.context; this.actionHooks = context[ACTION_KEY] = {}; context.dispatcher = this.container.lookup('event_dispatcher:main') || _ember['default'].EventDispatcher.create(); context.dispatcher.setup({}, '#ember-testing'); var hasRendered = false; var OutletView = module.container.factoryFor ? module.container.factoryFor('view:-outlet') : module.container.lookupFactory('view:-outlet'); var OutletTemplate = module.container.lookup('template:-outlet'); var toplevelView = module.component = OutletView.create(); var hasOutletTemplate = !!OutletTemplate; var outletState = { render: { owner: getOwner ? getOwner(module.container) : undefined, into: undefined, outlet: 'main', name: 'application', controller: module.context, ViewClass: undefined, template: OutletTemplate }, outlets: {} }; var element = document.getElementById('ember-testing'); var templateId = 0; if (hasOutletTemplate) { _ember['default'].run(function () { toplevelView.setOutletState(outletState); }); } context.render = function (template) { if (!template) { throw new Error("in a component integration test you must pass a template to `render()`"); } if (_ember['default'].isArray(template)) { template = template.join(''); } if (typeof template === 'string') { template = _ember['default'].Handlebars.compile(template); } var templateFullName = 'template:-undertest-' + ++templateId; this.registry.register(templateFullName, template); var stateToRender = { owner: getOwner ? getOwner(module.container) : undefined, into: undefined, outlet: 'main', name: 'index', controller: module.context, ViewClass: undefined, template: module.container.lookup(templateFullName), outlets: {} }; if (hasOutletTemplate) { stateToRender.name = 'index'; outletState.outlets.main = { render: stateToRender, outlets: {} }; } else { stateToRender.name = 'application'; outletState = { render: stateToRender, outlets: {} }; } _ember['default'].run(function () { toplevelView.setOutletState(outletState); }); if (!hasRendered) { _ember['default'].run(module.component, 'appendTo', '#ember-testing'); hasRendered = true; } // ensure the element is based on the wrapping toplevel view // Ember still wraps the main application template with a // normal tagged view context._element = element = document.querySelector('#ember-testing > .ember-view'); }; context.$ = function (selector) { // emulates Ember internal behavor of `this.$` in a component // https://github.com/emberjs/ember.js/blob/v2.5.1/packages/ember-views/lib/views/states/has_element.js#L18 return selector ? _ember['default'].$(selector, element) : _ember['default'].$(element); }; context.set = function (key, value) { var ret = _ember['default'].run(function () { return _ember['default'].set(context, key, value); }); if ((0, _emberTestHelpersHasEmberVersion['default'])(2, 0)) { return ret; } }; context.setProperties = function (hash) { var ret = _ember['default'].run(function () { return _ember['default'].setProperties(context, hash); }); if ((0, _emberTestHelpersHasEmberVersion['default'])(2, 0)) { return ret; } }; context.get = function (key) { return _ember['default'].get(context, key); }; context.getProperties = function () { var args = Array.prototype.slice.call(arguments); return _ember['default'].getProperties(context, args); }; context.on = function (actionName, handler) { module.actionHooks[actionName] = handler; }; context.send = function (actionName) { var hook = module.actionHooks[actionName]; if (!hook) { throw new Error("integration testing template received unexpected action " + actionName); } hook.apply(module.context, Array.prototype.slice.call(arguments, 1)); }; context.clearRender = function () { _ember['default'].run(function () { toplevelView.setOutletState({ render: { owner: module.container, into: undefined, outlet: 'main', name: 'application', controller: module.context, ViewClass: undefined, template: undefined }, outlets: {} }); }); }; }});define('ember-test-helpers/test-module-for-integration', ['exports', 'ember', 'ember-test-helpers/abstract-test-module', 'ember-test-helpers/test-resolver', 'ember-test-helpers/build-registry', 'ember-test-helpers/has-ember-version', 'ember-test-helpers/-legacy-overrides', 'ember-test-helpers/test-module-for-component'], function (exports, _ember, _emberTestHelpersAbstractTestModule, _emberTestHelpersTestResolver, _emberTestHelpersBuildRegistry, _emberTestHelpersHasEmberVersion, _emberTestHelpersLegacyOverrides, _emberTestHelpersTestModuleForComponent) { var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var isPreGlimmer = !(0, _emberTestHelpersHasEmberVersion['default'])(1, 13); var _default = (function (_AbstractTestModule) { _inherits(_default, _AbstractTestModule); function _default() { _classCallCheck(this, _default); _get(Object.getPrototypeOf(_default.prototype), 'constructor', this).apply(this, arguments); this.resolver = this.callbacks.resolver || (0, _emberTestHelpersTestResolver.getResolver)(); } _createClass(_default, [{ key: 'initSetupSteps', value: function initSetupSteps() { this.setupSteps = []; this.contextualizedSetupSteps = []; if (this.callbacks.beforeSetup) { this.setupSteps.push(this.callbacks.beforeSetup); delete this.callbacks.beforeSetup; } this.setupSteps.push(this.setupContainer); this.setupSteps.push(this.setupContext); this.setupSteps.push(this.setupTestElements); this.setupSteps.push(this.setupAJAXListeners); this.setupSteps.push(this.setupComponentIntegrationTest); if (_ember['default'].View && _ember['default'].View.views) { this.setupSteps.push(this._aliasViewRegistry); } if (this.callbacks.setup) { this.contextualizedSetupSteps.push(this.callbacks.setup); delete this.callbacks.setup; } } }, { key: 'initTeardownSteps', value: function initTeardownSteps() { this.teardownSteps = []; this.contextualizedTeardownSteps = []; if (this.callbacks.teardown) { this.contextualizedTeardownSteps.push(this.callbacks.teardown); delete this.callbacks.teardown; } this.teardownSteps.push(this.teardownContainer); this.teardownSteps.push(this.teardownContext); this.teardownSteps.push(this.teardownAJAXListeners); this.teardownSteps.push(this.teardownComponent); if (_ember['default'].View && _ember['default'].View.views) { this.teardownSteps.push(this._resetViewRegistry); } this.teardownSteps.push(this.teardownTestElements); if (this.callbacks.afterTeardown) { this.teardownSteps.push(this.callbacks.afterTeardown); delete this.callbacks.afterTeardown; } } }, { key: 'setupContainer', value: function setupContainer() { var resolver = this.resolver; var items = (0, _emberTestHelpersBuildRegistry['default'])(resolver); this.container = items.container; this.registry = items.registry; if ((0, _emberTestHelpersHasEmberVersion['default'])(1, 13)) { var thingToRegisterWith = this.registry || this.container; var router = resolver.resolve('router:main'); router = router || _ember['default'].Router.extend(); thingToRegisterWith.register('router:main', router); } } }, { key: 'setupContext', value: function setupContext() { var subjectName = this.subjectName; var container = this.container; var factory = function factory() { return container.factoryFor ? container.factoryFor(subjectName) : container.lookupFactory(subjectName); }; _get(Object.getPrototypeOf(_default.prototype), 'setupContext', this).call(this, { container: this.container, registry: this.registry, factory: factory, register: function register() { var target = this.registry || this.container; return target.register.apply(target, arguments); } }); var context = this.context; if (_ember['default'].setOwner) { _ember['default'].setOwner(context, this.container.owner); } if (_ember['default'].inject) { var keys = (Object.keys || _ember['default'].keys)(_ember['default'].inject); keys.forEach(function (typeName) { context.inject[typeName] = function (name, opts) { var alias = opts && opts.as || name; _ember['default'].run(function () { _ember['default'].set(context, alias, context.container.lookup(typeName + ':' + name)); }); }; }); } // only setup the injection if we are running against a version // of Ember that has `-view-registry:main` (Ember >= 1.12) if (this.container.factoryFor ? this.container.factoryFor('-view-registry:main') : this.container.lookupFactory('-view-registry:main')) { (this.registry || this.container).injection('component', '_viewRegistry', '-view-registry:main'); } } }, { key: 'setupComponentIntegrationTest', value: function setupComponentIntegrationTest() { if (isPreGlimmer) { return _emberTestHelpersLegacyOverrides.preGlimmerSetupIntegrationForComponent.apply(this, arguments); } else { return _emberTestHelpersTestModuleForComponent.setupComponentIntegrationTest.apply(this, arguments); } } }, { key: 'teardownComponent', value: function teardownComponent() { var component = this.component; if (component) { _ember['default'].run(function () { component.destroy(); }); } } }, { key: 'teardownContainer', value: function teardownContainer() { var container = this.container; _ember['default'].run(function () { container.destroy(); }); } // allow arbitrary named factories, like rspec let }, { key: 'contextualizeCallbacks', value: function contextualizeCallbacks() { var callbacks = this.callbacks; var context = this.context; this.cache = this.cache || {}; this.cachedCalls = this.cachedCalls || {}; var keys = (Object.keys || _ember['default'].keys)(callbacks); var keysLength = keys.length; if (keysLength) { for (var i = 0; i < keysLength; i++) { this._contextualizeCallback(context, keys[i], context); } } } }, { key: '_contextualizeCallback', value: function _contextualizeCallback(context, key, callbackContext) { var _this = this; var callbacks = this.callbacks; var factory = context.factory; context[key] = function (options) { if (_this.cachedCalls[key]) { return _this.cache[key]; } var result = callbacks[key].call(callbackContext, options, factory()); _this.cache[key] = result; _this.cachedCalls[key] = true; return result; }; } }, { key: '_aliasViewRegistry', value: function _aliasViewRegistry() { this._originalGlobalViewRegistry = _ember['default'].View.views; var viewRegistry = this.container.lookup('-view-registry:main'); if (viewRegistry) { _ember['default'].View.views = viewRegistry; } } }, { key: '_resetViewRegistry', value: function _resetViewRegistry() { _ember['default'].View.views = this._originalGlobalViewRegistry; } }]); return _default; })(_emberTestHelpersAbstractTestModule['default']); exports['default'] = _default;});define('ember-test-helpers/test-module-for-model', ['exports', 'require', 'ember-test-helpers/test-module', 'ember'], function (exports, _require, _emberTestHelpersTestModule, _ember) { var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _default = (function (_TestModule) { _inherits(_default, _TestModule); function _default(modelName, description, callbacks) { _classCallCheck(this, _default); _get(Object.getPrototypeOf(_default.prototype), 'constructor', this).call(this, 'model:' + modelName, description, callbacks); this.modelName = modelName; this.setupSteps.push(this.setupModel); } _createClass(_default, [{ key: 'setupModel', value: function setupModel() { var container = this.container; var defaultSubject = this.defaultSubject; var callbacks = this.callbacks; var modelName = this.modelName; var adapterFactory = container.factoryFor ? container.factoryFor('adapter:application') : container.lookupFactory('adapter:application'); if (!adapterFactory) { if (requirejs.entries['ember-data/adapters/json-api']) { adapterFactory = (0, _require['default'])('ember-data/adapters/json-api')['default']; } // when ember-data/adapters/json-api is provided via ember-cli shims // using Ember Data 1.x the actual JSONAPIAdapter isn't found, but the // above require statement returns a bizzaro object with only a `default` // property (circular reference actually) if (!adapterFactory || !adapterFactory.create) { adapterFactory = DS.JSONAPIAdapter || DS.FixtureAdapter; } var thingToRegisterWith = this.registry || this.container; thingToRegisterWith.register('adapter:application', adapterFactory); } callbacks.store = function () { var container = this.container; return container.lookup('service:store') || container.lookup('store:main'); }; if (callbacks.subject === defaultSubject) { callbacks.subject = function (options) { var container = this.container; return _ember['default'].run(function () { var store = container.lookup('service:store') || container.lookup('store:main'); return store.createRecord(modelName, options); }); }; } } }]); return _default; })(_emberTestHelpersTestModule['default']); exports['default'] = _default;});/* global DS, requirejs */ // added here to prevent an import from erroring when ED is not presentdefine('ember-test-helpers/test-module', ['exports', 'ember', 'ember-test-helpers/abstract-test-module', 'ember-test-helpers/test-resolver', 'ember-test-helpers/build-registry', 'ember-test-helpers/has-ember-version'], function (exports, _ember, _emberTestHelpersAbstractTestModule, _emberTestHelpersTestResolver, _emberTestHelpersBuildRegistry, _emberTestHelpersHasEmberVersion) { var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _default = (function (_AbstractTestModule) { _inherits(_default, _AbstractTestModule); function _default(subjectName, description, callbacks) { _classCallCheck(this, _default); // Allow `description` to be omitted, in which case it should // default to `subjectName` if (!callbacks && typeof description === 'object') { callbacks = description; description = subjectName; } _get(Object.getPrototypeOf(_default.prototype), 'constructor', this).call(this, description || subjectName, callbacks); this.subjectName = subjectName; this.description = description || subjectName; this.resolver = this.callbacks.resolver || (0, _emberTestHelpersTestResolver.getResolver)(); if (this.callbacks.integration && this.callbacks.needs) { throw new Error("cannot declare 'integration: true' and 'needs' in the same module"); } if (this.callbacks.integration) { this.initIntegration(callbacks); delete callbacks.integration; } this.initSubject(); this.initNeeds(); } _createClass(_default, [{ key: 'initIntegration', value: function initIntegration(options) { if (options.integration === 'legacy') { throw new Error('`integration: \'legacy\'` is only valid for component tests.'); } this.isIntegration = true; } }, { key: 'initSubject', value: function initSubject() { this.callbacks.subject = this.callbacks.subject || this.defaultSubject; } }, { key: 'initNeeds', value: function initNeeds() { this.needs = [this.subjectName]; if (this.callbacks.needs) { this.needs = this.needs.concat(this.callbacks.needs); delete this.callbacks.needs; } } }, { key: 'initSetupSteps', value: function initSetupSteps() { this.setupSteps = []; this.contextualizedSetupSteps = []; if (this.callbacks.beforeSetup) { this.setupSteps.push(this.callbacks.beforeSetup); delete this.callbacks.beforeSetup; } this.setupSteps.push(this.setupContainer); this.setupSteps.push(this.setupContext); this.setupSteps.push(this.setupTestElements); this.setupSteps.push(this.setupAJAXListeners); if (this.callbacks.setup) { this.contextualizedSetupSteps.push(this.callbacks.setup); delete this.callbacks.setup; } } }, { key: 'initTeardownSteps', value: function initTeardownSteps() { this.teardownSteps = []; this.contextualizedTeardownSteps = []; if (this.callbacks.teardown) { this.contextualizedTeardownSteps.push(this.callbacks.teardown); delete this.callbacks.teardown; } this.teardownSteps.push(this.teardownSubject); this.teardownSteps.push(this.teardownContainer); this.teardownSteps.push(this.teardownContext); this.teardownSteps.push(this.teardownTestElements); this.teardownSteps.push(this.teardownAJAXListeners); if (this.callbacks.afterTeardown) { this.teardownSteps.push(this.callbacks.afterTeardown); delete this.callbacks.afterTeardown; } } }, { key: 'setupContainer', value: function setupContainer() { if (this.isIntegration || this.isLegacy) { this._setupIntegratedContainer(); } else { this._setupIsolatedContainer(); } } }, { key: 'setupContext', value: function setupContext() { var subjectName = this.subjectName; var container = this.container; var factory = function factory() { return container.factoryFor ? container.factoryFor(subjectName) : container.lookupFactory(subjectName); }; _get(Object.getPrototypeOf(_default.prototype), 'setupContext', this).call(this, { container: this.container, registry: this.registry, factory: factory, register: function register() { var target = this.registry || this.container; return target.register.apply(target, arguments); } }); if (_ember['default'].setOwner) { _ember['default'].setOwner(this.context, this.container.owner); } this.setupInject(); } }, { key: 'setupInject', value: function setupInject() { var module = this; var context = this.context; if (_ember['default'].inject) { var keys = (Object.keys || _ember['default'].keys)(_ember['default'].inject); keys.forEach(function (typeName) { context.inject[typeName] = function (name, opts) { var alias = opts && opts.as || name; _ember['default'].run(function () { _ember['default'].set(context, alias, module.container.lookup(typeName + ':' + name)); }); }; }); } } }, { key: 'teardownSubject', value: function teardownSubject() { var subject = this.cache.subject; if (subject) { _ember['default'].run(function () { _ember['default'].tryInvoke(subject, 'destroy'); }); } } }, { key: 'teardownContainer', value: function teardownContainer() { var container = this.container; _ember['default'].run(function () { container.destroy(); }); } }, { key: 'defaultSubject', value: function defaultSubject(options, factory) { return factory.create(options); } // allow arbitrary named factories, like rspec let }, { key: 'contextualizeCallbacks', value: function contextualizeCallbacks() { var callbacks = this.callbacks; var context = this.context; this.cache = this.cache || {}; this.cachedCalls = this.cachedCalls || {}; var keys = (Object.keys || _ember['default'].keys)(callbacks); var keysLength = keys.length; if (keysLength) { var deprecatedContext = this._buildDeprecatedContext(this, context); for (var i = 0; i < keysLength; i++) { this._contextualizeCallback(context, keys[i], deprecatedContext); } } } }, { key: '_contextualizeCallback', value: function _contextualizeCallback(context, key, callbackContext) { var _this = this; var callbacks = this.callbacks; var factory = context.factory; context[key] = function (options) { if (_this.cachedCalls[key]) { return _this.cache[key]; } var result = callbacks[key].call(callbackContext, options, factory()); _this.cache[key] = result; _this.cachedCalls[key] = true; return result; }; } /* Builds a version of the passed in context that contains deprecation warnings for accessing properties that exist on the module. */ }, { key: '_buildDeprecatedContext', value: function _buildDeprecatedContext(module, context) { var deprecatedContext = Object.create(context); var keysForDeprecation = Object.keys(module); for (var i = 0, l = keysForDeprecation.length; i < l; i++) { this._proxyDeprecation(module, deprecatedContext, keysForDeprecation[i]); } return deprecatedContext; } /* Defines a key on an object to act as a proxy for deprecating the original. */ }, { key: '_proxyDeprecation', value: function _proxyDeprecation(obj, proxy, key) { if (typeof proxy[key] === 'undefined') { Object.defineProperty(proxy, key, { get: function get() { _ember['default'].deprecate('Accessing the test module property "' + key + '" from a callback is deprecated.', false, { id: 'ember-test-helpers.test-module.callback-context', until: '0.6.0' }); return obj[key]; } }); } } }, { key: '_setupContainer', value: function _setupContainer(isolated) { var resolver = this.resolver; var items = (0, _emberTestHelpersBuildRegistry['default'])(!isolated ? resolver : Object.create(resolver, { resolve: { value: function value() {} } })); this.container = items.container; this.registry = items.registry; if ((0, _emberTestHelpersHasEmberVersion['default'])(1, 13)) { var thingToRegisterWith = this.registry || this.container; var router = resolver.resolve('router:main'); router = router || _ember['default'].Router.extend(); thingToRegisterWith.register('router:main', router); } } }, { key: '_setupIsolatedContainer', value: function _setupIsolatedContainer() { var resolver = this.resolver; this._setupContainer(true); var thingToRegisterWith = this.registry || this.container; for (var i = this.needs.length; i > 0; i--) { var fullName = this.needs[i - 1]; var normalizedFullName = resolver.normalize(fullName); thingToRegisterWith.register(fullName, resolver.resolve(normalizedFullName)); } if (!this.registry) { this.container.resolver = function () {}; } } }, { key: '_setupIntegratedContainer', value: function _setupIntegratedContainer() { this._setupContainer(); } }]); return _default; })(_emberTestHelpersAbstractTestModule['default']); exports['default'] = _default;});define('ember-test-helpers/test-resolver', ['exports'], function (exports) { exports.setResolver = setResolver; exports.getResolver = getResolver; var __resolver__; function setResolver(resolver) { __resolver__ = resolver; } function getResolver() { if (__resolver__ == null) { throw new Error('you must set a resolver with `testResolver.set(resolver)`'); } return __resolver__; }});define('ember-test-helpers/wait', ['exports', 'ember'], function (exports, _ember) { var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); exports._teardownAJAXHooks = _teardownAJAXHooks; exports._setupAJAXHooks = _setupAJAXHooks; exports['default'] = wait; var jQuery = _ember['default'].$; var requests; function incrementAjaxPendingRequests(_, xhr) { requests.push(xhr); } function decrementAjaxPendingRequests(_, xhr) { for (var i = 0; i < requests.length; i++) { if (xhr === requests[i]) { requests.splice(i, 1); } } } function _teardownAJAXHooks() { if (!jQuery) { return; } jQuery(document).off('ajaxSend', incrementAjaxPendingRequests); jQuery(document).off('ajaxComplete', decrementAjaxPendingRequests); } function _setupAJAXHooks() { requests = []; if (!jQuery) { return; } jQuery(document).on('ajaxSend', incrementAjaxPendingRequests); jQuery(document).on('ajaxComplete', decrementAjaxPendingRequests); } var _internalCheckWaiters; if (_ember['default'].__loader.registry['ember-testing/test/waiters']) { _internalCheckWaiters = _ember['default'].__loader.require('ember-testing/test/waiters').checkWaiters; } function checkWaiters() { if (_internalCheckWaiters) { return _internalCheckWaiters(); } else if (_ember['default'].Test.waiters) { if (_ember['default'].Test.waiters.any(function (_ref) { var _ref2 = _slicedToArray(_ref, 2); var context = _ref2[0]; var callback = _ref2[1]; return !callback.call(context); })) { return true; } } return false; } function wait(_options) { var options = _options || {}; var waitForTimers = options.hasOwnProperty('waitForTimers') ? options.waitForTimers : true; var waitForAJAX = options.hasOwnProperty('waitForAJAX') ? options.waitForAJAX : true; var waitForWaiters = options.hasOwnProperty('waitForWaiters') ? options.waitForWaiters : true; return new _ember['default'].RSVP.Promise(function (resolve) { var watcher = self.setInterval(function () { if (waitForTimers && (_ember['default'].run.hasScheduledTimers() || _ember['default'].run.currentRunLoop)) { return; } if (waitForAJAX && requests && requests.length > 0) { return; } if (waitForWaiters && checkWaiters()) { return; } // Stop polling self.clearInterval(watcher); // Synchronously resolve the promise _ember['default'].run(null, resolve); }, 10); }); }});/* globals self */define("qunit", ["exports"], function (exports) { /* globals QUnit */ var _module = QUnit.module; exports.module = _module; var test = QUnit.test; exports.test = test; var skip = QUnit.skip; exports.skip = skip; var only = QUnit.only; exports.only = only; var todo = QUnit.todo; exports.todo = todo; exports["default"] = QUnit;});runningTests = true;if (window.Testem) { window.Testem.hookIntoTestFramework();}//# sourceMappingURL=test-support.map