UNPKG

cryonic

Version:

Easily pickle/serialize/freeze/store and re-hydrate complex JavaScript objects (including Functions)

1,681 lines (1,481 loc) 110 kB
!function (name, context, definition) { if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') { module.exports = definition(); } else if (typeof define === 'function' && typeof define.amd === 'object') { define(function () { return definition(); }); } else { context[name] = definition(); } }('chai', this, function () { function require(p) { var path = require.resolve(p) , mod = require.modules[path]; if (!mod) throw new Error('failed to require "' + p + '"'); if (!mod.exports) { mod.exports = {}; mod.call(mod.exports, mod, mod.exports, require.relative(path)); } return mod.exports; } require.modules = {}; require.resolve = function (path) { var orig = path , reg = path + '.js' , index = path + '/index.js'; return require.modules[reg] && reg || require.modules[index] && index || orig; }; require.register = function (path, fn) { require.modules[path] = fn; }; require.relative = function (parent) { return function(p){ if ('.' != p.charAt(0)) return require(p); var path = parent.split('/') , segs = p.split('/'); path.pop(); for (var i = 0; i < segs.length; i++) { var seg = segs[i]; if ('..' == seg) path.pop(); else if ('.' != seg) path.push(seg); } return require(path.join('/')); }; }; require.alias = function (from, to) { var fn = require.modules[from]; require.modules[to] = fn; }; require.register("chai.js", function(module, exports, require){ /*! * chai * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ var used = [] , exports = module.exports = {}; /*! * Chai version */ exports.version = '1.2.0'; /*! * Primary `Assertion` prototype */ exports.Assertion = require('./chai/assertion'); /*! * Assertion Error */ exports.AssertionError = require('./chai/browser/error'); /*! * Utils for plugins (not exported) */ var util = require('./chai/utils'); /** * # .use(function) * * Provides a way to extend the internals of Chai * * @param {Function} * @returns {this} for chaining * @api public */ exports.use = function (fn) { if (!~used.indexOf(fn)) { fn(this, util); used.push(fn); } return this; }; /*! * Core Assertions */ var core = require('./chai/core/assertions'); exports.use(core); /*! * Expect interface */ var expect = require('./chai/interface/expect'); exports.use(expect); /*! * Should interface */ var should = require('./chai/interface/should'); exports.use(should); /*! * Assert interface */ var assert = require('./chai/interface/assert'); exports.use(assert); }); // module: chai.js require.register("chai/assertion.js", function(module, exports, require){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ /*! * Module dependencies. */ var AssertionError = require('./browser/error') , util = require('./utils') , flag = util.flag; /*! * Module export. */ module.exports = Assertion; /*! * Assertion Constructor * * Creates object for chaining. * * @api private */ function Assertion (obj, msg, stack) { flag(this, 'ssfi', stack || arguments.callee); flag(this, 'object', obj); flag(this, 'message', msg); } /*! * ### Assertion.includeStack * * User configurable property, influences whether stack trace * is included in Assertion error message. Default of false * suppresses stack trace in the error message * * Assertion.includeStack = true; // enable stack on error * * @api public */ Assertion.includeStack = false; Assertion.addProperty = function (name, fn) { util.addProperty(this.prototype, name, fn); }; Assertion.addMethod = function (name, fn) { util.addMethod(this.prototype, name, fn); }; Assertion.addChainableMethod = function (name, fn, chainingBehavior) { util.addChainableMethod(this.prototype, name, fn, chainingBehavior); }; Assertion.overwriteProperty = function (name, fn) { util.overwriteProperty(this.prototype, name, fn); }; Assertion.overwriteMethod = function (name, fn) { util.overwriteMethod(this.prototype, name, fn); }; /*! * ### .assert(expression, message, negateMessage, expected, actual) * * 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} message to display if fails * @param {String} 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` * @api private */ Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual) { var ok = util.test(this, arguments); if (!ok) { var msg = util.getMessage(this, arguments) , actual = util.getActual(this, arguments); throw new AssertionError({ message: msg , actual: actual , expected: expected , stackStartFunction: (Assertion.includeStack) ? this.assert : flag(this, 'ssfi') }); } }; /*! * ### ._obj * * Quick reference to stored `actual` value for plugin developers. * * @api private */ Object.defineProperty(Assertion.prototype, '_obj', { get: function () { return flag(this, 'object'); } , set: function (val) { flag(this, 'object', val); } }); }); // module: chai/assertion.js require.register("chai/browser/error.js", function(module, exports, require){ /*! * chai * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ module.exports = AssertionError; function AssertionError (options) { options = options || {}; this.message = options.message; this.actual = options.actual; this.expected = options.expected; this.operator = options.operator; if (options.stackStartFunction && Error.captureStackTrace) { var stackStartFunction = options.stackStartFunction; Error.captureStackTrace(this, stackStartFunction); } } AssertionError.prototype = Object.create(Error.prototype); AssertionError.prototype.name = 'AssertionError'; AssertionError.prototype.constructor = AssertionError; AssertionError.prototype.toString = function() { return this.message; }; }); // module: chai/browser/error.js require.register("chai/core/assertions.js", function(module, exports, require){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ module.exports = function (chai, _) { var Assertion = chai.Assertion , toString = Object.prototype.toString , flag = _.flag; /** * ### Language Chains * * The following are provide as chainable getters to * improve the readability of your assertions. They * do not provide an testing capability unless they * have been overwritten by a plugin. * * **Chains** * * - to * - be * - been * - is * - that * - and * - have * - with * * @name language chains * @api public */ [ 'to', 'be', 'been' , 'is', 'and', 'have' , 'with', 'that' ].forEach(function (chain) { Assertion.addProperty(chain, function () { return this; }); }); /** * ### .not * * Negates any of assertions following in the chain. * * expect(foo).to.not.equal('bar'); * expect(goodFn).to.not.throw(Error); * expect({ foo: 'baz' }).to.have.property('foo') * .and.not.equal('bar'); * * @name not * @api public */ Assertion.addProperty('not', function () { flag(this, 'negate', true); }); /** * ### .deep * * Sets the `deep` flag, later used by the `equal` and * `property` assertions. * * expect(foo).to.deep.equal({ bar: 'baz' }); * expect({ foo: { bar: { baz: 'quux' } } }) * .to.have.deep.property('foo.bar.baz', 'quux'); * * @name deep * @api public */ Assertion.addProperty('deep', function () { flag(this, 'deep', true); }); /** * ### .a(type) * * The `a` and `an` assertions are aliases that can be * used either as language chains or to assert a value's * type (as revealed by `Object.prototype.toString`). * * // 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'); * * // language chain * expect(foo).to.be.an.instanceof(Foo); * * @name a * @alias an * @param {String} type * @param {String} message _optional_ * @api public */ function an(type, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , klassStart = type.charAt(0).toUpperCase() , klass = klassStart + type.slice(1) , article = ~[ 'A', 'E', 'I', 'O', 'U' ].indexOf(klassStart) ? 'an ' : 'a '; this.assert( '[object ' + klass + ']' === toString.call(obj) , 'expected #{this} to be ' + article + type , 'expected #{this} not to be ' + article + type ); } Assertion.addChainableMethod('an', an); Assertion.addChainableMethod('a', an); /** * ### .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. * * 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 * @param {Object|String|Number} obj * @param {String} message _optional_ * @api public */ function includeChainingBehavior () { flag(this, 'contains', true); } function include (val, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') this.assert( ~obj.indexOf(val) , 'expected #{this} to include ' + _.inspect(val) , 'expected #{this} to not include ' + _.inspect(val)); } Assertion.addChainableMethod('include', include, includeChainingBehavior); Assertion.addChainableMethod('contain', include, includeChainingBehavior); /** * ### .ok * * Asserts that the target is truthy. * * expect('everthing').to.be.ok; * expect(1).to.be.ok; * expect(false).to.not.be.ok; * expect(undefined).to.not.be.ok; * expect(null).to.not.be.ok; * * @name ok * @api public */ Assertion.addProperty('ok', function () { this.assert( flag(this, 'object') , 'expected #{this} to be truthy' , 'expected #{this} to be falsy'); }); /** * ### .true * * Asserts that the target is `true`. * * expect(true).to.be.true; * expect(1).to.not.be.true; * * @name true * @api public */ Assertion.addProperty('true', function () { this.assert( true === flag(this, 'object') , 'expected #{this} to be true' , 'expected #{this} to be false' , this.negate ? false : true ); }); /** * ### .false * * Asserts that the target is `false`. * * expect(false).to.be.false; * expect(0).to.not.be.false; * * @name false * @api public */ Assertion.addProperty('false', function () { this.assert( false === flag(this, 'object') , 'expected #{this} to be false' , 'expected #{this} to be true' , this.negate ? true : false ); }); /** * ### .null * * Asserts that the target is `null`. * * expect(null).to.be.null; * expect(undefined).not.to.be.null; * * @name null * @api public */ Assertion.addProperty('null', function () { this.assert( null === flag(this, 'object') , 'expected #{this} to be null' , 'expected #{this} not to be null' ); }); /** * ### .undefined * * Asserts that the target is `undefined`. * * expect(undefined).to.be.undefined; * expect(null).to.not.be.undefined; * * @name undefined * @api public */ Assertion.addProperty('undefined', function () { this.assert( undefined === flag(this, 'object') , 'expected #{this} to be undefined' , 'expected #{this} not to be undefined' ); }); /** * ### .exist * * Asserts that the target is neither `null` nor `undefined`. * * var foo = 'hi' * , bar = null * , baz; * * expect(foo).to.exist; * expect(bar).to.not.exist; * expect(baz).to.not.exist; * * @name exist * @api public */ Assertion.addProperty('exist', function () { this.assert( null != flag(this, 'object') , 'expected #{this} to exist' , 'expected #{this} to not exist' ); }); /** * ### .empty * * Asserts that the target's length is `0`. For arrays, it checks * the `length` property. For objects, it gets the count of * enumerable keys. * * expect([]).to.be.empty; * expect('').to.be.empty; * expect({}).to.be.empty; * * @name empty * @api public */ Assertion.addProperty('empty', function () { var obj = flag(this, 'object') , expected = obj; if (Array.isArray(obj) || 'string' === typeof object) { expected = obj.length; } else if (typeof obj === 'object') { expected = Object.keys(obj).length; } this.assert( !expected , 'expected #{this} to be empty' , 'expected #{this} not to be empty' ); }); /** * ### .arguments * * Asserts that the target is an arguments object. * * function test () { * expect(arguments).to.be.arguments; * } * * @name arguments * @alias Arguments * @api public */ function checkArguments () { var obj = flag(this, 'object') , type = Object.prototype.toString.call(obj); this.assert( '[object Arguments]' === type , 'expected #{this} to be arguments but got ' + type , 'expected #{this} to not be arguments' ); } Assertion.addProperty('arguments', checkArguments); Assertion.addProperty('Arguments', checkArguments); /** * ### .equal(value) * * Asserts that the target is strictly equal (`===`) to `value`. * Alternately, if the `deep` flag is set, asserts that * the target is deeply equal to `value`. * * expect('hello').to.equal('hello'); * expect(42).to.equal(42); * expect(1).to.not.equal(true); * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' }); * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); * * @name equal * @alias equals * @alias eq * @alias deep.equal * @param {Mixed} value * @param {String} message _optional_ * @api public */ function assertEqual (val, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'deep')) { return this.eql(val); } else { this.assert( val === obj , 'expected #{this} to equal #{exp}' , 'expected #{this} to not equal #{exp}' , val ); } } Assertion.addMethod('equal', assertEqual); Assertion.addMethod('equals', assertEqual); Assertion.addMethod('eq', assertEqual); /** * ### .eql(value) * * Asserts that the target is deeply equal to `value`. * * expect({ foo: 'bar' }).to.eql({ foo: 'bar' }); * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]); * * @name eql * @param {Mixed} value * @param {String} message _optional_ * @api public */ Assertion.addMethod('eql', function (obj, msg) { if (msg) flag(this, 'message', msg); this.assert( _.eql(obj, flag(this, 'object')) , 'expected #{this} to deeply equal #{exp}' , 'expected #{this} to not deeply equal #{exp}' , obj ); }); /** * ### .above(value) * * Asserts that the target is greater than `value`. * * expect(10).to.be.above(5); * * Can also be used in conjunction with `length` to * assert a minimum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.above(2); * expect([ 1, 2, 3 ]).to.have.length.above(2); * * @name above * @alias gt * @alias greaterThan * @param {Number} value * @param {String} message _optional_ * @api public */ function assertAbove (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len > n , 'expected #{this} to have a length above #{exp} but got #{act}' , 'expected #{this} to not have a length above #{exp}' , n , len ); } else { this.assert( obj > n , 'expected #{this} to be above ' + n , 'expected #{this} to be below ' + n ); } } Assertion.addMethod('above', assertAbove); Assertion.addMethod('gt', assertAbove); Assertion.addMethod('greaterThan', assertAbove); /** * ### .below(value) * * Asserts that the target is less than `value`. * * expect(5).to.be.below(10); * * Can also be used in conjunction with `length` to * assert a maximum length. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.below(4); * expect([ 1, 2, 3 ]).to.have.length.below(4); * * @name below * @alias lt * @alias lessThan * @param {Number} value * @param {String} message _optional_ * @api public */ function assertBelow (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len < n , 'expected #{this} to have a length below #{exp} but got #{act}' , 'expected #{this} to not have a length below #{exp}' , n , len ); } else { this.assert( obj < n , 'expected #{this} to be below ' + n , 'expected #{this} to be above ' + n ); } } Assertion.addMethod('below', assertBelow); Assertion.addMethod('lt', assertBelow); Assertion.addMethod('lessThan', assertBelow); /** * ### .within(start, finish) * * Asserts that the target is within a range. * * expect(7).to.be.within(5,10); * * Can also be used in conjunction with `length` to * assert a length range. The benefit being a * more informative error message than if the length * was supplied directly. * * expect('foo').to.have.length.within(2,4); * expect([ 1, 2, 3 ]).to.have.length.within(2,4); * * @name within * @param {Number} start lowerbound inclusive * @param {Number} finish upperbound inclusive * @param {String} message _optional_ * @api public */ Assertion.addMethod('within', function (start, finish, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , range = start + '..' + finish; if (flag(this, 'doLength')) { new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len >= start && len <= finish , 'expected #{this} to have a length within ' + range , 'expected #{this} to not have a length within ' + range ); } else { this.assert( obj >= start && obj <= finish , 'expected #{this} to be within ' + range , 'expected #{this} to not be within ' + range ); } }); /** * ### .instanceof(constructor) * * Asserts that the target is an instance of `constructor`. * * var Tea = function (name) { this.name = name; } * , Chai = new Tea('chai'); * * expect(Chai).to.be.an.instanceof(Tea); * expect([ 1, 2, 3 ]).to.be.instanceof(Array); * * @name instanceof * @param {Constructor} constructor * @param {String} message _optional_ * @alias instanceOf * @api public */ function assertInstanceOf (constructor, msg) { if (msg) flag(this, 'message', msg); var name = _.getName(constructor); this.assert( flag(this, 'object') instanceof constructor , 'expected #{this} to be an instance of ' + name , 'expected #{this} to not be an instance of ' + name ); }; Assertion.addMethod('instanceof', assertInstanceOf); Assertion.addMethod('instanceOf', assertInstanceOf); /** * ### .property(name, [value]) * * Asserts that the target has a property `name`, optionally asserting that * the value of that property is strictly equal to `value`. * If the `deep` flag is set, you can use dot- and bracket-notation for deep * references into objects and arrays. * * // simple referencing * var obj = { foo: 'bar' }; * expect(obj).to.have.property('foo'); * expect(obj).to.have.property('foo', 'bar'); * * // 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` * assertion, or traverse nested arrays. * * var arr = [ * [ 'chai', 'matcha', 'konacha' ] * , [ { tea: 'chai' } * , { tea: 'matcha' } * , { tea: 'konacha' } ] * ]; * * expect(arr).to.have.deep.property('[0][1]', 'matcha'); * expect(arr).to.have.deep.property('[1][2].tea', 'konacha'); * * Furthermore, `property` changes the subject of the assertion * to be the value of that property from the original object. This * permits for further chainable assertions on that property. * * expect(obj).to.have.property('foo') * .that.is.a('string'); * expect(deepObj).to.have.property('green') * .that.is.an('object') * .that.deep.equals({ tea: 'matcha' }); * expect(deepObj).to.have.property('teas') * .that.is.an('array') * .with.deep.property('[2]') * .that.deep.equals({ tea: 'konacha' }); * * @name property * @alias deep.property * @param {String} name * @param {Mixed} value (optional) * @param {String} message _optional_ * @returns value of property for chaining * @api public */ Assertion.addMethod('property', function (name, val, msg) { if (msg) flag(this, 'message', msg); var descriptor = flag(this, 'deep') ? 'deep property ' : 'property ' , negate = flag(this, 'negate') , obj = flag(this, 'object') , value = flag(this, 'deep') ? _.getPathValue(name, obj) : obj[name]; if (negate && undefined !== val) { if (undefined === value) { msg = (msg != null) ? msg + ': ' : ''; throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name)); } } else { this.assert( undefined !== value , 'expected #{this} to have a ' + descriptor + _.inspect(name) , 'expected #{this} to not have ' + descriptor + _.inspect(name)); } if (undefined !== val) { 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 , value ); } flag(this, 'object', value); }); /** * ### .ownProperty(name) * * Asserts that the target has an own property `name`. * * expect('test').to.have.ownProperty('length'); * * @name ownProperty * @alias haveOwnProperty * @param {String} name * @param {String} message _optional_ * @api public */ function assertOwnProperty (name, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( obj.hasOwnProperty(name) , 'expected #{this} to have own property ' + _.inspect(name) , 'expected #{this} to not have own property ' + _.inspect(name) ); } Assertion.addMethod('ownProperty', assertOwnProperty); Assertion.addMethod('haveOwnProperty', assertOwnProperty); /** * ### .length(value) * * Asserts that the target's `length` property has * the expected value. * * expect([ 1, 2, 3]).to.have.length(3); * expect('foobar').to.have.length(6); * * Can also be 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); * * @name length * @alias lengthOf * @param {Number} length * @param {String} message _optional_ * @api public */ function assertLengthChain () { flag(this, 'doLength', true); } function assertLength (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).to.have.property('length'); var len = obj.length; this.assert( len == n , 'expected #{this} to have a length of #{exp} but got #{act}' , 'expected #{this} to not have a length of #{act}' , n , len ); } Assertion.addChainableMethod('length', assertLength, assertLengthChain); Assertion.addMethod('lengthOf', assertLength, assertLengthChain); /** * ### .match(regexp) * * Asserts that the target matches a regular expression. * * expect('foobar').to.match(/^foo/); * * @name match * @param {RegExp} RegularExpression * @param {String} message _optional_ * @api public */ Assertion.addMethod('match', function (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 ); }); /** * ### .string(string) * * Asserts that the string target contains another string. * * expect('foobar').to.have.string('bar'); * * @name string * @param {String} string * @param {String} message _optional_ * @api public */ Assertion.addMethod('string', function (str, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).is.a('string'); this.assert( ~obj.indexOf(str) , 'expected #{this} to contain ' + _.inspect(str) , 'expected #{this} to not contain ' + _.inspect(str) ); }); /** * ### .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. * * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']); * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar'); * * @name keys * @alias key * @param {String...|Array} keys * @api public */ function assertKeys (keys) { var obj = flag(this, 'object') , str , ok = true; keys = keys instanceof Array ? keys : Array.prototype.slice.call(arguments); if (!keys.length) throw new Error('keys required'); var actual = Object.keys(obj) , len = keys.length; // Inclusion ok = keys.every(function(key){ return ~actual.indexOf(key); }); // Strict 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; } else { str = _.inspect(keys[0]); } // Form str = (len > 1 ? 'keys ' : 'key ') + str; // Have / include str = (flag(this, 'contains') ? 'contain ' : 'have ') + str; // Assertion this.assert( ok , 'expected #{this} to ' + str , 'expected #{this} to not ' + str ); } Assertion.addMethod('keys', assertKeys); Assertion.addMethod('key', assertKeys); /** * ### .throw(constructor) * * Asserts that the function target will throw a specific error, or specific type of error * (as determined using `instanceof`), optionally with a RegExp or string inclusion test * for the error's message. * * var err = new ReferenceError('This is a bad function.'); * var fn = function () { throw err; } * expect(fn).to.throw(ReferenceError); * expect(fn).to.throw(Error); * expect(fn).to.throw(/bad function/); * expect(fn).to.not.throw('good function'); * expect(fn).to.throw(ReferenceError, /bad function/); * expect(fn).to.throw(err); * expect(fn).to.not.throw(new RangeError('Out of range.')); * * Please note that when a throw expectation is negated, it will check each * parameter independently, starting with error constructor type. The appropriate way * to check for the existence of a type of error but for a message that does not match * is to use `and`. * * expect(fn).to.throw(ReferenceError) * .and.not.throw(/good function/); * * @name throw * @alias throws * @alias Throw * @param {ErrorConstructor} constructor * @param {String|RegExp} expected error message * @param {String} message _optional_ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types * @api public */ function assertThrows (constructor, errMsg, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj, msg).is.a('function'); var thrown = false , desiredError = null , name = null , thrownError = null; if (arguments.length === 0) { errMsg = null; constructor = null; } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) { errMsg = constructor; constructor = null; } else if (constructor && constructor instanceof Error) { desiredError = constructor; constructor = null; errMsg = null; } else if (typeof constructor === 'function') { name = (new constructor()).name; } else { constructor = null; } try { obj(); } catch (err) { // first, check desired error if (desiredError) { this.assert( err === desiredError , 'expected #{this} to throw ' + _.inspect(desiredError) + ' but ' + _.inspect(err) + ' was thrown' , 'expected #{this} to not throw ' + _.inspect(desiredError) ); return this; } // next, check constructor if (constructor) { this.assert( err instanceof constructor , 'expected #{this} to throw ' + name + ' but ' + _.inspect(err) + ' was thrown' , 'expected #{this} to not throw ' + name + ' but ' + _.inspect(err) + ' was thrown'); if (!errMsg) return this; } // next, check message if (err.message && errMsg && errMsg instanceof RegExp) { this.assert( errMsg.exec(err.message) , 'expected #{this} to throw error matching ' + errMsg + ' but got ' + _.inspect(err.message) , 'expected #{this} to throw error not matching ' + errMsg ); return this; } else if (err.message && errMsg && 'string' === typeof errMsg) { this.assert( ~err.message.indexOf(errMsg) , 'expected #{this} to throw error including #{exp} but got #{act}' , 'expected #{this} to throw error not including #{act}' , errMsg , err.message ); return this; } else { thrown = true; thrownError = err; } } var expectedThrown = name ? name : desiredError ? _.inspect(desiredError) : 'an error'; var actuallyGot = '' if (thrown) { actuallyGot = ' but ' + _.inspect(thrownError) + ' was thrown' } this.assert( thrown === true , 'expected #{this} to throw ' + expectedThrown + actuallyGot , 'expected #{this} to not throw ' + expectedThrown + actuallyGot ); }; Assertion.addMethod('throw', assertThrows); Assertion.addMethod('throws', assertThrows); Assertion.addMethod('Throw', assertThrows); /** * ### .respondTo(method) * * Asserts that the object or class target will respond to a method. * * Klass.prototype.bar = function(){}; * expect(Klass).to.respondTo('bar'); * expect(obj).to.respondTo('bar'); * * To check if a constructor will respond to a static function, * set the `itself` flag. * * Klass.baz = function(){}; * expect(Klass).itself.to.respondTo('baz'); * * @name respondTo * @param {String} method * @param {String} message _optional_ * @api public */ Assertion.addMethod('respondTo', function (method, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , itself = flag(this, 'itself') , context = ('function' === typeof obj && !itself) ? obj.prototype[method] : obj[method]; this.assert( 'function' === typeof context , 'expected #{this} to respond to ' + _.inspect(method) , 'expected #{this} to not respond to ' + _.inspect(method) ); }); /** * ### .itself * * Sets the `itself` flag, later used by the `respondTo` assertion. * * function Foo() {} * Foo.bar = function() {} * Foo.prototype.baz = function() {} * * expect(Foo).itself.to.respondTo('bar'); * expect(Foo).itself.not.to.respondTo('baz'); * * @name itself * @api public */ Assertion.addProperty('itself', function () { flag(this, 'itself', true); }); /** * ### .satisfy(method) * * Asserts that the target passes a given truth test. * * expect(1).to.satisfy(function(num) { return num > 0; }); * * @name satisfy * @param {Function} matcher * @param {String} message _optional_ * @api public */ Assertion.addMethod('satisfy', function (matcher, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( matcher(obj) , 'expected #{this} to satisfy ' + _.inspect(matcher) , 'expected #{this} to not satisfy' + _.inspect(matcher) , this.negate ? false : true , matcher(obj) ); }); /** * ### .closeTo(expected, delta) * * Asserts that the target is equal `expected`, to within a +/- `delta` range. * * expect(1.5).to.be.closeTo(1, 0.5); * * @name closeTo * @param {Number} expected * @param {Number} delta * @param {String} message _optional_ * @api public */ Assertion.addMethod('closeTo', function (expected, delta, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); this.assert( Math.abs(obj - expected) <= delta , 'expected #{this} to be close to ' + expected + ' +/- ' + delta , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta ); }); }; }); // module: chai/core/assertions.js require.register("chai/interface/assert.js", function(module, exports, require){ /*! * chai * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ module.exports = function (chai, util) { /*! * Chai dependencies. */ var Assertion = chai.Assertion , flag = util.flag; /*! * Module export. */ /** * ### assert(expression, message) * * Write your own test expressions. * * assert('foo' !== 'bar', 'foo is not bar'); * assert(Array.isArray([]), 'empty arrays are arrays'); * * @param {Mixed} expression to test for truthiness * @param {String} message to display on error * @name assert * @api public */ var assert = chai.assert = function (express, errmsg) { var test = new Assertion(null); test.assert( express , errmsg , '[ negation message unavailable ]' ); }; /** * ### .fail(actual, expected, [message], [operator]) * * Throw a failure. Node.js `assert` module-compatible. * * @name fail * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @param {String} operator * @api public */ assert.fail = function (actual, expected, message, operator) { throw new chai.AssertionError({ actual: actual , expected: expected , message: message , operator: operator , stackStartFunction: assert.fail }); }; /** * ### .ok(object, [message]) * * Asserts that `object` is truthy. * * assert.ok('everything', 'everything is ok'); * assert.ok(false, 'this will fail'); * * @name ok * @param {Mixed} object to test * @param {String} message * @api public */ assert.ok = function (val, msg) { new Assertion(val, msg).is.ok; }; /** * ### .equal(actual, expected, [message]) * * Asserts non-strict equality (`==`) of `actual` and `expected`. * * assert.equal(3, '3', '== coerces values to strings'); * * @name equal * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.equal = function (act, exp, msg) { var test = new Assertion(act, msg); test.assert( exp == flag(test, 'object') , 'expected #{this} to equal #{exp}' , 'expected #{this} to not equal #{act}' , exp , act ); }; /** * ### .notEqual(actual, expected, [message]) * * Asserts non-strict inequality (`!=`) of `actual` and `expected`. * * assert.notEqual(3, 4, 'these numbers are not equal'); * * @name notEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.notEqual = function (act, exp, msg) { var test = new Assertion(act, msg); test.assert( exp != flag(test, 'object') , 'expected #{this} to not equal #{exp}' , 'expected #{this} to equal #{act}' , exp , act ); }; /** * ### .strictEqual(actual, expected, [message]) * * Asserts strict equality (`===`) of `actual` and `expected`. * * assert.strictEqual(true, true, 'these booleans are strictly equal'); * * @name strictEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.strictEqual = function (act, exp, msg) { new Assertion(act, msg).to.equal(exp); }; /** * ### .notStrictEqual(actual, expected, [message]) * * Asserts strict inequality (`!==`) of `actual` and `expected`. * * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); * * @name notStrictEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.notStrictEqual = function (act, exp, msg) { new Assertion(act, msg).to.not.equal(exp); }; /** * ### .deepEqual(actual, expected, [message]) * * Asserts that `actual` is deeply equal to `expected`. * * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); * * @name deepEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.deepEqual = function (act, exp, msg) { new Assertion(act, msg).to.eql(exp); }; /** * ### .notDeepEqual(actual, expected, [message]) * * Assert that `actual` is not deeply equal to `expected`. * * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); * * @name notDeepEqual * @param {Mixed} actual * @param {Mixed} expected * @param {String} message * @api public */ assert.notDeepEqual = function (act, exp, msg) { new Assertion(act, msg).to.not.eql(exp); }; /** * ### .isTrue(value, [message]) * * Asserts that `value` is true. * * var teaServed = true; * assert.isTrue(teaServed, 'the tea has been served'); * * @name isTrue * @param {Mixed} value * @param {String} message * @api public */ assert.isTrue = function (val, msg) { new Assertion(val, msg).is['true']; }; /** * ### .isFalse(value, [message]) * * Asserts that `value` is false. * * var teaServed = false; * assert.isFalse(teaServed, 'no tea yet? hmm...'); * * @name isFalse * @param {Mixed} value * @param {String} message * @api public */ assert.isFalse = function (val, msg) { new Assertion(val, msg).is['false']; }; /** * ### .isNull(value, [message]) * * Asserts that `value` is null. * * assert.isNull(err, 'there was no error'); * * @name isNull * @param {Mixed} value * @param {String} message * @api public */ assert.isNull = function (val, msg) { new Assertion(val, msg).to.equal(null); }; /** * ### .isNotNull(value, [message]) * * Asserts that `value` is not null. * * var tea = 'tasty chai'; * assert.isNotNull(tea, 'great, time for tea!'); * * @name isNotNull * @param {Mixed} value * @param {String} message * @api public */ assert.isNotNull = function (val, msg) { new Assertion(val, msg).to.not.equal(null); }; /** * ### .isUndefined(value, [message]) * * Asserts that `value` is `undefined`. * * var tea; * assert.isUndefined(tea,