UNPKG

chai

Version:

BDD/TDD assertion library for node.js and the browser. Test framework agnostic.

2,028 lines (1,776 loc) 110 kB
;(function(){ /** * Require the given path. * * @param {String} path * @return {Object} exports * @api public */ function require(path, parent, orig) { var resolved = require.resolve(path); // lookup failed if (null == resolved) { orig = orig || path; parent = parent || 'root'; var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); err.path = orig; err.parent = parent; err.require = true; throw err; } var module = require.modules[resolved]; // perform real require() // by invoking the module's // registered function if (!module.exports) { module.exports = {}; module.client = module.component = true; module.call(this, module.exports, require.relative(resolved), module); } return module.exports; } /** * Registered modules. */ require.modules = {}; /** * Registered aliases. */ require.aliases = {}; /** * Resolve `path`. * * Lookup: * * - PATH/index.js * - PATH.js * - PATH * * @param {String} path * @return {String} path or null * @api private */ require.resolve = function(path) { if (path.charAt(0) === '/') path = path.slice(1); var paths = [ path, path + '.js', path + '.json', path + '/index.js', path + '/index.json' ]; for (var i = 0; i < paths.length; i++) { var path = paths[i]; if (require.modules.hasOwnProperty(path)) return path; if (require.aliases.hasOwnProperty(path)) return require.aliases[path]; } }; /** * Normalize `path` relative to the current path. * * @param {String} curr * @param {String} path * @return {String} * @api private */ require.normalize = function(curr, path) { var segs = []; if ('.' != path.charAt(0)) return path; curr = curr.split('/'); path = path.split('/'); for (var i = 0; i < path.length; ++i) { if ('..' == path[i]) { curr.pop(); } else if ('.' != path[i] && '' != path[i]) { segs.push(path[i]); } } return curr.concat(segs).join('/'); }; /** * Register module at `path` with callback `definition`. * * @param {String} path * @param {Function} definition * @api private */ require.register = function(path, definition) { require.modules[path] = definition; }; /** * Alias a module definition. * * @param {String} from * @param {String} to * @api private */ require.alias = function(from, to) { if (!require.modules.hasOwnProperty(from)) { throw new Error('Failed to alias "' + from + '", it does not exist'); } require.aliases[to] = from; }; /** * Return a require function relative to the `parent` path. * * @param {String} parent * @return {Function} * @api private */ require.relative = function(parent) { var p = require.normalize(parent, '..'); /** * lastIndexOf helper. */ function lastIndexOf(arr, obj) { var i = arr.length; while (i--) { if (arr[i] === obj) return i; } return -1; } /** * The relative require() itself. */ function localRequire(path) { var resolved = localRequire.resolve(path); return require(resolved, parent, path); } /** * Resolve relative to the parent. */ localRequire.resolve = function(path) { var c = path.charAt(0); if ('/' == c) return path.slice(1); if ('.' == c) return require.normalize(p, path); // resolve deps by returning // the dep in the nearest "deps" // directory var segs = parent.split('/'); var i = lastIndexOf(segs, 'deps') + 1; if (!i) i = 0; path = segs.slice(0, i + 1).join('/') + '/deps/' + path; return path; }; /** * Check if module is defined at `path`. */ localRequire.exists = function(path) { return require.modules.hasOwnProperty(localRequire.resolve(path)); }; return localRequire; }; require.register("chaijs-assertion-error/index.js", function(exports, require, module){ /*! * 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("chai/index.js", function(exports, require, module){ module.exports = require('./lib/chai'); }); require.register("chai/lib/chai.js", function(exports, require, module){ /*! * chai * Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ var used = [] , exports = module.exports = {}; /*! * Chai version */ exports.version = '1.7.2'; /*! * Assertion Error */ exports.AssertionError = require('assertion-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; }; /*! * Primary `Assertion` prototype */ var assertion = require('./chai/assertion'); exports.use(assertion); /*! * 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); }); require.register("chai/lib/chai/assertion.js", function(exports, require, module){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ module.exports = function (_chai, util) { /*! * Module dependencies. */ var AssertionError = _chai.AssertionError , flag = util.flag; /*! * Module export. */ _chai.Assertion = 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.showDiff * * User configurable property, influences whether or not * the `showDiff` flag should be included in the thrown * AssertionErrors. `false` will always be `false`; `true` * will be true when the assertion has requested a diff * be shown. * * @api public */ Assertion.showDiff = true; 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, showDiff) { var ok = util.test(this, arguments); if (true !== showDiff) showDiff = false; if (true !== Assertion.showDiff) showDiff = false; if (!ok) { var msg = util.getMessage(this, arguments) , actual = util.getActual(this, arguments); throw new AssertionError(msg, { actual: actual , expected: expected , showDiff: showDiff }, (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); } }); }; }); require.register("chai/lib/chai/core/assertions.js", function(exports, require, module){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2013 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 * - at * - of * - same * * @name language chains * @api public */ [ 'to', 'be', 'been' , 'is', 'and', 'have' , 'with', 'that', 'at' , 'of', 'same' ].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. * * // 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); type = type.toLowerCase(); var obj = flag(this, 'object') , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a '; this.assert( type === _.type(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 , this._obj , true ); } } 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 * @alias eqls * @param {Mixed} value * @param {String} message _optional_ * @api public */ function assertEql(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 , this._obj , true ); } Assertion.addMethod('eql', assertEql); Assertion.addMethod('eqls', assertEql); /** * ### .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 at most ' + n ); } } Assertion.addMethod('above', assertAbove); Assertion.addMethod('gt', assertAbove); Assertion.addMethod('greaterThan', assertAbove); /** * ### .least(value) * * Asserts that the target is greater than or equal to `value`. * * expect(10).to.be.at.least(10); * * 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.of.at.least(2); * expect([ 1, 2, 3 ]).to.have.length.of.at.least(3); * * @name least * @alias gte * @param {Number} value * @param {String} message _optional_ * @api public */ function assertLeast (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 at least #{exp} but got #{act}' , 'expected #{this} to have a length below #{exp}' , n , len ); } else { this.assert( obj >= n , 'expected #{this} to be at least ' + n , 'expected #{this} to be below ' + n ); } } Assertion.addMethod('least', assertLeast); Assertion.addMethod('gte', assertLeast); /** * ### .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 at least ' + n ); } } Assertion.addMethod('below', assertBelow); Assertion.addMethod('lt', assertBelow); Assertion.addMethod('lessThan', assertBelow); /** * ### .most(value) * * Asserts that the target is less than or equal to `value`. * * expect(5).to.be.at.most(5); * * 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.of.at.most(4); * expect([ 1, 2, 3 ]).to.have.length.of.at.most(3); * * @name most * @alias lte * @param {Number} value * @param {String} message _optional_ * @api public */ function assertMost (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 at most #{exp} but got #{act}' , 'expected #{this} to have a length above #{exp}' , n , len ); } else { this.assert( obj <= n , 'expected #{this} to be at most ' + n , 'expected #{this} to be above ' + n ); } } Assertion.addMethod('most', assertMost); Assertion.addMethod('lte', assertMost); /** * ### .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 #{exp} but #{act} was thrown' , 'expected #{this} to not throw #{exp}' , desiredError , err ); return this; } // next, check constructor if (constructor) { this.assert( err instanceof constructor , 'expected #{this} to throw #{exp} but #{act} was thrown' , 'expected #{this} to not throw #{exp} but #{act} was thrown' , name , err ); if (!errMsg) return this; } // next, check message var message = 'object' === _.type(err) && "message" in err ? err.message : '' + err; if ((message != null) && errMsg && errMsg instanceof RegExp) { this.assert( errMsg.exec(message) , 'expected #{this} to throw error matching #{exp} but got #{act}' , 'expected #{this} to throw error not matching #{exp}' , errMsg , message ); return this; } else if ((message != null) && errMsg && 'string' === typeof errMsg) { this.assert( ~message.indexOf(errMsg) , 'expected #{this} to throw error including #{exp} but got #{act}' , 'expected #{this} to throw error not including #{act}' , errMsg , message ); return this; } else { thrown = true; thrownError = err; } } var actuallyGot = '' , expectedThrown = name !== null ? name : desiredError ? '#{exp}' //_.inspect(desiredError) : 'an error'; if (thrown) { actuallyGot = ' but #{act} was thrown' } this.assert( thrown === true , 'expected #{this} to throw ' + expectedThrown + actuallyGot , 'expected #{this} to not throw ' + expectedThrown + actuallyGot , desiredError , thrownError ); }; 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' === _.type(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 ' + _.objDisplay(matcher) , 'expected #{this} to not satisfy' + _.objDisplay(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 ); }); function isSubsetOf(subset, superset) { return subset.every(function(elem) { return superset.indexOf(elem) !== -1; }) } /** * ### .members(set) * * Asserts that the target is a superset of `set`, * or that the target and `set` have the same members. * * expect([1, 2, 3]).to.include.members([3, 2]); * expect([1, 2, 3]).to.not.include.members([3, 2, 8]); * * expect([4, 2]).to.have.members([2, 4]); * expect([5, 2]).to.not.have.members([5, 2, 1]); * * @name members * @param {Array} set * @param {String} message _optional_ * @api public */ Assertion.addMethod('members', function (subset, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object'); new Assertion(obj).to.be.an('array'); new Assertion(subset).to.be.an('array'); if (flag(this, 'contains')) { return this.assert( isSubsetOf(subset, obj) , 'expected #{this} to be a superset of #{act}' , 'expected #{this} to not be a superset of #{act}' , obj , subset ); } this.assert( isSubsetOf(obj, subset) && isSubsetOf(subset, obj) , 'expected #{this} to have the same members as #{act}' , 'expected #{this} to not have the same members as #{act}' , obj , subset ); }); }; }); require.register("chai/lib/chai/interface/assert.js", function(exports, require, module){ /*! * chai * Copyright(c) 2011-2013 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; }; /** * ### .notOk(object, [message]) * * Asserts that `object` is falsy. * * assert.notOk('everything', 'this will fail'); * assert.notOk(false, 'this will pass'); * * @name notOk * @param {Mixed} object to test * @param {String} message * @api public */ assert.notOk = function (val, msg) { new Assertion(val, msg).is.not.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 =