vendor/assets/javascripts/chai.js in konacha-3.5.1 vs vendor/assets/javascripts/chai.js in konacha-3.6.0

- old
+ new

@@ -1,673 +1,10 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.chai = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ +module.exports = require('./lib/chai'); -;(function(){ - -/** - * Require the module at `name`. - * - * @param {String} name - * @return {Object} exports - * @api public - */ - -function require(name) { - var module = require.modules[name]; - if (!module) throw new Error('failed to require "' + name + '"'); - - if (!('exports' in module) && typeof module.definition === 'function') { - module.client = module.component = true; - module.definition.call(this, module.exports = {}, module); - delete module.definition; - } - - return module.exports; -} - -/** - * Meta info, accessible in the global scope unless you use AMD option. - */ - -require.loader = 'component'; - -/** - * Internal helper object, contains a sorting function for semantiv versioning - */ -require.helper = {}; -require.helper.semVerSort = function(a, b) { - var aArray = a.version.split('.'); - var bArray = b.version.split('.'); - for (var i=0; i<aArray.length; ++i) { - var aInt = parseInt(aArray[i], 10); - var bInt = parseInt(bArray[i], 10); - if (aInt === bInt) { - var aLex = aArray[i].substr((""+aInt).length); - var bLex = bArray[i].substr((""+bInt).length); - if (aLex === '' && bLex !== '') return 1; - if (aLex !== '' && bLex === '') return -1; - if (aLex !== '' && bLex !== '') return aLex > bLex ? 1 : -1; - continue; - } else if (aInt > bInt) { - return 1; - } else { - return -1; - } - } - return 0; -} - -/** - * Find and require a module which name starts with the provided name. - * If multiple modules exists, the highest semver is used. - * This function can only be used for remote dependencies. - - * @param {String} name - module name: `user~repo` - * @param {Boolean} returnPath - returns the canonical require path if true, - * otherwise it returns the epxorted module - */ -require.latest = function (name, returnPath) { - function showError(name) { - throw new Error('failed to find latest module of "' + name + '"'); - } - // only remotes with semvers, ignore local files conataining a '/' - var versionRegexp = /(.*)~(.*)@v?(\d+\.\d+\.\d+[^\/]*)$/; - var remoteRegexp = /(.*)~(.*)/; - if (!remoteRegexp.test(name)) showError(name); - var moduleNames = Object.keys(require.modules); - var semVerCandidates = []; - var otherCandidates = []; // for instance: name of the git branch - for (var i=0; i<moduleNames.length; i++) { - var moduleName = moduleNames[i]; - if (new RegExp(name + '@').test(moduleName)) { - var version = moduleName.substr(name.length+1); - var semVerMatch = versionRegexp.exec(moduleName); - if (semVerMatch != null) { - semVerCandidates.push({version: version, name: moduleName}); - } else { - otherCandidates.push({version: version, name: moduleName}); - } - } - } - if (semVerCandidates.concat(otherCandidates).length === 0) { - showError(name); - } - if (semVerCandidates.length > 0) { - var module = semVerCandidates.sort(require.helper.semVerSort).pop().name; - if (returnPath === true) { - return module; - } - return require(module); - } - // if the build contains more than one branch of the same module - // you should not use this funciton - var module = otherCandidates.sort(function(a, b) {return a.name > b.name})[0].name; - if (returnPath === true) { - return module; - } - return require(module); -} - -/** - * Registered modules. - */ - -require.modules = {}; - -/** - * Register module at `name` with callback `definition`. - * - * @param {String} name - * @param {Function} definition - * @api private - */ - -require.register = function (name, definition) { - require.modules[name] = { - definition: definition - }; -}; - -/** - * Define a module's exports immediately with `exports`. - * - * @param {String} name - * @param {Generic} exports - * @api private - */ - -require.define = function (name, exports) { - require.modules[name] = { - exports: exports - }; -}; -require.register("chaijs~assertion-error@1.0.0", function (exports, module) { +},{"./lib/chai":2}],2:[function(require,module,exports){ /*! - * assertion-error - * Copyright(c) 2013 Jake Luer <jake@qualiancy.com> - * MIT Licensed - */ - -/*! - * Return a function that will copy properties from - * one object to another excluding any originally - * listed. Returned function will create a new `{}`. - * - * @param {String} excluded properties ... - * @return {Function} - */ - -function exclude () { - var excludes = [].slice.call(arguments); - - function excludeProps (res, obj) { - Object.keys(obj).forEach(function (key) { - if (!~excludes.indexOf(key)) res[key] = obj[key]; - }); - } - - return function extendExclude () { - var args = [].slice.call(arguments) - , i = 0 - , res = {}; - - for (; i < args.length; i++) { - excludeProps(res, args[i]); - } - - return res; - }; -}; - -/*! - * Primary Exports - */ - -module.exports = AssertionError; - -/** - * ### AssertionError - * - * An extension of the JavaScript `Error` constructor for - * assertion and validation scenarios. - * - * @param {String} message - * @param {Object} properties to include (optional) - * @param {callee} start stack function (optional) - */ - -function AssertionError (message, _props, ssf) { - var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON') - , props = extend(_props || {}); - - // default values - this.message = message || 'Unspecified AssertionError'; - this.showDiff = false; - - // copy from properties - for (var key in props) { - this[key] = props[key]; - } - - // capture stack trace - ssf = ssf || arguments.callee; - if (ssf && Error.captureStackTrace) { - Error.captureStackTrace(this, ssf); - } -} - -/*! - * Inherit from Error.prototype - */ - -AssertionError.prototype = Object.create(Error.prototype); - -/*! - * Statically set name - */ - -AssertionError.prototype.name = 'AssertionError'; - -/*! - * Ensure correct constructor - */ - -AssertionError.prototype.constructor = AssertionError; - -/** - * Allow errors to be converted to JSON for static transfer. - * - * @param {Boolean} include stack (default: `true`) - * @return {Object} object that can be `JSON.stringify` - */ - -AssertionError.prototype.toJSON = function (stack) { - var extend = exclude('constructor', 'toJSON', 'stack') - , props = extend({ name: this.name }, this); - - // include stack if exists and not turned off - if (false !== stack && this.stack) { - props.stack = this.stack; - } - - return props; -}; - -}); - -require.register("chaijs~type-detect@0.1.1", function (exports, module) { -/*! - * type-detect - * Copyright(c) 2013 jake luer <jake@alogicalparadox.com> - * MIT Licensed - */ - -/*! - * Primary Exports - */ - -var exports = module.exports = getType; - -/*! - * Detectable javascript natives - */ - -var natives = { - '[object Array]': 'array' - , '[object RegExp]': 'regexp' - , '[object Function]': 'function' - , '[object Arguments]': 'arguments' - , '[object Date]': 'date' -}; - -/** - * ### typeOf (obj) - * - * Use several different techniques to determine - * the type of object being tested. - * - * - * @param {Mixed} object - * @return {String} object type - * @api public - */ - -function getType (obj) { - var str = Object.prototype.toString.call(obj); - if (natives[str]) return natives[str]; - if (obj === null) return 'null'; - if (obj === undefined) return 'undefined'; - if (obj === Object(obj)) return 'object'; - return typeof obj; -} - -exports.Library = Library; - -/** - * ### Library - * - * Create a repository for custom type detection. - * - * ```js - * var lib = new type.Library; - * ``` - * - */ - -function Library () { - this.tests = {}; -} - -/** - * #### .of (obj) - * - * Expose replacement `typeof` detection to the library. - * - * ```js - * if ('string' === lib.of('hello world')) { - * // ... - * } - * ``` - * - * @param {Mixed} object to test - * @return {String} type - */ - -Library.prototype.of = getType; - -/** - * #### .define (type, test) - * - * Add a test to for the `.test()` assertion. - * - * Can be defined as a regular expression: - * - * ```js - * lib.define('int', /^[0-9]+$/); - * ``` - * - * ... or as a function: - * - * ```js - * lib.define('bln', function (obj) { - * if ('boolean' === lib.of(obj)) return true; - * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ]; - * if ('string' === lib.of(obj)) obj = obj.toLowerCase(); - * return !! ~blns.indexOf(obj); - * }); - * ``` - * - * @param {String} type - * @param {RegExp|Function} test - * @api public - */ - -Library.prototype.define = function (type, test) { - if (arguments.length === 1) return this.tests[type]; - this.tests[type] = test; - return this; -}; - -/** - * #### .test (obj, test) - * - * Assert that an object is of type. Will first - * check natives, and if that does not pass it will - * use the user defined custom tests. - * - * ```js - * assert(lib.test('1', 'int')); - * assert(lib.test('yes', 'bln')); - * ``` - * - * @param {Mixed} object - * @param {String} type - * @return {Boolean} result - * @api public - */ - -Library.prototype.test = function (obj, type) { - if (type === getType(obj)) return true; - var test = this.tests[type]; - - if (test && 'regexp' === getType(test)) { - return test.test(obj); - } else if (test && 'function' === getType(test)) { - return test(obj); - } else { - throw new ReferenceError('Type test "' + type + '" not defined or invalid.'); - } -}; - -}); - -require.register("chaijs~deep-eql@0.1.3", function (exports, module) { -/*! - * deep-eql - * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com> - * MIT Licensed - */ - -/*! - * Module dependencies - */ - -var type = require('chaijs~type-detect@0.1.1'); - -/*! - * Buffer.isBuffer browser shim - */ - -var Buffer; -try { Buffer = require('buffer').Buffer; } -catch(ex) { - Buffer = {}; - Buffer.isBuffer = function() { return false; } -} - -/*! - * Primary Export - */ - -module.exports = deepEqual; - -/** - * Assert super-strict (egal) equality between - * two objects of any type. - * - * @param {Mixed} a - * @param {Mixed} b - * @param {Array} memoised (optional) - * @return {Boolean} equal match - */ - -function deepEqual(a, b, m) { - if (sameValue(a, b)) { - return true; - } else if ('date' === type(a)) { - return dateEqual(a, b); - } else if ('regexp' === type(a)) { - return regexpEqual(a, b); - } else if (Buffer.isBuffer(a)) { - return bufferEqual(a, b); - } else if ('arguments' === type(a)) { - return argumentsEqual(a, b, m); - } else if (!typeEqual(a, b)) { - return false; - } else if (('object' !== type(a) && 'object' !== type(b)) - && ('array' !== type(a) && 'array' !== type(b))) { - return sameValue(a, b); - } else { - return objectEqual(a, b, m); - } -} - -/*! - * Strict (egal) equality test. Ensures that NaN always - * equals NaN and `-0` does not equal `+0`. - * - * @param {Mixed} a - * @param {Mixed} b - * @return {Boolean} equal match - */ - -function sameValue(a, b) { - if (a === b) return a !== 0 || 1 / a === 1 / b; - return a !== a && b !== b; -} - -/*! - * Compare the types of two given objects and - * return if they are equal. Note that an Array - * has a type of `array` (not `object`) and arguments - * have a type of `arguments` (not `array`/`object`). - * - * @param {Mixed} a - * @param {Mixed} b - * @return {Boolean} result - */ - -function typeEqual(a, b) { - return type(a) === type(b); -} - -/*! - * Compare two Date objects by asserting that - * the time values are equal using `saveValue`. - * - * @param {Date} a - * @param {Date} b - * @return {Boolean} result - */ - -function dateEqual(a, b) { - if ('date' !== type(b)) return false; - return sameValue(a.getTime(), b.getTime()); -} - -/*! - * Compare two regular expressions by converting them - * to string and checking for `sameValue`. - * - * @param {RegExp} a - * @param {RegExp} b - * @return {Boolean} result - */ - -function regexpEqual(a, b) { - if ('regexp' !== type(b)) return false; - return sameValue(a.toString(), b.toString()); -} - -/*! - * Assert deep equality of two `arguments` objects. - * Unfortunately, these must be sliced to arrays - * prior to test to ensure no bad behavior. - * - * @param {Arguments} a - * @param {Arguments} b - * @param {Array} memoize (optional) - * @return {Boolean} result - */ - -function argumentsEqual(a, b, m) { - if ('arguments' !== type(b)) return false; - a = [].slice.call(a); - b = [].slice.call(b); - return deepEqual(a, b, m); -} - -/*! - * Get enumerable properties of a given object. - * - * @param {Object} a - * @return {Array} property names - */ - -function enumerable(a) { - var res = []; - for (var key in a) res.push(key); - return res; -} - -/*! - * Simple equality for flat iterable objects - * such as Arrays or Node.js buffers. - * - * @param {Iterable} a - * @param {Iterable} b - * @return {Boolean} result - */ - -function iterableEqual(a, b) { - if (a.length !== b.length) return false; - - var i = 0; - var match = true; - - for (; i < a.length; i++) { - if (a[i] !== b[i]) { - match = false; - break; - } - } - - return match; -} - -/*! - * Extension to `iterableEqual` specifically - * for Node.js Buffers. - * - * @param {Buffer} a - * @param {Mixed} b - * @return {Boolean} result - */ - -function bufferEqual(a, b) { - if (!Buffer.isBuffer(b)) return false; - return iterableEqual(a, b); -} - -/*! - * Block for `objectEqual` ensuring non-existing - * values don't get in. - * - * @param {Mixed} object - * @return {Boolean} result - */ - -function isValue(a) { - return a !== null && a !== undefined; -} - -/*! - * Recursively check the equality of two objects. - * Once basic sameness has been established it will - * defer to `deepEqual` for each enumerable key - * in the object. - * - * @param {Mixed} a - * @param {Mixed} b - * @return {Boolean} result - */ - -function objectEqual(a, b, m) { - if (!isValue(a) || !isValue(b)) { - return false; - } - - if (a.prototype !== b.prototype) { - return false; - } - - var i; - if (m) { - for (i = 0; i < m.length; i++) { - if ((m[i][0] === a && m[i][1] === b) - || (m[i][0] === b && m[i][1] === a)) { - return true; - } - } - } else { - m = []; - } - - try { - var ka = enumerable(a); - var kb = enumerable(b); - } catch (ex) { - return false; - } - - ka.sort(); - kb.sort(); - - if (!iterableEqual(ka, kb)) { - return false; - } - - m.push([ a, b ]); - - var key; - for (i = ka.length - 1; i >= 0; i--) { - key = ka[i]; - if (!deepEqual(a[key], b[key], m)) { - return false; - } - } - - return true; -} - -}); - -require.register("chai", function (exports, module) { -module.exports = require('chai/lib/chai.js'); - -}); - -require.register("chai/lib/chai.js", function (exports, module) { -/*! * chai * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -676,23 +13,23 @@ /*! * Chai version */ -exports.version = '1.9.2'; +exports.version = '3.0.0'; /*! * Assertion Error */ -exports.AssertionError = require('chaijs~assertion-error@1.0.0'); +exports.AssertionError = require('assertion-error'); /*! * Utils for plugins (not exported) */ -var util = require('chai/lib/chai/utils/index.js'); +var util = require('./chai/utils'); /** * # .use(function) * * Provides a way to extend the internals of Chai @@ -710,62 +47,66 @@ return this; }; /*! + * Utility Functions + */ + +exports.util = util; + +/*! * Configuration */ -var config = require('chai/lib/chai/config.js'); +var config = require('./chai/config'); exports.config = config; /*! * Primary `Assertion` prototype */ -var assertion = require('chai/lib/chai/assertion.js'); +var assertion = require('./chai/assertion'); exports.use(assertion); /*! * Core Assertions */ -var core = require('chai/lib/chai/core/assertions.js'); +var core = require('./chai/core/assertions'); exports.use(core); /*! * Expect interface */ -var expect = require('chai/lib/chai/interface/expect.js'); +var expect = require('./chai/interface/expect'); exports.use(expect); /*! * Should interface */ -var should = require('chai/lib/chai/interface/should.js'); +var should = require('./chai/interface/should'); exports.use(should); /*! * Assert interface */ -var assert = require('chai/lib/chai/interface/assert.js'); +var assert = require('./chai/interface/assert'); exports.use(assert); -}); - -require.register("chai/lib/chai/assertion.js", function (exports, module) { +},{"./chai/assertion":3,"./chai/config":4,"./chai/core/assertions":5,"./chai/interface/assert":6,"./chai/interface/expect":7,"./chai/interface/should":8,"./chai/utils":21,"assertion-error":29}],3:[function(require,module,exports){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ -var config = require('chai/lib/chai/config.js'); +var config = require('./config'); module.exports = function (_chai, util) { /*! * Module dependencies. */ @@ -837,21 +178,22 @@ Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) { util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior); }; - /*! - * ### .assert(expression, message, negateMessage, expected, actual) + /** + * ### .assert(expression, message, negateMessage, expected, actual, showDiff) * * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. * * @name assert * @param {Philosophical} expression to be tested - * @param {String or Function} message or function that returns message to display if fails + * @param {String or Function} message or function that returns message to display if expression fails * @param {String or Function} negatedMessage or function that returns negatedMessage to display if negated expression fails * @param {Mixed} expected value (remember to check for negation) * @param {Mixed} actual (optional) will default to `this.obj` + * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails * @api private */ Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) { var ok = util.test(this, arguments); @@ -885,13 +227,11 @@ flag(this, 'object', val); } }); }; -}); - -require.register("chai/lib/chai/config.js", function (exports, module) { +},{"./config":4}],4:[function(require,module,exports){ module.exports = { /** * ### config.includeStack * @@ -924,28 +264,31 @@ /** * ### config.truncateThreshold * * User configurable property, sets length threshold for actual and - * expected values in assertion errors. If this threshold is exceeded, - * the value is truncated. + * expected values in assertion errors. If this threshold is exceeded, for + * example for large data structures, the value is replaced with something + * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`. * * Set it to zero if you want to disable truncating altogether. * + * This is especially userful when doing assertions on arrays: having this + * set to a reasonable large value makes the failure messages readily + * inspectable. + * * chai.config.truncateThreshold = 0; // disable truncating * * @param {Number} * @api public */ truncateThreshold: 40 }; -}); - -require.register("chai/lib/chai/core/assertions.js", function (exports, module) { +},{}],5:[function(require,module,exports){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed @@ -969,10 +312,11 @@ * - to * - be * - been * - is * - that + * - which * - and * - has * - have * - with * - at @@ -983,11 +327,11 @@ * @api public */ [ 'to', 'be', 'been' , 'is', 'and', 'has', 'have' - , 'with', 'that', 'at' + , 'with', 'that', 'which', 'at' , 'of', 'same' ].forEach(function (chain) { Assertion.addProperty(chain, function () { return this; }); }); @@ -1018,19 +362,60 @@ * * expect(foo).to.deep.equal({ bar: 'baz' }); * expect({ foo: { bar: { baz: 'quux' } } }) * .to.have.deep.property('foo.bar.baz', 'quux'); * + * `.deep.property` special characters can be escaped + * by adding two slashes before the `.` or `[]`. + * + * var deepCss = { '.link': { '[target]': 42 }}; + * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42); + * * @name deep * @api public */ Assertion.addProperty('deep', function () { flag(this, 'deep', true); }); /** + * ### .any + * + * Sets the `any` flag, (opposite of the `all` flag) + * later used in the `keys` assertion. + * + * expect(foo).to.have.any.keys('bar', 'baz'); + * + * @name any + * @api public + */ + + Assertion.addProperty('any', function () { + flag(this, 'any', true); + flag(this, 'all', false) + }); + + + /** + * ### .all + * + * Sets the `all` flag (opposite of the `any` flag) + * later used by the `keys` assertion. + * + * expect(foo).to.have.all.keys('bar', 'baz'); + * + * @name all + * @api public + */ + + Assertion.addProperty('all', function () { + flag(this, 'all', true); + flag(this, 'any', false); + }); + + /** * ### .a(type) * * The `a` and `an` assertions are aliases that can be * used either as language chains or to assert a value's * type. @@ -1038,11 +423,17 @@ * // typeof * expect('test').to.be.a('string'); * expect({ foo: 'bar' }).to.be.an('object'); * expect(null).to.be.a('null'); * expect(undefined).to.be.an('undefined'); + * expect(new Promise).to.be.a('promise'); + * expect(new Float32Array()).to.be.a('float32array'); + * expect(Symbol()).to.be.a('symbol'); * + * // es6 overrides + * expect({[Symbol.toStringTag]:()=>'foo'}).to.be.a('foo'); + * * // language chain * expect(foo).to.be.an.instanceof(Foo); * * @name a * @alias an @@ -1071,18 +462,20 @@ * ### .include(value) * * The `include` and `contain` assertions can be used as either property * based language chains or as methods to assert the inclusion of an object * in an array or a substring in a string. When used as language chains, - * they toggle the `contain` flag for the `keys` assertion. + * they toggle the `contains` flag for the `keys` assertion. * * expect([1,2,3]).to.include(2); * expect('foobar').to.contain('foo'); * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); * * @name include * @alias contain + * @alias includes + * @alias contains * @param {Object|String|Number} obj * @param {String} message _optional_ * @api public */ @@ -1104,24 +497,26 @@ } else if (_.type(val) === 'object') { if (!flag(this, 'negate')) { for (var k in val) new Assertion(obj).property(k, val[k]); return; } - var subset = {} - for (var k in val) subset[k] = obj[k] + var subset = {}; + for (var k in val) subset[k] = obj[k]; expected = _.eql(subset, val); } else { - expected = obj && ~obj.indexOf(val) + expected = obj && ~obj.indexOf(val); } this.assert( expected , 'expected #{this} to include ' + _.inspect(val) , 'expected #{this} to not include ' + _.inspect(val)); } Assertion.addChainableMethod('include', include, includeChainingBehavior); Assertion.addChainableMethod('contain', include, includeChainingBehavior); + Assertion.addChainableMethod('contains', include, includeChainingBehavior); + Assertion.addChainableMethod('includes', include, includeChainingBehavior); /** * ### .ok * * Asserts that the target is truthy. @@ -1189,11 +584,11 @@ * ### .null * * Asserts that the target is `null`. * * expect(null).to.be.null; - * expect(undefined).not.to.be.null; + * expect(undefined).to.not.be.null; * * @name null * @api public */ @@ -1252,11 +647,11 @@ /** * ### .empty * - * Asserts that the target's length is `0`. For arrays, it checks + * Asserts that the target's length is `0`. For arrays and strings, it checks * the `length` property. For objects, it gets the count of * enumerable keys. * * expect([]).to.be.empty; * expect('').to.be.empty; @@ -1665,11 +1060,11 @@ * // deep referencing * var deepObj = { * green: { tea: 'matcha' } * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ] * }; - + * * expect(deepObj).to.have.deep.property('green.tea', 'matcha'); * expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); * * You can also use an array as the starting point of a `deep.property` @@ -1697,10 +1092,22 @@ * expect(deepObj).to.have.property('teas') * .that.is.an('array') * .with.deep.property('[2]') * .that.deep.equals({ tea: 'konacha' }); * + * Note that dots and bracket in `name` must be backslash-escaped when + * the `deep` flag is set, while they must NOT be escaped when the `deep` + * flag is not set. + * + * // simple referencing + * var css = { '.link[target]': 42 }; + * expect(css).to.have.property('.link[target]', 42); + * + * // deep referencing + * var deepCss = { '.link': { '[target]': 42 }}; + * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42); + * * @name property * @alias deep.property * @param {String} name * @param {Mixed} value (optional) * @param {String} message _optional_ @@ -1709,30 +1116,35 @@ */ Assertion.addMethod('property', function (name, val, msg) { if (msg) flag(this, 'message', msg); - var descriptor = flag(this, 'deep') ? 'deep property ' : 'property ' + var isDeep = !!flag(this, 'deep') + , descriptor = isDeep ? 'deep property ' : 'property ' , negate = flag(this, 'negate') , obj = flag(this, 'object') - , value = flag(this, 'deep') - ? _.getPathValue(name, obj) + , pathInfo = isDeep ? _.getPathInfo(name, obj) : null + , hasProperty = isDeep + ? pathInfo.exists + : _.hasProperty(name, obj) + , value = isDeep + ? pathInfo.value : obj[name]; - if (negate && undefined !== val) { + if (negate && arguments.length > 1) { if (undefined === value) { msg = (msg != null) ? msg + ': ' : ''; throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name)); } } else { this.assert( - undefined !== value + hasProperty , 'expected #{this} to have a ' + descriptor + _.inspect(name) , 'expected #{this} to not have ' + descriptor + _.inspect(name)); } - if (undefined !== val) { + if (arguments.length > 1) { this.assert( val === value , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}' , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}' , val @@ -1770,30 +1182,90 @@ Assertion.addMethod('ownProperty', assertOwnProperty); Assertion.addMethod('haveOwnProperty', assertOwnProperty); /** - * ### .length(value) + * ### .ownPropertyDescriptor(name[, descriptor[, message]]) * - * Asserts that the target's `length` property has - * the expected value. + * Asserts that the target has an own property descriptor `name`, that optionally matches `descriptor`. * - * expect([ 1, 2, 3]).to.have.length(3); - * expect('foobar').to.have.length(6); + * expect('test').to.have.ownPropertyDescriptor('length'); + * expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 }); + * expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 }); + * expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false); + * expect('test').ownPropertyDescriptor('length').to.have.keys('value'); * - * Can also be used as a chain precursor to a value - * comparison for the length property. + * @name ownPropertyDescriptor + * @alias haveOwnPropertyDescriptor + * @param {String} name + * @param {Object} descriptor _optional_ + * @param {String} message _optional_ + * @api public + */ + + function assertOwnPropertyDescriptor (name, descriptor, msg) { + if (typeof descriptor === 'string') { + msg = descriptor; + descriptor = null; + } + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name); + if (actualDescriptor && descriptor) { + this.assert( + _.eql(descriptor, actualDescriptor) + , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor) + , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor) + , descriptor + , actualDescriptor + , true + ); + } else { + this.assert( + actualDescriptor + , 'expected #{this} to have an own property descriptor for ' + _.inspect(name) + , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name) + ); + } + flag(this, 'object', actualDescriptor); + } + + Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor); + Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor); + + /** + * ### .length * + * Sets the `doLength` flag later used as a chain precursor to a value + * comparison for the `length` property. + * * expect('foo').to.have.length.above(2); * expect([ 1, 2, 3 ]).to.have.length.above(2); * expect('foo').to.have.length.below(4); * expect([ 1, 2, 3 ]).to.have.length.below(4); * expect('foo').to.have.length.within(2,4); * expect([ 1, 2, 3 ]).to.have.length.within(2,4); * + * *Deprecation notice:* Using `length` as an assertion will be deprecated + * in version 2.4.0 and removed in 3.0.0. Code using the old style of + * asserting for `length` property value using `length(value)` should be + * switched to use `lengthOf(value)` instead. + * * @name length - * @alias lengthOf + * @api public + */ + + /** + * ### .lengthOf(value[, message]) + * + * Asserts that the target's `length` property has + * the expected value. + * + * expect([ 1, 2, 3]).to.have.lengthOf(3); + * expect('foobar').to.have.lengthOf(6); + * + * @name lengthOf * @param {Number} length * @param {String} message _optional_ * @api public */ @@ -1825,25 +1297,28 @@ * Asserts that the target matches a regular expression. * * expect('foobar').to.match(/^foo/); * * @name match + * @alias matches * @param {RegExp} RegularExpression * @param {String} message _optional_ * @api public */ - - Assertion.addMethod('match', function (re, msg) { + function assertMatch(re, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( re.exec(obj) , 'expected #{this} to match ' + re , 'expected #{this} not to match ' + re ); - }); + } + Assertion.addMethod('match', assertMatch); + Assertion.addMethod('matches', assertMatch); + /** * ### .string(string) * * Asserts that the string target contains another string. * @@ -1869,55 +1344,105 @@ /** * ### .keys(key1, [key2], [...]) * - * Asserts that the target has exactly the given keys, or - * asserts the inclusion of some keys when using the - * `include` or `contain` modifiers. + * Asserts that the target contains any or all of the passed-in keys. + * Use in combination with `any`, `all`, `contains`, or `have` will affect + * what will pass. * - * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']); - * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar'); + * When used in conjunction with `any`, at least one key that is passed + * in must exist in the target object. This is regardless whether or not + * the `have` or `contain` qualifiers are used. Note, either `any` or `all` + * should be used in the assertion. If neither are used, the assertion is + * defaulted to `all`. * + * When both `all` and `contain` are used, the target object must have at + * least all of the passed-in keys but may have more keys not listed. + * + * When both `all` and `have` are used, the target object must both contain + * all of the passed-in keys AND the number of keys in the target object must + * match the number of keys passed in (in other words, a target object must + * have all and only all of the passed-in keys). + * + * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz'); + * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo'); + * expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz'); + * expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']); + * expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6}); + * expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']); + * expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7}); + * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']); + * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys({'bar': 6}); + * + * * @name keys * @alias key - * @param {String...|Array} keys + * @param {String...|Array|Object} keys * @api public */ function assertKeys (keys) { var obj = flag(this, 'object') , str - , ok = true; + , ok = true + , mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments'; - keys = keys instanceof Array - ? keys - : Array.prototype.slice.call(arguments); + switch (_.type(keys)) { + case "array": + if (arguments.length > 1) throw (new Error(mixedArgsMsg)); + break; + case "object": + if (arguments.length > 1) throw (new Error(mixedArgsMsg)); + keys = Object.keys(keys); + break; + default: + keys = Array.prototype.slice.call(arguments); + } if (!keys.length) throw new Error('keys required'); var actual = Object.keys(obj) , expected = keys - , len = keys.length; + , len = keys.length + , any = flag(this, 'any') + , all = flag(this, 'all'); - // Inclusion - ok = keys.every(function(key){ - return ~actual.indexOf(key); - }); + if (!any && !all) { + all = true; + } - // Strict - if (!flag(this, 'negate') && !flag(this, 'contains')) { - ok = ok && keys.length == actual.length; + // Has any + if (any) { + var intersection = expected.filter(function(key) { + return ~actual.indexOf(key); + }); + ok = intersection.length > 0; } + // Has all + if (all) { + ok = keys.every(function(key){ + return ~actual.indexOf(key); + }); + if (!flag(this, 'negate') && !flag(this, 'contains')) { + ok = ok && keys.length == actual.length; + } + } + // Key string if (len > 1) { keys = keys.map(function(key){ return _.inspect(key); }); var last = keys.pop(); - str = keys.join(', ') + ', and ' + last; + if (all) { + str = keys.join(', ') + ', and ' + last; + } + if (any) { + str = keys.join(', ') + ', or ' + last; + } } else { str = _.inspect(keys[0]); } // Form @@ -1929,11 +1454,11 @@ // Assertion this.assert( ok , 'expected #{this} to ' + str , 'expected #{this} to not ' + str - , expected.sort() + , expected.slice(0).sort() , actual.sort() , true ); } @@ -2037,11 +1562,11 @@ return this; } } // next, check message - var message = 'object' === _.type(err) && "message" in err + var message = 'error' === _.type(err) && "message" in err ? err.message : '' + err; if ((message != null) && errMsg && errMsg instanceof RegExp) { this.assert( @@ -2266,15 +1791,127 @@ , 'expected #{this} to not have the same members as #{act}' , obj , subset ); }); -}; -}); + /** + * ### .change(function) + * + * Asserts that a function changes an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val += 3 }; + * var noChangeFn = function() { return 'foo' + 'bar'; } + * expect(fn).to.change(obj, 'val'); + * expect(noChangFn).to.not.change(obj, 'val') + * + * @name change + * @alias changes + * @alias Change + * @param {String} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ -require.register("chai/lib/chai/interface/assert.js", function (exports, module) { + function assertChanges (object, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object'); + new Assertion(object, msg).to.have.property(prop); + new Assertion(fn).is.a('function'); + + var initial = object[prop]; + fn(); + + this.assert( + initial !== object[prop] + , 'expected .' + prop + ' to change' + , 'expected .' + prop + ' to not change' + ); + } + + Assertion.addChainableMethod('change', assertChanges); + Assertion.addChainableMethod('changes', assertChanges); + + /** + * ### .increase(function) + * + * Asserts that a function increases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * expect(fn).to.increase(obj, 'val'); + * + * @name increase + * @alias increases + * @alias Increase + * @param {String} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + function assertIncreases (object, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object'); + new Assertion(object, msg).to.have.property(prop); + new Assertion(fn).is.a('function'); + + var initial = object[prop]; + fn(); + + this.assert( + object[prop] - initial > 0 + , 'expected .' + prop + ' to increase' + , 'expected .' + prop + ' to not increase' + ); + } + + Assertion.addChainableMethod('increase', assertIncreases); + Assertion.addChainableMethod('increases', assertIncreases); + + /** + * ### .decrease(function) + * + * Asserts that a function decreases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * expect(fn).to.decrease(obj, 'val'); + * + * @name decrease + * @alias decreases + * @alias Decrease + * @param {String} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + function assertDecreases (object, prop, msg) { + if (msg) flag(this, 'message', msg); + var fn = flag(this, 'object'); + new Assertion(object, msg).to.have.property(prop); + new Assertion(fn).is.a('function'); + + var initial = object[prop]; + fn(); + + this.assert( + object[prop] - initial < 0 + , 'expected .' + prop + ' to decrease' + , 'expected .' + prop + ' to not decrease' + ); + } + + Assertion.addChainableMethod('decrease', assertDecreases); + Assertion.addChainableMethod('decreases', assertDecreases); + +}; + +},{}],6:[function(require,module,exports){ /*! * chai * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -2510,10 +2147,46 @@ * @param {Mixed} value * @param {String} message * @api public */ + assert.isAbove = function (val, abv, msg) { + new Assertion(val, msg).to.be.above(abv); + }; + + /** + * ### .isAbove(valueToCheck, valueToBeAbove, [message]) + * + * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove` + * + * assert.isAbove(5, 2, '5 is strictly greater than 2'); + * + * @name isAbove + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeAbove + * @param {String} message + * @api public + */ + + assert.isBelow = function (val, blw, msg) { + new Assertion(val, msg).to.be.below(blw); + }; + + /** + * ### .isBelow(valueToCheck, valueToBeBelow, [message]) + * + * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow` + * + * assert.isBelow(3, 6, '3 is strictly less than 6'); + * + * @name isBelow + * @param {Mixed} valueToCheck + * @param {Mixed} valueToBeBelow + * @param {String} message + * @api public + */ + assert.isTrue = function (val, msg) { new Assertion(val, msg).is['true']; }; /** @@ -2937,11 +2610,11 @@ /** * ### .notInclude(haystack, needle, [message]) * * Asserts that `haystack` does not include `needle`. Works * for strings and arrays. - *i + * * assert.notInclude('foobar', 'baz', 'string not include substring'); * assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value'); * * @name notInclude * @param {Array|String} haystack @@ -3241,14 +2914,40 @@ * @param {String} message * @api public */ assert.operator = function (val, operator, val2, msg) { - if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) { - throw new Error('Invalid operator "' + operator + '"'); + var ok; + switch(operator) { + case '==': + ok = val == val2; + break; + case '===': + ok = val === val2; + break; + case '>': + ok = val > val2; + break; + case '>=': + ok = val >= val2; + break; + case '<': + ok = val < val2; + break; + case '<=': + ok = val <= val2; + break; + case '!=': + ok = val != val2; + break; + case '!==': + ok = val !== val2; + break; + default: + throw new Error('Invalid operator "' + operator + '"'); } - var test = new Assertion(eval(val + operator + val2), msg); + var test = new Assertion(ok, msg); test.assert( true === flag(test, 'object') , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2) , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) ); }; @@ -3290,10 +2989,29 @@ assert.sameMembers = function (set1, set2, msg) { new Assertion(set1, msg).to.have.same.members(set2); } /** + * ### .sameDeepMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` have the same members - using a deep equality checking. + * Order is not taken into account. + * + * assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members'); + * + * @name sameDeepMembers + * @param {Array} set1 + * @param {Array} set2 + * @param {String} message + * @api public + */ + + assert.sameDeepMembers = function (set1, set2, msg) { + new Assertion(set1, msg).to.have.same.deep.members(set2); + } + + /** * ### .includeMembers(superset, subset, [message]) * * Asserts that `subset` is included in `superset`. * Order is not taken into account. * @@ -3308,16 +3026,155 @@ assert.includeMembers = function (superset, subset, msg) { new Assertion(superset, msg).to.include.members(subset); } + /** + * ### .changes(function, object, property) + * + * Asserts that a function changes the value of a property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 22 }; + * assert.changes(fn, obj, 'val'); + * + * @name changes + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.changes = function (fn, obj, prop) { + new Assertion(fn).to.change(obj, prop); + } + + /** + * ### .doesNotChange(function, object, property) + * + * Asserts that a function does not changes the value of a property + * + * var obj = { val: 10 }; + * var fn = function() { console.log('foo'); }; + * assert.doesNotChange(fn, obj, 'val'); + * + * @name doesNotChange + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.doesNotChange = function (fn, obj, prop) { + new Assertion(fn).to.not.change(obj, prop); + } + + /** + * ### .increases(function, object, property) + * + * Asserts that a function increases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 13 }; + * assert.increases(fn, obj, 'val'); + * + * @name increases + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.increases = function (fn, obj, prop) { + new Assertion(fn).to.increase(obj, prop); + } + + /** + * ### .doesNotIncrease(function, object, property) + * + * Asserts that a function does not increase object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 8 }; + * assert.doesNotIncrease(fn, obj, 'val'); + * + * @name doesNotIncrease + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.doesNotIncrease = function (fn, obj, prop) { + new Assertion(fn).to.not.increase(obj, prop); + } + + /** + * ### .decreases(function, object, property) + * + * Asserts that a function decreases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 5 }; + * assert.decreases(fn, obj, 'val'); + * + * @name decreases + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.decreases = function (fn, obj, prop) { + new Assertion(fn).to.decrease(obj, prop); + } + + /** + * ### .doesNotDecrease(function, object, property) + * + * Asserts that a function does not decreases an object property + * + * var obj = { val: 10 }; + * var fn = function() { obj.val = 15 }; + * assert.doesNotDecrease(fn, obj, 'val'); + * + * @name doesNotDecrease + * @param {Function} modifier function + * @param {Object} object + * @param {String} property name + * @param {String} message _optional_ + * @api public + */ + + assert.doesNotDecrease = function (fn, obj, prop) { + new Assertion(fn).to.not.decrease(obj, prop); + } + /*! - * Undocumented / untested + * ### .ifError(object) + * + * Asserts if value is not a false value, and throws if it is a true value. + * This is added to allow for chai to be a drop-in replacement for Node's + * assert class. + * + * var err = new Error('I am a custom error'); + * assert.ifError(err); // Rethrows err! + * + * @name ifError + * @param {Object} object + * @api public */ - assert.ifError = function (val, msg) { - new Assertion(val, msg).to.not.be.ok; + assert.ifError = function (val) { + if (val) { + throw(val); + } }; /*! * Aliases. */ @@ -3328,29 +3185,46 @@ }) ('Throw', 'throw') ('Throw', 'throws'); }; -}); - -require.register("chai/lib/chai/interface/expect.js", function (exports, module) { +},{}],7:[function(require,module,exports){ /*! * chai * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ module.exports = function (chai, util) { chai.expect = function (val, message) { return new chai.Assertion(val, message); }; -}; + /** + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @api public + */ -}); + chai.expect.fail = function (actual, expected, message, operator) { + message = message || 'expect.fail()'; + throw new chai.AssertionError(message, { + actual: actual + , expected: expected + , operator: operator + }, chai.expect.fail); + }; +}; -require.register("chai/lib/chai/interface/should.js", function (exports, module) { +},{}],8:[function(require,module,exports){ /*! * chai * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -3359,14 +3233,12 @@ var Assertion = chai.Assertion; function loadShould () { // explicitly define this method as function as to have it's name to include as `ssfi` function shouldGetter() { - if (this instanceof String || this instanceof Number) { - return new Assertion(this.constructor(this), null, shouldGetter); - } else if (this instanceof Boolean) { - return new Assertion(this == true, null, shouldGetter); + if (this instanceof String || this instanceof Number || this instanceof Boolean ) { + return new Assertion(this.valueOf(), null, shouldGetter); } return new Assertion(this, null, shouldGetter); } function shouldSetter(value) { // See https://github.com/chaijs/chai/issues/86: this makes @@ -3389,10 +3261,32 @@ , configurable: true }); var should = {}; + /** + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @api public + */ + + should.fail = function (actual, expected, message, operator) { + message = message || 'should.fail()'; + throw new chai.AssertionError(message, { + actual: actual + , expected: expected + , operator: operator + }, should.fail); + }; + should.equal = function (val1, val2, msg) { new Assertion(val1, msg).to.equal(val2); }; should.Throw = function (fn, errt, errs, msg) { @@ -3426,26 +3320,24 @@ chai.should = loadShould; chai.Should = loadShould; }; -}); - -require.register("chai/lib/chai/utils/addChainableMethod.js", function (exports, module) { +},{}],9:[function(require,module,exports){ /*! * Chai - addChainingMethod utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ /*! * Module dependencies */ -var transferFlags = require('chai/lib/chai/utils/transferFlags.js'); -var flag = require('chai/lib/chai/utils/flag.js'); -var config = require('chai/lib/chai/config.js'); +var transferFlags = require('./transferFlags'); +var flag = require('./flag'); +var config = require('../config'); /*! * Module variables */ @@ -3541,20 +3433,18 @@ } , configurable: true }); }; -}); - -require.register("chai/lib/chai/utils/addMethod.js", function (exports, module) { +},{"../config":4,"./flag":12,"./transferFlags":28}],10:[function(require,module,exports){ /*! * Chai - addMethod utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ -var config = require('chai/lib/chai/config.js'); +var config = require('../config'); /** * ### .addMethod (ctx, name, method) * * Adds a method to the prototype of an object. @@ -3576,11 +3466,11 @@ * @param {String} name of method to add * @param {Function} method function to be used for name * @name addMethod * @api public */ -var flag = require('chai/lib/chai/utils/flag.js'); +var flag = require('./flag'); module.exports = function (ctx, name, method) { ctx[name] = function () { var old_ssfi = flag(this, 'ssfi'); if (old_ssfi && config.includeStack === false) @@ -3588,13 +3478,11 @@ var result = method.apply(this, arguments); return result === undefined ? this : result; }; }; -}); - -require.register("chai/lib/chai/utils/addProperty.js", function (exports, module) { +},{"../config":4,"./flag":12}],11:[function(require,module,exports){ /*! * Chai - addProperty utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -3632,31 +3520,29 @@ } , configurable: true }); }; -}); - -require.register("chai/lib/chai/utils/flag.js", function (exports, module) { +},{}],12:[function(require,module,exports){ /*! * Chai - flag utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ /** - * ### flag(object ,key, [value]) + * ### flag(object, key, [value]) * * Get or set a flag value on an object. If a * value is provided it will be set, else it will * return the currently set value or `undefined` if * the value is not set. * * utils.flag(this, 'foo', 'bar'); // setter * utils.flag(this, 'foo'); // getter, returns `bar` * - * @param {Object} object (constructed Assertion + * @param {Object} object constructed Assertion * @param {String} key * @param {Mixed} value (optional) * @name flag * @api private */ @@ -3668,13 +3554,11 @@ } else { return flags[key]; } }; -}); - -require.register("chai/lib/chai/utils/getActual.js", function (exports, module) { +},{}],13:[function(require,module,exports){ /*! * Chai - getActual utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -3690,13 +3574,11 @@ module.exports = function (obj, args) { return args.length > 4 ? args[4] : obj._obj; }; -}); - -require.register("chai/lib/chai/utils/getEnumerableProperties.js", function (exports, module) { +},{}],14:[function(require,module,exports){ /*! * Chai - getEnumerableProperties utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -3719,27 +3601,25 @@ result.push(name); } return result; }; -}); - -require.register("chai/lib/chai/utils/getMessage.js", function (exports, module) { +},{}],15:[function(require,module,exports){ /*! * Chai - message composition utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ /*! * Module dependancies */ -var flag = require('chai/lib/chai/utils/flag.js') - , getActual = require('chai/lib/chai/utils/getActual.js') - , inspect = require('chai/lib/chai/utils/inspect.js') - , objDisplay = require('chai/lib/chai/utils/objDisplay.js'); +var flag = require('./flag') + , getActual = require('./getActual') + , inspect = require('./inspect') + , objDisplay = require('./objDisplay'); /** * ### .getMessage(object, message, negateMessage) * * Construct the error message based on flags @@ -3773,13 +3653,11 @@ .replace(/#{exp}/g, objDisplay(expected)); return flagMsg ? flagMsg + ': ' + msg : msg; }; -}); - -require.register("chai/lib/chai/utils/getName.js", function (exports, module) { +},{"./flag":12,"./getActual":13,"./inspect":22,"./objDisplay":23}],16:[function(require,module,exports){ /*! * Chai - getName utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -3797,55 +3675,55 @@ var match = /^\s?function ([^(]*)\(/.exec(func); return match && match[1] ? match[1] : ""; }; -}); - -require.register("chai/lib/chai/utils/getPathValue.js", function (exports, module) { +},{}],17:[function(require,module,exports){ /*! - * Chai - getPathValue utility + * Chai - getPathInfo utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> - * @see https://github.com/logicalparadox/filtr * MIT Licensed */ +var hasProperty = require('./hasProperty'); + /** - * ### .getPathValue(path, object) + * ### .getPathInfo(path, object) * - * This allows the retrieval of values in an + * This allows the retrieval of property info in an * object given a string path. * - * var obj = { - * prop1: { - * arr: ['a', 'b', 'c'] - * , str: 'Hello' - * } - * , prop2: { - * arr: [ { nested: 'Universe' } ] - * , str: 'Hello again!' - * } - * } + * The path info consists of an object with the + * following properties: * - * The following would be the results. + * * parent - The parent object of the property referenced by `path` + * * name - The name of the final property, a number if it was an array indexer + * * value - The value of the property, if it exists, otherwise `undefined` + * * exists - Whether the property exists or not * - * getPathValue('prop1.str', obj); // Hello - * getPathValue('prop1.att[2]', obj); // b - * getPathValue('prop2.arr[0].nested', obj); // Universe - * * @param {String} path * @param {Object} object - * @returns {Object} value or `undefined` - * @name getPathValue + * @returns {Object} info + * @name getPathInfo * @api public */ -var getPathValue = module.exports = function (path, obj) { - var parsed = parsePath(path); - return _getPathValue(parsed, obj); +module.exports = function getPathInfo(path, obj) { + var parsed = parsePath(path), + last = parsed[parsed.length - 1]; + + var info = { + parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj, + name: last.p || last.i, + value: _getPathValue(parsed, obj) + }; + info.exists = hasProperty(info.name, info.parent); + + return info; }; + /*! * ## parsePath(path) * * Helper function used to parse string object * paths. Use in conjunction with `_getPathValue`. @@ -3854,45 +3732,51 @@ * * ### Paths: * * * Can be as near infinitely deep and nested * * Arrays are also valid using the formal `myobject.document[3].property`. + * * Literal dots and brackets (not delimiter) must be backslash-escaped. * * @param {String} path * @returns {Object} parsed * @api private */ function parsePath (path) { - var str = path.replace(/\[/g, '.[') + var str = path.replace(/([^\\])\[/g, '$1.[') , parts = str.match(/(\\\.|[^.]+?)+/g); return parts.map(function (value) { - var re = /\[(\d+)\]$/ - , mArr = re.exec(value) + var re = /^\[(\d+)\]$/ + , mArr = re.exec(value); if (mArr) return { i: parseFloat(mArr[1]) }; - else return { p: value }; + else return { p: value.replace(/\\([.\[\]])/g, '$1') }; }); -}; +} + /*! * ## _getPathValue(parsed, obj) * * Helper companion function for `.parsePath` that returns * the value located at the parsed address. * * var value = getPathValue(parsed, obj); * * @param {Object} parsed definition from `parsePath`. * @param {Object} object to search against + * @param {Number} object to search against * @returns {Object|Undefined} value * @api private */ -function _getPathValue (parsed, obj) { +function _getPathValue (parsed, obj, index) { var tmp = obj , res; - for (var i = 0, l = parsed.length; i < l; i++) { + + index = (index === undefined ? parsed.length : index); + + for (var i = 0, l = index; i < l; i++) { var part = parsed[i]; if (tmp) { if ('undefined' !== typeof part.p) tmp = tmp[part.p]; else if ('undefined' !== typeof part.i) @@ -3901,15 +3785,57 @@ } else { res = undefined; } } return res; -}; +} -}); +},{"./hasProperty":20}],18:[function(require,module,exports){ +/*! + * Chai - getPathValue utility + * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> + * @see https://github.com/logicalparadox/filtr + * MIT Licensed + */ -require.register("chai/lib/chai/utils/getProperties.js", function (exports, module) { +var getPathInfo = require('./getPathInfo'); + +/** + * ### .getPathValue(path, object) + * + * This allows the retrieval of values in an + * object given a string path. + * + * var obj = { + * prop1: { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * , prop2: { + * arr: [ { nested: 'Universe' } ] + * , str: 'Hello again!' + * } + * } + * + * The following would be the results. + * + * getPathValue('prop1.str', obj); // Hello + * getPathValue('prop1.att[2]', obj); // b + * getPathValue('prop2.arr[0].nested', obj); // Universe + * + * @param {String} path + * @param {Object} object + * @returns {Object} value or `undefined` + * @name getPathValue + * @api public + */ +module.exports = function(path, obj) { + var info = getPathInfo(path, obj); + return info.value; +}; + +},{"./getPathInfo":17}],19:[function(require,module,exports){ /*! * Chai - getProperties utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -3942,13 +3868,76 @@ } return result; }; -}); +},{}],20:[function(require,module,exports){ +/*! + * Chai - hasProperty utility + * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> + * MIT Licensed + */ -require.register("chai/lib/chai/utils/index.js", function (exports, module) { +var type = require('type-detect'); + +/** + * ### .hasProperty(object, name) + * + * This allows checking whether an object has + * named property or numeric array index. + * + * Basically does the same thing as the `in` + * operator but works properly with natives + * and null/undefined values. + * + * var obj = { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * + * The following would be the results. + * + * hasProperty('str', obj); // true + * hasProperty('constructor', obj); // true + * hasProperty('bar', obj); // false + * + * hasProperty('length', obj.str); // true + * hasProperty(1, obj.str); // true + * hasProperty(5, obj.str); // false + * + * hasProperty('length', obj.arr); // true + * hasProperty(2, obj.arr); // true + * hasProperty(3, obj.arr); // false + * + * @param {Objuect} object + * @param {String|Number} name + * @returns {Boolean} whether it exists + * @name getPathInfo + * @api public + */ + +var literals = { + 'number': Number + , 'string': String +}; + +module.exports = function hasProperty(name, obj) { + var ot = type(obj); + + // Bad Object, obviously no props at all + if(ot === 'null' || ot === 'undefined') + return false; + + // The `in` operator does not work with certain literals + // box these before the check + if(literals[ot] && typeof obj !== 'object') + obj = new literals[ot](obj); + + return name in obj; +}; + +},{"type-detect":34}],21:[function(require,module,exports){ /*! * chai * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -3961,118 +3950,128 @@ /*! * test utility */ -exports.test = require('chai/lib/chai/utils/test.js'); +exports.test = require('./test'); /*! * type utility */ -exports.type = require('chai/lib/chai/utils/type.js'); +exports.type = require('type-detect'); /*! * message utility */ -exports.getMessage = require('chai/lib/chai/utils/getMessage.js'); +exports.getMessage = require('./getMessage'); /*! * actual utility */ -exports.getActual = require('chai/lib/chai/utils/getActual.js'); +exports.getActual = require('./getActual'); /*! * Inspect util */ -exports.inspect = require('chai/lib/chai/utils/inspect.js'); +exports.inspect = require('./inspect'); /*! * Object Display util */ -exports.objDisplay = require('chai/lib/chai/utils/objDisplay.js'); +exports.objDisplay = require('./objDisplay'); /*! * Flag utility */ -exports.flag = require('chai/lib/chai/utils/flag.js'); +exports.flag = require('./flag'); /*! * Flag transferring utility */ -exports.transferFlags = require('chai/lib/chai/utils/transferFlags.js'); +exports.transferFlags = require('./transferFlags'); /*! * Deep equal utility */ -exports.eql = require('chaijs~deep-eql@0.1.3'); +exports.eql = require('deep-eql'); /*! * Deep path value */ -exports.getPathValue = require('chai/lib/chai/utils/getPathValue.js'); +exports.getPathValue = require('./getPathValue'); /*! + * Deep path info + */ + +exports.getPathInfo = require('./getPathInfo'); + +/*! + * Check if a property exists + */ + +exports.hasProperty = require('./hasProperty'); + +/*! * Function name */ -exports.getName = require('chai/lib/chai/utils/getName.js'); +exports.getName = require('./getName'); /*! * add Property */ -exports.addProperty = require('chai/lib/chai/utils/addProperty.js'); +exports.addProperty = require('./addProperty'); /*! * add Method */ -exports.addMethod = require('chai/lib/chai/utils/addMethod.js'); +exports.addMethod = require('./addMethod'); /*! * overwrite Property */ -exports.overwriteProperty = require('chai/lib/chai/utils/overwriteProperty.js'); +exports.overwriteProperty = require('./overwriteProperty'); /*! * overwrite Method */ -exports.overwriteMethod = require('chai/lib/chai/utils/overwriteMethod.js'); +exports.overwriteMethod = require('./overwriteMethod'); /*! * Add a chainable method */ -exports.addChainableMethod = require('chai/lib/chai/utils/addChainableMethod.js'); +exports.addChainableMethod = require('./addChainableMethod'); /*! * Overwrite chainable method */ -exports.overwriteChainableMethod = require('chai/lib/chai/utils/overwriteChainableMethod.js'); +exports.overwriteChainableMethod = require('./overwriteChainableMethod'); -}); - -require.register("chai/lib/chai/utils/inspect.js", function (exports, module) { +},{"./addChainableMethod":9,"./addMethod":10,"./addProperty":11,"./flag":12,"./getActual":13,"./getMessage":15,"./getName":16,"./getPathInfo":17,"./getPathValue":18,"./hasProperty":20,"./inspect":22,"./objDisplay":23,"./overwriteChainableMethod":24,"./overwriteMethod":25,"./overwriteProperty":26,"./test":27,"./transferFlags":28,"deep-eql":30,"type-detect":34}],22:[function(require,module,exports){ // This is (almost) directly from Node.js utils // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js -var getName = require('chai/lib/chai/utils/getName.js'); -var getProperties = require('chai/lib/chai/utils/getProperties.js'); -var getEnumerableProperties = require('chai/lib/chai/utils/getEnumerableProperties.js'); +var getName = require('./getName'); +var getProperties = require('./getProperties'); +var getEnumerableProperties = require('./getEnumerableProperties'); module.exports = inspect; /** * Echos the value of a value. Trys to print the value out @@ -4256,10 +4255,13 @@ .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); case 'number': + if (value === 0 && (1/value) === -Infinity) { + return ctx.stylize('-0', 'number'); + } return ctx.stylize('' + value, 'number'); case 'boolean': return ctx.stylize('' + value, 'boolean'); } @@ -4394,25 +4396,23 @@ function objectToString(o) { return Object.prototype.toString.call(o); } -}); - -require.register("chai/lib/chai/utils/objDisplay.js", function (exports, module) { +},{"./getEnumerableProperties":14,"./getName":16,"./getProperties":19}],23:[function(require,module,exports){ /*! * Chai - flag utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ /*! * Module dependancies */ -var inspect = require('chai/lib/chai/utils/inspect.js'); -var config = require('chai/lib/chai/config.js'); +var inspect = require('./inspect'); +var config = require('../config'); /** * ### .objDisplay (object) * * Determines if an object or an array matches @@ -4447,13 +4447,66 @@ } else { return str; } }; -}); +},{"../config":4,"./inspect":22}],24:[function(require,module,exports){ +/*! + * Chai - overwriteChainableMethod utility + * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> + * MIT Licensed + */ -require.register("chai/lib/chai/utils/overwriteMethod.js", function (exports, module) { +/** + * ### overwriteChainableMethod (ctx, name, method, chainingBehavior) + * + * Overwites an already existing chainable method + * and provides access to the previous function or + * property. Must return functions to be used for + * name. + * + * utils.overwriteChainableMethod(chai.Assertion.prototype, 'length', + * function (_super) { + * } + * , function (_super) { + * } + * ); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteChainableMethod('foo', fn, fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.have.length(3); + * expect(myFoo).to.have.length.above(3); + * + * @param {Object} ctx object whose method / property is to be overwritten + * @param {String} name of method / property to overwrite + * @param {Function} method function that returns a function to be used for name + * @param {Function} chainingBehavior function that returns a function to be used for property + * @name overwriteChainableMethod + * @api public + */ + +module.exports = function (ctx, name, method, chainingBehavior) { + var chainableBehavior = ctx.__methods[name]; + + var _chainingBehavior = chainableBehavior.chainingBehavior; + chainableBehavior.chainingBehavior = function () { + var result = chainingBehavior(_chainingBehavior).call(this); + return result === undefined ? this : result; + }; + + var _method = chainableBehavior.method; + chainableBehavior.method = function () { + var result = method(_method).apply(this, arguments); + return result === undefined ? this : result; + }; +}; + +},{}],25:[function(require,module,exports){ /*! * Chai - overwriteMethod utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -4502,13 +4555,11 @@ var result = method(_super).apply(this, arguments); return result === undefined ? this : result; } }; -}); - -require.register("chai/lib/chai/utils/overwriteProperty.js", function (exports, module) { +},{}],26:[function(require,module,exports){ /*! * Chai - overwriteProperty utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -4560,81 +4611,22 @@ } , configurable: true }); }; -}); - -require.register("chai/lib/chai/utils/overwriteChainableMethod.js", function (exports, module) { +},{}],27:[function(require,module,exports){ /*! - * Chai - overwriteChainableMethod utility - * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> - * MIT Licensed - */ - -/** - * ### overwriteChainableMethod (ctx, name, fn) - * - * Overwites an already existing chainable method - * and provides access to the previous function or - * property. Must return functions to be used for - * name. - * - * utils.overwriteChainableMethod(chai.Assertion.prototype, 'length', - * function (_super) { - * } - * , function (_super) { - * } - * ); - * - * Can also be accessed directly from `chai.Assertion`. - * - * chai.Assertion.overwriteChainableMethod('foo', fn, fn); - * - * Then can be used as any other assertion. - * - * expect(myFoo).to.have.length(3); - * expect(myFoo).to.have.length.above(3); - * - * @param {Object} ctx object whose method / property is to be overwritten - * @param {String} name of method / property to overwrite - * @param {Function} method function that returns a function to be used for name - * @param {Function} chainingBehavior function that returns a function to be used for property - * @name overwriteChainableMethod - * @api public - */ - -module.exports = function (ctx, name, method, chainingBehavior) { - var chainableBehavior = ctx.__methods[name]; - - var _chainingBehavior = chainableBehavior.chainingBehavior; - chainableBehavior.chainingBehavior = function () { - var result = chainingBehavior(_chainingBehavior).call(this); - return result === undefined ? this : result; - }; - - var _method = chainableBehavior.method; - chainableBehavior.method = function () { - var result = method(_method).apply(this, arguments); - return result === undefined ? this : result; - }; -}; - -}); - -require.register("chai/lib/chai/utils/test.js", function (exports, module) { -/*! * Chai - test utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ /*! * Module dependancies */ -var flag = require('chai/lib/chai/utils/flag.js'); +var flag = require('./flag'); /** * # test(object, expression) * * Test and object for expression. @@ -4647,13 +4639,11 @@ var negate = flag(obj, 'negate') , expr = args[0]; return negate ? !expr : expr; }; -}); - -require.register("chai/lib/chai/utils/transferFlags.js", function (exports, module) { +},{"./flag":12}],28:[function(require,module,exports){ /*! * Chai - transferFlags utility * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ @@ -4672,13 +4662,13 @@ * * var anotherAsseriton = new Assertion(myObj); * utils.transferFlags(assertion, anotherAssertion, false); * * @param {Assertion} assertion the assertion to transfer the flags from - * @param {Object} object the object to transfer the flags too; usually a new assertion + * @param {Object} object the object to transfer the flags to; usually a new assertion * @param {Boolean} includeAll - * @name getAllFlags + * @name transferFlags * @api private */ module.exports = function (assertion, object, includeAll) { var flags = assertion.__flags || (assertion.__flags = Object.create(null)); @@ -4695,64 +4685,668 @@ object.__flags[flag] = flags[flag]; } } }; -}); +},{}],29:[function(require,module,exports){ +/*! + * assertion-error + * Copyright(c) 2013 Jake Luer <jake@qualiancy.com> + * MIT Licensed + */ -require.register("chai/lib/chai/utils/type.js", function (exports, module) { /*! - * Chai - type utility - * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com> + * Return a function that will copy properties from + * one object to another excluding any originally + * listed. Returned function will create a new `{}`. + * + * @param {String} excluded properties ... + * @return {Function} + */ + +function exclude () { + var excludes = [].slice.call(arguments); + + function excludeProps (res, obj) { + Object.keys(obj).forEach(function (key) { + if (!~excludes.indexOf(key)) res[key] = obj[key]; + }); + } + + return function extendExclude () { + var args = [].slice.call(arguments) + , i = 0 + , res = {}; + + for (; i < args.length; i++) { + excludeProps(res, args[i]); + } + + return res; + }; +}; + +/*! + * Primary Exports + */ + +module.exports = AssertionError; + +/** + * ### AssertionError + * + * An extension of the JavaScript `Error` constructor for + * assertion and validation scenarios. + * + * @param {String} message + * @param {Object} properties to include (optional) + * @param {callee} start stack function (optional) + */ + +function AssertionError (message, _props, ssf) { + var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON') + , props = extend(_props || {}); + + // default values + this.message = message || 'Unspecified AssertionError'; + this.showDiff = false; + + // copy from properties + for (var key in props) { + this[key] = props[key]; + } + + // capture stack trace + ssf = ssf || arguments.callee; + if (ssf && Error.captureStackTrace) { + Error.captureStackTrace(this, ssf); + } else { + this.stack = new Error().stack; + } +} + +/*! + * Inherit from Error.prototype + */ + +AssertionError.prototype = Object.create(Error.prototype); + +/*! + * Statically set name + */ + +AssertionError.prototype.name = 'AssertionError'; + +/*! + * Ensure correct constructor + */ + +AssertionError.prototype.constructor = AssertionError; + +/** + * Allow errors to be converted to JSON for static transfer. + * + * @param {Boolean} include stack (default: `true`) + * @return {Object} object that can be `JSON.stringify` + */ + +AssertionError.prototype.toJSON = function (stack) { + var extend = exclude('constructor', 'toJSON', 'stack') + , props = extend({ name: this.name }, this); + + // include stack if exists and not turned off + if (false !== stack && this.stack) { + props.stack = this.stack; + } + + return props; +}; + +},{}],30:[function(require,module,exports){ +module.exports = require('./lib/eql'); + +},{"./lib/eql":31}],31:[function(require,module,exports){ +/*! + * deep-eql + * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ /*! + * Module dependencies + */ + +var type = require('type-detect'); + +/*! + * Buffer.isBuffer browser shim + */ + +var Buffer; +try { Buffer = require('buffer').Buffer; } +catch(ex) { + Buffer = {}; + Buffer.isBuffer = function() { return false; } +} + +/*! + * Primary Export + */ + +module.exports = deepEqual; + +/** + * Assert super-strict (egal) equality between + * two objects of any type. + * + * @param {Mixed} a + * @param {Mixed} b + * @param {Array} memoised (optional) + * @return {Boolean} equal match + */ + +function deepEqual(a, b, m) { + if (sameValue(a, b)) { + return true; + } else if ('date' === type(a)) { + return dateEqual(a, b); + } else if ('regexp' === type(a)) { + return regexpEqual(a, b); + } else if (Buffer.isBuffer(a)) { + return bufferEqual(a, b); + } else if ('arguments' === type(a)) { + return argumentsEqual(a, b, m); + } else if (!typeEqual(a, b)) { + return false; + } else if (('object' !== type(a) && 'object' !== type(b)) + && ('array' !== type(a) && 'array' !== type(b))) { + return sameValue(a, b); + } else { + return objectEqual(a, b, m); + } +} + +/*! + * Strict (egal) equality test. Ensures that NaN always + * equals NaN and `-0` does not equal `+0`. + * + * @param {Mixed} a + * @param {Mixed} b + * @return {Boolean} equal match + */ + +function sameValue(a, b) { + if (a === b) return a !== 0 || 1 / a === 1 / b; + return a !== a && b !== b; +} + +/*! + * Compare the types of two given objects and + * return if they are equal. Note that an Array + * has a type of `array` (not `object`) and arguments + * have a type of `arguments` (not `array`/`object`). + * + * @param {Mixed} a + * @param {Mixed} b + * @return {Boolean} result + */ + +function typeEqual(a, b) { + return type(a) === type(b); +} + +/*! + * Compare two Date objects by asserting that + * the time values are equal using `saveValue`. + * + * @param {Date} a + * @param {Date} b + * @return {Boolean} result + */ + +function dateEqual(a, b) { + if ('date' !== type(b)) return false; + return sameValue(a.getTime(), b.getTime()); +} + +/*! + * Compare two regular expressions by converting them + * to string and checking for `sameValue`. + * + * @param {RegExp} a + * @param {RegExp} b + * @return {Boolean} result + */ + +function regexpEqual(a, b) { + if ('regexp' !== type(b)) return false; + return sameValue(a.toString(), b.toString()); +} + +/*! + * Assert deep equality of two `arguments` objects. + * Unfortunately, these must be sliced to arrays + * prior to test to ensure no bad behavior. + * + * @param {Arguments} a + * @param {Arguments} b + * @param {Array} memoize (optional) + * @return {Boolean} result + */ + +function argumentsEqual(a, b, m) { + if ('arguments' !== type(b)) return false; + a = [].slice.call(a); + b = [].slice.call(b); + return deepEqual(a, b, m); +} + +/*! + * Get enumerable properties of a given object. + * + * @param {Object} a + * @return {Array} property names + */ + +function enumerable(a) { + var res = []; + for (var key in a) res.push(key); + return res; +} + +/*! + * Simple equality for flat iterable objects + * such as Arrays or Node.js buffers. + * + * @param {Iterable} a + * @param {Iterable} b + * @return {Boolean} result + */ + +function iterableEqual(a, b) { + if (a.length !== b.length) return false; + + var i = 0; + var match = true; + + for (; i < a.length; i++) { + if (a[i] !== b[i]) { + match = false; + break; + } + } + + return match; +} + +/*! + * Extension to `iterableEqual` specifically + * for Node.js Buffers. + * + * @param {Buffer} a + * @param {Mixed} b + * @return {Boolean} result + */ + +function bufferEqual(a, b) { + if (!Buffer.isBuffer(b)) return false; + return iterableEqual(a, b); +} + +/*! + * Block for `objectEqual` ensuring non-existing + * values don't get in. + * + * @param {Mixed} object + * @return {Boolean} result + */ + +function isValue(a) { + return a !== null && a !== undefined; +} + +/*! + * Recursively check the equality of two objects. + * Once basic sameness has been established it will + * defer to `deepEqual` for each enumerable key + * in the object. + * + * @param {Mixed} a + * @param {Mixed} b + * @return {Boolean} result + */ + +function objectEqual(a, b, m) { + if (!isValue(a) || !isValue(b)) { + return false; + } + + if (a.prototype !== b.prototype) { + return false; + } + + var i; + if (m) { + for (i = 0; i < m.length; i++) { + if ((m[i][0] === a && m[i][1] === b) + || (m[i][0] === b && m[i][1] === a)) { + return true; + } + } + } else { + m = []; + } + + try { + var ka = enumerable(a); + var kb = enumerable(b); + } catch (ex) { + return false; + } + + ka.sort(); + kb.sort(); + + if (!iterableEqual(ka, kb)) { + return false; + } + + m.push([ a, b ]); + + var key; + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key], m)) { + return false; + } + } + + return true; +} + +},{"buffer":undefined,"type-detect":32}],32:[function(require,module,exports){ +module.exports = require('./lib/type'); + +},{"./lib/type":33}],33:[function(require,module,exports){ +/*! + * type-detect + * Copyright(c) 2013 jake luer <jake@alogicalparadox.com> + * MIT Licensed + */ + +/*! + * Primary Exports + */ + +var exports = module.exports = getType; + +/*! * Detectable javascript natives */ var natives = { - '[object Arguments]': 'arguments' - , '[object Array]': 'array' - , '[object Date]': 'date' - , '[object Function]': 'function' - , '[object Number]': 'number' + '[object Array]': 'array' , '[object RegExp]': 'regexp' - , '[object String]': 'string' + , '[object Function]': 'function' + , '[object Arguments]': 'arguments' + , '[object Date]': 'date' }; /** - * ### type(object) + * ### typeOf (obj) * - * Better implementation of `typeof` detection that can - * be used cross-browser. Handles the inconsistencies of - * Array, `null`, and `undefined` detection. + * Use several different techniques to determine + * the type of object being tested. * - * utils.type({}) // 'object' - * utils.type(null) // `null' - * utils.type(undefined) // `undefined` - * utils.type([]) // `array` * - * @param {Mixed} object to detect type of - * @name type - * @api private + * @param {Mixed} object + * @return {String} object type + * @api public */ -module.exports = function (obj) { +function getType (obj) { var str = Object.prototype.toString.call(obj); if (natives[str]) return natives[str]; if (obj === null) return 'null'; if (obj === undefined) return 'undefined'; if (obj === Object(obj)) return 'object'; return typeof obj; +} + +exports.Library = Library; + +/** + * ### Library + * + * Create a repository for custom type detection. + * + * ```js + * var lib = new type.Library; + * ``` + * + */ + +function Library () { + this.tests = {}; +} + +/** + * #### .of (obj) + * + * Expose replacement `typeof` detection to the library. + * + * ```js + * if ('string' === lib.of('hello world')) { + * // ... + * } + * ``` + * + * @param {Mixed} object to test + * @return {String} type + */ + +Library.prototype.of = getType; + +/** + * #### .define (type, test) + * + * Add a test to for the `.test()` assertion. + * + * Can be defined as a regular expression: + * + * ```js + * lib.define('int', /^[0-9]+$/); + * ``` + * + * ... or as a function: + * + * ```js + * lib.define('bln', function (obj) { + * if ('boolean' === lib.of(obj)) return true; + * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ]; + * if ('string' === lib.of(obj)) obj = obj.toLowerCase(); + * return !! ~blns.indexOf(obj); + * }); + * ``` + * + * @param {String} type + * @param {RegExp|Function} test + * @api public + */ + +Library.prototype.define = function (type, test) { + if (arguments.length === 1) return this.tests[type]; + this.tests[type] = test; + return this; }; -}); +/** + * #### .test (obj, test) + * + * Assert that an object is of type. Will first + * check natives, and if that does not pass it will + * use the user defined custom tests. + * + * ```js + * assert(lib.test('1', 'int')); + * assert(lib.test('yes', 'bln')); + * ``` + * + * @param {Mixed} object + * @param {String} type + * @return {Boolean} result + * @api public + */ -if (typeof exports == "object") { - module.exports = require("chai"); -} else if (typeof define == "function" && define.amd) { - define("chai", [], function(){ return require("chai"); }); -} else { - (this || window)["chai"] = require("chai"); +Library.prototype.test = function (obj, type) { + if (type === getType(obj)) return true; + var test = this.tests[type]; + + if (test && 'regexp' === getType(test)) { + return test.test(obj); + } else if (test && 'function' === getType(test)) { + return test(obj); + } else { + throw new ReferenceError('Type test "' + type + '" not defined or invalid.'); + } +}; + +},{}],34:[function(require,module,exports){ +arguments[4][32][0].apply(exports,arguments) +},{"./lib/type":35,"dup":32}],35:[function(require,module,exports){ +/*! + * type-detect + * Copyright(c) 2013 jake luer <jake@alogicalparadox.com> + * MIT Licensed + */ + +/*! + * Primary Exports + */ + +var exports = module.exports = getType; + +/** + * ### typeOf (obj) + * + * Use several different techniques to determine + * the type of object being tested. + * + * + * @param {Mixed} object + * @return {String} object type + * @api public + */ +var objectTypeRegexp = /^\[object (.*)\]$/; + +function getType(obj) { + var type = Object.prototype.toString.call(obj).match(objectTypeRegexp)[1].toLowerCase(); + // Let "new String('')" return 'object' + if (typeof Promise === 'function' && obj instanceof Promise) return 'promise'; + // PhantomJS has type "DOMWindow" for null + if (obj === null) return 'null'; + // PhantomJS has type "DOMWindow" for undefined + if (obj === undefined) return 'undefined'; + return type; } -})() + +exports.Library = Library; + +/** + * ### Library + * + * Create a repository for custom type detection. + * + * ```js + * var lib = new type.Library; + * ``` + * + */ + +function Library() { + if (!(this instanceof Library)) return new Library(); + this.tests = {}; +} + +/** + * #### .of (obj) + * + * Expose replacement `typeof` detection to the library. + * + * ```js + * if ('string' === lib.of('hello world')) { + * // ... + * } + * ``` + * + * @param {Mixed} object to test + * @return {String} type + */ + +Library.prototype.of = getType; + +/** + * #### .define (type, test) + * + * Add a test to for the `.test()` assertion. + * + * Can be defined as a regular expression: + * + * ```js + * lib.define('int', /^[0-9]+$/); + * ``` + * + * ... or as a function: + * + * ```js + * lib.define('bln', function (obj) { + * if ('boolean' === lib.of(obj)) return true; + * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ]; + * if ('string' === lib.of(obj)) obj = obj.toLowerCase(); + * return !! ~blns.indexOf(obj); + * }); + * ``` + * + * @param {String} type + * @param {RegExp|Function} test + * @api public + */ + +Library.prototype.define = function(type, test) { + if (arguments.length === 1) return this.tests[type]; + this.tests[type] = test; + return this; +}; + +/** + * #### .test (obj, test) + * + * Assert that an object is of type. Will first + * check natives, and if that does not pass it will + * use the user defined custom tests. + * + * ```js + * assert(lib.test('1', 'int')); + * assert(lib.test('yes', 'bln')); + * ``` + * + * @param {Mixed} object + * @param {String} type + * @return {Boolean} result + * @api public + */ + +Library.prototype.test = function(obj, type) { + if (type === getType(obj)) return true; + var test = this.tests[type]; + + if (test && 'regexp' === getType(test)) { + return test.test(obj); + } else if (test && 'function' === getType(test)) { + return test(obj); + } else { + throw new ReferenceError('Type test "' + type + '" not defined or invalid.'); + } +}; + +},{}]},{},[1])(1) +}); \ No newline at end of file