UNPKG

@testim/testim-cli

Version:

Command line interface for running Testing on you CI

275 lines (237 loc) 9.22 kB
/** `Object#toString` result shortcuts */ var argsClass = '[object Arguments]', arrayClass = '[object Array]', boolClass = '[object Boolean]', dateClass = '[object Date]', errorClass = '[object Error]', funcClass = '[object Function]', numberClass = '[object Number]', objectClass = '[object Object]', regexpClass = '[object RegExp]', stringClass = '[object String]'; var toString = Object.prototype.toString, hasOwnProperty = Object.prototype.hasOwnProperty, supportsArgsClass = toString.call(arguments) == argsClass, // For less <IE9 && FF<4 supportNodeClass, errorProto = Error.prototype, objectProto = Object.prototype, stringProto = String.prototype, propertyIsEnumerable = objectProto.propertyIsEnumerable; try { supportNodeClass = !(toString.call(document) == objectClass && !({ 'toString': 0 } + '')); } catch (e) { supportNodeClass = true; } var nonEnumProps = {}; nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': true, 'toString': true, 'valueOf': true }; nonEnumProps[errorClass] = nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': true, 'toString': true }; nonEnumProps[objectClass] = { 'constructor': true }; var support = {}; (function () { var ctor = function() { this.x = 1; }, props = []; ctor.prototype = { 'valueOf': 1, 'y': 1 }; for (var key in new ctor) { props.push(key); } for (key in arguments) { } // Detect if `name` or `message` properties of `Error.prototype` are enumerable by default. support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || propertyIsEnumerable.call(errorProto, 'name'); // Detect if `prototype` properties are enumerable by default. support.enumPrototypes = propertyIsEnumerable.call(ctor, 'prototype'); // Detect if `arguments` object indexes are non-enumerable support.nonEnumArgs = key != 0; // Detect if properties shadowing those on `Object.prototype` are non-enumerable. support.nonEnumShadows = !/valueOf/.test(props); }(1)); var isObject = Rx.internals.isObject = function(value) { var type = typeof value; return value && (type == 'function' || type == 'object') || false; }; function keysIn(object) { var result = []; if (!isObject(object)) { return result; } if (support.nonEnumArgs && object.length && isArguments(object)) { object = slice.call(object); } var skipProto = support.enumPrototypes && typeof object == 'function', skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error); for (var key in object) { if (!(skipProto && key == 'prototype') && !(skipErrorProps && (key == 'message' || key == 'name'))) { result.push(key); } } if (support.nonEnumShadows && object !== objectProto) { var ctor = object.constructor, index = -1, length = dontEnumsLength; if (object === (ctor && ctor.prototype)) { var className = object === stringProto ? stringClass : object === errorProto ? errorClass : toString.call(object), nonEnum = nonEnumProps[className]; } while (++index < length) { key = dontEnums[index]; if (!(nonEnum && nonEnum[key]) && hasOwnProperty.call(object, key)) { result.push(key); } } } return result; } function internalFor(object, callback, keysFunc) { var index = -1, props = keysFunc(object), length = props.length; while (++index < length) { var key = props[index]; if (callback(object[key], key, object) === false) { break; } } return object; } function internalForIn(object, callback) { return internalFor(object, callback, keysIn); } function isNode(value) { // IE < 9 presents DOM nodes as `Object` objects except they have `toString` // methods that are `typeof` "string" and still can coerce nodes to strings return typeof value.toString != 'function' && typeof (value + '') == 'string'; } var isArguments = function(value) { return (value && typeof value == 'object') ? toString.call(value) == argsClass : false; } // fallback for browsers that can't detect `arguments` objects by [[Class]] if (!supportsArgsClass) { isArguments = function(value) { return (value && typeof value == 'object') ? hasOwnProperty.call(value, 'callee') : false; }; } var isEqual = Rx.internals.isEqual = function (x, y) { return deepEquals(x, y, [], []); }; /** @private * Used for deep comparison **/ function deepEquals(a, b, stackA, stackB) { // exit early for identical values if (a === b) { // treat `+0` vs. `-0` as not equal return a !== 0 || (1 / a == 1 / b); } var type = typeof a, otherType = typeof b; // exit early for unlike primitive values if (a === a && (a == null || b == null || (type != 'function' && type != 'object' && otherType != 'function' && otherType != 'object'))) { return false; } // compare [[Class]] names var className = toString.call(a), otherClass = toString.call(b); if (className == argsClass) { className = objectClass; } if (otherClass == argsClass) { otherClass = objectClass; } if (className != otherClass) { return false; } switch (className) { case boolClass: case dateClass: // coerce dates and booleans to numbers, dates to milliseconds and booleans // to `1` or `0` treating invalid dates coerced to `NaN` as not equal return +a == +b; case numberClass: // treat `NaN` vs. `NaN` as equal return (a != +a) ? b != +b : // but treat `-0` vs. `+0` as not equal (a == 0 ? (1 / a == 1 / b) : a == +b); case regexpClass: case stringClass: // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) // treat string primitives and their corresponding object instances as equal return a == String(b); } var isArr = className == arrayClass; if (!isArr) { // exit for functions and DOM nodes if (className != objectClass || (!support.nodeClass && (isNode(a) || isNode(b)))) { return false; } // in older versions of Opera, `arguments` objects have `Array` constructors var ctorA = !support.argsObject && isArguments(a) ? Object : a.constructor, ctorB = !support.argsObject && isArguments(b) ? Object : b.constructor; // non `Object` object instances with different constructors are not equal if (ctorA != ctorB && !(hasOwnProperty.call(a, 'constructor') && hasOwnProperty.call(b, 'constructor')) && !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) && ('constructor' in a && 'constructor' in b) ) { return false; } } // assume cyclic structures are equal // the algorithm for detecting cyclic structures is adapted from ES 5.1 // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) var initedStack = !stackA; stackA || (stackA = []); stackB || (stackB = []); var length = stackA.length; while (length--) { if (stackA[length] == a) { return stackB[length] == b; } } var size = 0; var result = true; // add `a` and `b` to the stack of traversed objects stackA.push(a); stackB.push(b); // recursively compare objects and arrays (susceptible to call stack limits) if (isArr) { // compare lengths to determine if a deep comparison is necessary length = a.length; size = b.length; result = size == length; if (result) { // deep compare the contents, ignoring non-numeric properties while (size--) { var index = length, value = b[size]; if (!(result = deepEquals(a[size], value, stackA, stackB))) { break; } } } } else { // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` // which, in this case, is more costly internalForIn(b, function(value, key, b) { if (hasOwnProperty.call(b, key)) { // count the number of properties. size++; // deep compare each property value. return (result = hasOwnProperty.call(a, key) && deepEquals(a[key], value, stackA, stackB)); } }); if (result) { // ensure both objects have the same number of properties internalForIn(a, function(value, key, a) { if (hasOwnProperty.call(a, key)) { // `size` will be `-1` if `a` has more properties than `b` return (result = --size > -1); } }); } } stackA.pop(); stackB.pop(); return result; }