UNPKG

loadjs

Version:

Tiny async loader for modern browsers

1,571 lines (1,433 loc) 341 kB
(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'); },{"./lib/chai":2}],2:[function(require,module,exports){ /*! * chai * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ var used = []; /*! * Chai version */ exports.version = '4.1.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(exports, util); used.push(fn); } return exports; }; /*! * Utility Functions */ exports.util = util; /*! * Configuration */ var config = require('./chai/config'); exports.config = config; /*! * 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); },{"./chai/assertion":3,"./chai/config":4,"./chai/core/assertions":5,"./chai/interface/assert":6,"./chai/interface/expect":7,"./chai/interface/should":8,"./chai/utils":22,"assertion-error":33}],3:[function(require,module,exports){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ var config = require('./config'); 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. * * `Assertion` objects contain metadata in the form of flags. Three flags can * be assigned during instantiation by passing arguments to this constructor: * * - `object`: This flag contains the target of the assertion. For example, in * the assertion `expect(numKittens).to.equal(7);`, the `object` flag will * contain `numKittens` so that the `equal` assertion can reference it when * needed. * * - `message`: This flag contains an optional custom error message to be * prepended to the error message that's generated by the assertion when it * fails. * * - `ssfi`: This flag stands for "start stack function indicator". It * contains a function reference that serves as the starting point for * removing frames from the stack trace of the error that's created by the * assertion when it fails. The goal is to provide a cleaner stack trace to * end users by removing Chai's internal functions. Note that it only works * in environments that support `Error.captureStackTrace`, and only when * `Chai.config.includeStack` hasn't been set to `false`. * * - `lockSsfi`: This flag controls whether or not the given `ssfi` flag * should retain its current value, even as assertions are chained off of * this object. This is usually set to `true` when creating a new assertion * from within another assertion. It's also temporarily set to `true` before * an overwritten assertion gets called by the overwriting assertion. * * @param {Mixed} obj target of the assertion * @param {String} msg (optional) custom error message * @param {Function} ssfi (optional) starting point for removing stack frames * @param {Boolean} lockSsfi (optional) whether or not the ssfi flag is locked * @api private */ function Assertion (obj, msg, ssfi, lockSsfi) { flag(this, 'ssfi', ssfi || Assertion); flag(this, 'lockSsfi', lockSsfi); flag(this, 'object', obj); flag(this, 'message', msg); return util.proxify(this); } Object.defineProperty(Assertion, 'includeStack', { get: function() { console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); return config.includeStack; }, set: function(value) { console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); config.includeStack = value; } }); Object.defineProperty(Assertion, 'showDiff', { get: function() { console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); return config.showDiff; }, set: function(value) { console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); config.showDiff = value; } }); 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); }; Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) { util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior); }; /** * ### .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|Function} message or function that returns message to display if expression fails * @param {String|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); if (false !== showDiff) showDiff = true; if (undefined === expected && undefined === _actual) showDiff = false; if (true !== config.showDiff) showDiff = false; if (!ok) { msg = util.getMessage(this, arguments); var actual = util.getActual(this, arguments); throw new AssertionError(msg, { actual: actual , expected: expected , showDiff: showDiff }, (config.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); } }); }; },{"./config":4}],4:[function(require,module,exports){ module.exports = { /** * ### config.includeStack * * User configurable property, influences whether stack trace * is included in Assertion error message. Default of false * suppresses stack trace in the error message. * * chai.config.includeStack = true; // enable stack on error * * @param {Boolean} * @api public */ includeStack: false, /** * ### config.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. * * @param {Boolean} * @api public */ showDiff: true, /** * ### config.truncateThreshold * * User configurable property, sets length threshold for actual and * 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, /** * ### config.useProxy * * User configurable property, defines if chai will use a Proxy to throw * an error when a non-existent property is read, which protects users * from typos when using property-based assertions. * * Set it to false if you want to disable this feature. * * chai.config.useProxy = false; // disable use of Proxy * * This feature is automatically disabled regardless of this config value * in environments that don't support proxies. * * @param {Boolean} * @api public */ useProxy: true, /** * ### config.proxyExcludedKeys * * User configurable property, defines which properties should be ignored * instead of throwing an error if they do not exist on the assertion. * This is only applied if the environment Chai is running in supports proxies and * if the `useProxy` configuration setting is enabled. * By default, `then` and `inspect` will not throw an error if they do not exist on the * assertion object because the `.inspect` property is read by `util.inspect` (for example, when * using `console.log` on the assertion object) and `.then` is necessary for promise type-checking. * * // By default these keys will not throw an error if they do not exist on the assertion object * chai.config.proxyExcludedKeys = ['then', 'inspect']; * * @param {Array} * @api public */ proxyExcludedKeys: ['then', 'inspect', 'toJSON'] }; },{}],5:[function(require,module,exports){ /*! * chai * http://chaijs.com * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com> * MIT Licensed */ module.exports = function (chai, _) { var Assertion = chai.Assertion , AssertionError = chai.AssertionError , flag = _.flag; /** * ### Language Chains * * The following are provided as chainable getters to improve the readability * of your assertions. * * **Chains** * * - to * - be * - been * - is * - that * - which * - and * - has * - have * - with * - at * - of * - same * - but * - does * * @name language chains * @namespace BDD * @api public */ [ 'to', 'be', 'been' , 'is', 'and', 'has', 'have' , 'with', 'that', 'which', 'at' , 'of', 'same', 'but', 'does' ].forEach(function (chain) { Assertion.addProperty(chain); }); /** * ### .not * * Negates all assertions that follow in the chain. * * expect(function () {}).to.not.throw(); * expect({a: 1}).to.not.have.property('b'); * expect([1, 2]).to.be.an('array').that.does.not.include(3); * * Just because you can negate any assertion with `.not` doesn't mean you * should. With great power comes great responsibility. It's often best to * assert that the one expected output was produced, rather than asserting * that one of countless unexpected outputs wasn't produced. See individual * assertions for specific guidance. * * expect(2).to.equal(2); // Recommended * expect(2).to.not.equal(1); // Not recommended * * @name not * @namespace BDD * @api public */ Assertion.addProperty('not', function () { flag(this, 'negate', true); }); /** * ### .deep * * Causes all `.equal`, `.include`, `.members`, `.keys`, and `.property` * assertions that follow in the chain to use deep equality instead of strict * (`===`) equality. See the `deep-eql` project page for info on the deep * equality algorithm: https://github.com/chaijs/deep-eql. * * // Target object deeply (but not strictly) equals `{a: 1}` * expect({a: 1}).to.deep.equal({a: 1}); * expect({a: 1}).to.not.equal({a: 1}); * * // Target array deeply (but not strictly) includes `{a: 1}` * expect([{a: 1}]).to.deep.include({a: 1}); * expect([{a: 1}]).to.not.include({a: 1}); * * // Target object deeply (but not strictly) includes `x: {a: 1}` * expect({x: {a: 1}}).to.deep.include({x: {a: 1}}); * expect({x: {a: 1}}).to.not.include({x: {a: 1}}); * * // Target array deeply (but not strictly) has member `{a: 1}` * expect([{a: 1}]).to.have.deep.members([{a: 1}]); * expect([{a: 1}]).to.not.have.members([{a: 1}]); * * // Target set deeply (but not strictly) has key `{a: 1}` * expect(new Set([{a: 1}])).to.have.deep.keys([{a: 1}]); * expect(new Set([{a: 1}])).to.not.have.keys([{a: 1}]); * * // Target object deeply (but not strictly) has property `x: {a: 1}` * expect({x: {a: 1}}).to.have.deep.property('x', {a: 1}); * expect({x: {a: 1}}).to.not.have.property('x', {a: 1}); * * @name deep * @namespace BDD * @api public */ Assertion.addProperty('deep', function () { flag(this, 'deep', true); }); /** * ### .nested * * Enables dot- and bracket-notation in all `.property` and `.include` * assertions that follow in the chain. * * expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]'); * expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'}); * * If `.` or `[]` are part of an actual property name, they can be escaped by * adding two backslashes before them. * * expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\.a.\\[b\\]'); * expect({'.a': {'[b]': 'x'}}).to.nested.include({'\\.a.\\[b\\]': 'x'}); * * `.nested` cannot be combined with `.own`. * * @name nested * @namespace BDD * @api public */ Assertion.addProperty('nested', function () { flag(this, 'nested', true); }); /** * ### .own * * Causes all `.property` and `.include` assertions that follow in the chain * to ignore inherited properties. * * Object.prototype.b = 2; * * expect({a: 1}).to.have.own.property('a'); * expect({a: 1}).to.have.property('b').but.not.own.property('b'); * * expect({a: 1}).to.own.include({a: 1}); * expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2}); * * `.own` cannot be combined with `.nested`. * * @name own * @namespace BDD * @api public */ Assertion.addProperty('own', function () { flag(this, 'own', true); }); /** * ### .ordered * * Causes all `.members` assertions that follow in the chain to require that * members be in the same order. * * expect([1, 2]).to.have.ordered.members([1, 2]) * .but.not.have.ordered.members([2, 1]); * * When `.include` and `.ordered` are combined, the ordering begins at the * start of both arrays. * * expect([1, 2, 3]).to.include.ordered.members([1, 2]) * .but.not.include.ordered.members([2, 3]); * * @name ordered * @namespace BDD * @api public */ Assertion.addProperty('ordered', function () { flag(this, 'ordered', true); }); /** * ### .any * * Causes all `.keys` assertions that follow in the chain to only require that * the target have at least one of the given keys. This is the opposite of * `.all`, which requires that the target have all of the given keys. * * expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd'); * * See the `.keys` doc for guidance on when to use `.any` or `.all`. * * @name any * @namespace BDD * @api public */ Assertion.addProperty('any', function () { flag(this, 'any', true); flag(this, 'all', false); }); /** * ### .all * * Causes all `.keys` assertions that follow in the chain to require that the * target have all of the given keys. This is the opposite of `.any`, which * only requires that the target have at least one of the given keys. * * expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); * * Note that `.all` is used by default when neither `.all` nor `.any` are * added earlier in the chain. However, it's often best to add `.all` anyway * because it improves readability. * * See the `.keys` doc for guidance on when to use `.any` or `.all`. * * @name all * @namespace BDD * @api public */ Assertion.addProperty('all', function () { flag(this, 'all', true); flag(this, 'any', false); }); /** * ### .a(type[, msg]) * * Asserts that the target's type is equal to the given string `type`. Types * are case insensitive. See the `type-detect` project page for info on the * type detection algorithm: https://github.com/chaijs/type-detect. * * expect('foo').to.be.a('string'); * expect({a: 1}).to.be.an('object'); * expect(null).to.be.a('null'); * expect(undefined).to.be.an('undefined'); * expect(new Error).to.be.an('error'); * expect(Promise.resolve()).to.be.a('promise'); * expect(new Float32Array).to.be.a('float32array'); * expect(Symbol()).to.be.a('symbol'); * * `.a` supports objects that have a custom type set via `Symbol.toStringTag`. * * var myObj = { * [Symbol.toStringTag]: 'myCustomType' * }; * * expect(myObj).to.be.a('myCustomType').but.not.an('object'); * * It's often best to use `.a` to check a target's type before making more * assertions on the same target. That way, you avoid unexpected behavior from * any assertion that does different things based on the target's type. * * expect([1, 2, 3]).to.be.an('array').that.includes(2); * expect([]).to.be.an('array').that.is.empty; * * Add `.not` earlier in the chain to negate `.a`. However, it's often best to * assert that the target is the expected type, rather than asserting that it * isn't one of many unexpected types. * * expect('foo').to.be.a('string'); // Recommended * expect('foo').to.not.be.an('array'); // Not recommended * * `.a` accepts an optional `msg` argument which is a custom error message to * show when the assertion fails. The message can also be given as the second * argument to `expect`. * * expect(1).to.be.a('string', 'nooo why fail??'); * expect(1, 'nooo why fail??').to.be.a('string'); * * `.a` can also be used as a language chain to improve the readability of * your assertions. * * expect({b: 2}).to.have.a.property('b'); * * The alias `.an` can be used interchangeably with `.a`. * * @name a * @alias an * @param {String} type * @param {String} msg _optional_ * @namespace BDD * @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).toLowerCase() , 'expected #{this} to be ' + article + type , 'expected #{this} not to be ' + article + type ); } Assertion.addChainableMethod('an', an); Assertion.addChainableMethod('a', an); /** * ### .include(val[, msg]) * * When the target is a string, `.include` asserts that the given string `val` * is a substring of the target. * * expect('foobar').to.include('foo'); * * When the target is an array, `.include` asserts that the given `val` is a * member of the target. * * expect([1, 2, 3]).to.include(2); * * When the target is an object, `.include` asserts that the given object * `val`'s properties are a subset of the target's properties. * * expect({a: 1, b: 2, c: 3}).to.include({a: 1, b: 2}); * * When the target is a Set or WeakSet, `.include` asserts that the given `val` is a * member of the target. SameValueZero equality algorithm is used. * * expect(new Set([1, 2])).to.include(2); * * When the target is a Map, `.include` asserts that the given `val` is one of * the values of the target. SameValueZero equality algorithm is used. * * expect(new Map([['a', 1], ['b', 2]])).to.include(2); * * Because `.include` does different things based on the target's type, it's * important to check the target's type before using `.include`. See the `.a` * doc for info on testing a target's type. * * expect([1, 2, 3]).to.be.an('array').that.includes(2); * * By default, strict (`===`) equality is used to compare array members and * object properties. Add `.deep` earlier in the chain to use deep equality * instead (WeakSet targets are not supported). See the `deep-eql` project * page for info on the deep equality algorithm: https://github.com/chaijs/deep-eql. * * // Target array deeply (but not strictly) includes `{a: 1}` * expect([{a: 1}]).to.deep.include({a: 1}); * expect([{a: 1}]).to.not.include({a: 1}); * * // Target object deeply (but not strictly) includes `x: {a: 1}` * expect({x: {a: 1}}).to.deep.include({x: {a: 1}}); * expect({x: {a: 1}}).to.not.include({x: {a: 1}}); * * By default, all of the target's properties are searched when working with * objects. This includes properties that are inherited and/or non-enumerable. * Add `.own` earlier in the chain to exclude the target's inherited * properties from the search. * * Object.prototype.b = 2; * * expect({a: 1}).to.own.include({a: 1}); * expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2}); * * Note that a target object is always only searched for `val`'s own * enumerable properties. * * `.deep` and `.own` can be combined. * * expect({a: {b: 2}}).to.deep.own.include({a: {b: 2}}); * * Add `.nested` earlier in the chain to enable dot- and bracket-notation when * referencing nested properties. * * expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'}); * * If `.` or `[]` are part of an actual property name, they can be escaped by * adding two backslashes before them. * * expect({'.a': {'[b]': 2}}).to.nested.include({'\\.a.\\[b\\]': 2}); * * `.deep` and `.nested` can be combined. * * expect({a: {b: [{c: 3}]}}).to.deep.nested.include({'a.b[0]': {c: 3}}); * * `.own` and `.nested` cannot be combined. * * Add `.not` earlier in the chain to negate `.include`. * * expect('foobar').to.not.include('taco'); * expect([1, 2, 3]).to.not.include(4); * * However, it's dangerous to negate `.include` when the target is an object. * The problem is that it creates uncertain expectations by asserting that the * target object doesn't have all of `val`'s key/value pairs but may or may * not have some of them. It's often best to identify the exact output that's * expected, and then write an assertion that only accepts that exact output. * * When the target object isn't even expected to have `val`'s keys, it's * often best to assert exactly that. * * expect({c: 3}).to.not.have.any.keys('a', 'b'); // Recommended * expect({c: 3}).to.not.include({a: 1, b: 2}); // Not recommended * * When the target object is expected to have `val`'s keys, it's often best to * assert that each of the properties has its expected value, rather than * asserting that each property doesn't have one of many unexpected values. * * expect({a: 3, b: 4}).to.include({a: 3, b: 4}); // Recommended * expect({a: 3, b: 4}).to.not.include({a: 1, b: 2}); // Not recommended * * `.include` accepts an optional `msg` argument which is a custom error * message to show when the assertion fails. The message can also be given as * the second argument to `expect`. * * expect([1, 2, 3]).to.include(4, 'nooo why fail??'); * expect([1, 2, 3], 'nooo why fail??').to.include(4); * * `.include` can also be used as a language chain, causing all `.members` and * `.keys` assertions that follow in the chain to require the target to be a * superset of the expected set, rather than an identical set. Note that * `.members` ignores duplicates in the subset when `.include` is added. * * // Target object's keys are a superset of ['a', 'b'] but not identical * expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b'); * expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b'); * * // Target array is a superset of [1, 2] but not identical * expect([1, 2, 3]).to.include.members([1, 2]); * expect([1, 2, 3]).to.not.have.members([1, 2]); * * // Duplicates in the subset are ignored * expect([1, 2, 3]).to.include.members([1, 2, 2, 2]); * * Note that adding `.any` earlier in the chain causes the `.keys` assertion * to ignore `.include`. * * // Both assertions are identical * expect({a: 1}).to.include.any.keys('a', 'b'); * expect({a: 1}).to.have.any.keys('a', 'b'); * * The aliases `.includes`, `.contain`, and `.contains` can be used * interchangeably with `.include`. * * @name include * @alias contain * @alias includes * @alias contains * @param {Mixed} val * @param {String} msg _optional_ * @namespace BDD * @api public */ function SameValueZero(a, b) { return (_.isNaN(a) && _.isNaN(b)) || a === b; } function includeChainingBehavior () { flag(this, 'contains', true); } function include (val, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , objType = _.type(obj).toLowerCase() , flagMsg = flag(this, 'message') , negate = flag(this, 'negate') , ssfi = flag(this, 'ssfi') , isDeep = flag(this, 'deep') , descriptor = isDeep ? 'deep ' : ''; flagMsg = flagMsg ? flagMsg + ': ' : ''; var included = false; switch (objType) { case 'string': included = obj.indexOf(val) !== -1; break; case 'weakset': if (isDeep) { throw new AssertionError( flagMsg + 'unable to use .deep.include with WeakSet', undefined, ssfi ); } included = obj.has(val); break; case 'map': var isEql = isDeep ? _.eql : SameValueZero; obj.forEach(function (item) { included = included || isEql(item, val); }); break; case 'set': if (isDeep) { obj.forEach(function (item) { included = included || _.eql(item, val); }); } else { included = obj.has(val); } break; case 'array': if (isDeep) { included = obj.some(function (item) { return _.eql(item, val); }) } else { included = obj.indexOf(val) !== -1; } break; default: // This block is for asserting a subset of properties in an object. // `_.expectTypes` isn't used here because `.include` should work with // objects with a custom `@@toStringTag`. if (val !== Object(val)) { throw new AssertionError( flagMsg + 'object tested must be an array, a map, an object,' + ' a set, a string, or a weakset, but ' + objType + ' given', undefined, ssfi ); } var props = Object.keys(val) , firstErr = null , numErrs = 0; props.forEach(function (prop) { var propAssertion = new Assertion(obj); _.transferFlags(this, propAssertion, true); flag(propAssertion, 'lockSsfi', true); if (!negate || props.length === 1) { propAssertion.property(prop, val[prop]); return; } try { propAssertion.property(prop, val[prop]); } catch (err) { if (!_.checkError.compatibleConstructor(err, AssertionError)) { throw err; } if (firstErr === null) firstErr = err; numErrs++; } }, this); // When validating .not.include with multiple properties, we only want // to throw an assertion error if all of the properties are included, // in which case we throw the first property assertion error that we // encountered. if (negate && props.length > 1 && numErrs === props.length) { throw firstErr; } return; } // Assert inclusion in collection or substring in a string. this.assert( included , 'expected #{this} to ' + descriptor + 'include ' + _.inspect(val) , 'expected #{this} to not ' + descriptor + '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 loosely (`==`) equal to `true`. However, it's * often best to assert that the target is strictly (`===`) or deeply equal to * its expected value. * * expect(1).to.equal(1); // Recommended * expect(1).to.be.ok; // Not recommended * * expect(true).to.be.true; // Recommended * expect(true).to.be.ok; // Not recommended * * Add `.not` earlier in the chain to negate `.ok`. * * expect(0).to.equal(0); // Recommended * expect(0).to.not.be.ok; // Not recommended * * expect(false).to.be.false; // Recommended * expect(false).to.not.be.ok; // Not recommended * * expect(null).to.be.null; // Recommended * expect(null).to.not.be.ok; // Not recommended * * expect(undefined).to.be.undefined; // Recommended * expect(undefined).to.not.be.ok; // Not recommended * * A custom error message can be given as the second argument to `expect`. * * expect(false, 'nooo why fail??').to.be.ok; * * @name ok * @namespace BDD * @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 strictly (`===`) equal to `true`. * * expect(true).to.be.true; * * Add `.not` earlier in the chain to negate `.true`. However, it's often best * to assert that the target is equal to its expected value, rather than not * equal to `true`. * * expect(false).to.be.false; // Recommended * expect(false).to.not.be.true; // Not recommended * * expect(1).to.equal(1); // Recommended * expect(1).to.not.be.true; // Not recommended * * A custom error message can be given as the second argument to `expect`. * * expect(false, 'nooo why fail??').to.be.true; * * @name true * @namespace BDD * @api public */ Assertion.addProperty('true', function () { this.assert( true === flag(this, 'object') , 'expected #{this} to be true' , 'expected #{this} to be false' , flag(this, 'negate') ? false : true ); }); /** * ### .false * * Asserts that the target is strictly (`===`) equal to `false`. * * expect(false).to.be.false; * * Add `.not` earlier in the chain to negate `.false`. However, it's often * best to assert that the target is equal to its expected value, rather than * not equal to `false`. * * expect(true).to.be.true; // Recommended * expect(true).to.not.be.false; // Not recommended * * expect(1).to.equal(1); // Recommended * expect(1).to.not.be.false; // Not recommended * * A custom error message can be given as the second argument to `expect`. * * expect(true, 'nooo why fail??').to.be.false; * * @name false * @namespace BDD * @api public */ Assertion.addProperty('false', function () { this.assert( false === flag(this, 'object') , 'expected #{this} to be false' , 'expected #{this} to be true' , flag(this, 'negate') ? true : false ); }); /** * ### .null * * Asserts that the target is strictly (`===`) equal to `null`. * * expect(null).to.be.null; * * Add `.not` earlier in the chain to negate `.null`. However, it's often best * to assert that the target is equal to its expected value, rather than not * equal to `null`. * * expect(1).to.equal(1); // Recommended * expect(1).to.not.be.null; // Not recommended * * A custom error message can be given as the second argument to `expect`. * * expect(42, 'nooo why fail??').to.be.null; * * @name null * @namespace BDD * @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 strictly (`===`) equal to `undefined`. * * expect(undefined).to.be.undefined; * * Add `.not` earlier in the chain to negate `.undefined`. However, it's often * best to assert that the target is equal to its expected value, rather than * not equal to `undefined`. * * expect(1).to.equal(1); // Recommended * expect(1).to.not.be.undefined; // Not recommended * * A custom error message can be given as the second argument to `expect`. * * expect(42, 'nooo why fail??').to.be.undefined; * * @name undefined * @namespace BDD * @api public */ Assertion.addProperty('undefined', function () { this.assert( undefined === flag(this, 'object') , 'expected #{this} to be undefined' , 'expected #{this} not to be undefined' ); }); /** * ### .NaN * * Asserts that the target is exactly `NaN`. * * expect(NaN).to.be.NaN; * * Add `.not` earlier in the chain to negate `.NaN`. However, it's often best * to assert that the target is equal to its expected value, rather than not * equal to `NaN`. * * expect('foo').to.equal('foo'); // Recommended * expect('foo').to.not.be.NaN; // Not recommended * * A custom error message can be given as the second argument to `expect`. * * expect(42, 'nooo why fail??').to.be.NaN; * * @name NaN * @namespace BDD * @api public */ Assertion.addProperty('NaN', function () { this.assert( _.isNaN(flag(this, 'object')) , 'expected #{this} to be NaN' , 'expected #{this} not to be NaN' ); }); /** * ### .exist * * Asserts that the target is not strictly (`===`) equal to either `null` or * `undefined`. However, it's often best to assert that the target is equal to * its expected value. * * expect(1).to.equal(1); // Recommended * expect(1).to.exist; // Not recommended * * expect(0).to.equal(0); // Recommended * expect(0).to.exist; // Not recommended * * Add `.not` earlier in the chain to negate `.exist`. * * expect(null).to.be.null; // Recommended * expect(null).to.not.exist; // Not recommended * * expect(undefined).to.be.undefined; // Recommended * expect(undefined).to.not.exist; // Not recommended * * A custom error message can be given as the second argument to `expect`. * * expect(null, 'nooo why fail??').to.exist; * * @name exist * @namespace BDD * @api public */ Assertion.addProperty('exist', function () { var val = flag(this, 'object'); this.assert( val !== null && val !== undefined , 'expected #{this} to exist' , 'expected #{this} to not exist' ); }); /** * ### .empty * * When the target is a string or array, `.empty` asserts that the target's * `length` property is strictly (`===`) equal to `0`. * * expect([]).to.be.empty; * expect('').to.be.empty; * * When the target is a map or set, `.empty` asserts that the target's `size` * property is strictly equal to `0`. * * expect(new Set()).to.be.empty; * expect(new Map()).to.be.empty; * * When the target is a non-function object, `.empty` asserts that the target * doesn't have any own enumerable properties. Properties with Symbol-based * keys are excluded from the count. * * expect({}).to.be.empty; * * Because `.empty` does different things based on the target's type, it's * important to check the target's type before using `.empty`. See the `.a` * doc for info on testing a target's type. * * expect([]).to.be.an('array').that.is.empty; * * Add `.not` earlier in the chain to negate `.empty`. However, it's often * best to assert that the target contains its expected number of values, * rather than asserting that it's not empty. * * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended * expect([1, 2, 3]).to.not.be.empty; // Not recommended * * expect(new Set([1, 2, 3])).to.have.property('size', 3); // Recommended * expect(new Set([1, 2, 3])).to.not.be.empty; // Not recommended * * expect(Object.keys({a: 1})).to.have.lengthOf(1); // Recommended * expect({a: 1}).to.not.be.empty; // Not recommended * * A custom error message can be given as the second argument to `expect`. * * expect([1, 2, 3], 'nooo why fail??').to.be.empty; * * @name empty * @namespace BDD * @api public */ Assertion.addProperty('empty', function () { var val = flag(this, 'object') , ssfi = flag(this, 'ssfi') , flagMsg = flag(this, 'message') , itemsCount; flagMsg = flagMsg ? flagMsg + ': ' : ''; switch (_.type(val).toLowerCase()) { case 'array': case 'string': itemsCount = val.length; break; case 'map': case 'set': itemsCount = val.size; break; case 'weakmap': case 'weakset': throw new AssertionError( flagMsg + '.empty was passed a weak collection', undefined, ssfi ); case 'function': var msg = flagMsg + '.empty was passed a function ' + _.getName(val); throw new AssertionError(msg.trim(), undefined, ssfi); default: if (val !== Object(val)) { throw new AssertionError( flagMsg + '.empty was passed non-string primitive ' + _.inspect(val), undefined, ssfi ); } itemsCount = Object.keys(val).length; } this.assert( 0 === itemsCount , '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; * } * * test(); * * Add `.not` earlier in the chain to negate `.arguments`. However, it's often * best to assert which type the target is expected to be, rather than * asserting that its not an `arguments` object. * * expect('foo').to.be.a('string'); // Recommended * expect('foo').to.not.be.arguments; // Not recommended * * A custom error message can be given as the second argument to `expect`. * * expect({}, 'nooo why fail??').to.be.arguments; * * The alias `.Arguments` can be used interchangeably with `.arguments`. * * @name arguments * @alias Arguments * @namespace BDD * @api public */ function checkArguments () { var obj = flag(this, 'object') , type = _.type(obj); this.assert( '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(val[, msg]) * * Asserts that the target is strictly (`===`) equal to the given `val`. * * expect(1).to.equal(1); * expect('foo').to.equal('foo'); * * Add `.deep` earlier in the chain to use deep equality instead. See the * `deep-eql` project page for info on the deep equality algorithm: * https://github.com/chaijs/deep-eql. * * // Target object deeply (but not strictly) equals `{a: 1}` * expect({a: 1}).to.deep.equal({a: 1}); * expect({a: 1}).to.not.equal({a: 1}); * * // Target array deeply (but not strictly) equals `[1, 2]` * expect([1, 2]).to.deep.equal([1, 2]); * expect([1, 2]).to.not.equal([1, 2]); * * Add `.not` earlier in the chain to negate `.equal`. However, it's often * best to assert that the target is equal to its expected value, rather than * not equal to one of countless unexpected values. * * expect(1).to.equal(1); // Recommended * expect(1).to.not.equal(2); // Not recommended * * `.equal` accepts an optional `msg` argument which is a custom error message * to show when the assertion fails. The message can also be given as the * second argument to `expect`. * * expect(1).to.equal(2, 'nooo why fail??'); * expect(1, 'nooo why fail??').to.equal(2); * * The aliases `.equals` and `eq` can be used interchangeably with `.equal`. * * @name equal * @alias equals * @alias eq * @param {Mixed} val * @param {String} msg _optional_ * @namespace BDD * @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(obj[, msg]) * * Asserts that the target is deeply equal to the given `obj`. See the * `deep-eql` project page for info on the deep equality algorithm: * https://github.com/chaijs/deep-eql. * * // Target object is deeply (but not strictly) equal to {a: 1} * expect({a: 1}).to.eql({a: 1}).but.not.equal({a: 1}); * * // Target array is deeply (but not strictly) equal to [1, 2] * expect([1, 2]).to.eql([1, 2]).but.not.equal([1, 2]); * * Add `.not` earlier in the chain to negate `.eql`. However, it's often best * to assert that the target is deeply equal to its expected value, rather * than not deeply equal to one of countless unexpected values. * * expect({a: 1}).to.eql({a: 1}); // Recommended * expect({a: 1}).to.not.eql({b: 2}); // Not recommended * * `.eql` accepts an optional `msg` argument which is a custom error message * to show when the assertion fails. The message can also be given as the * second argument to `expect`. * * expect({a: 1}).to.eql({b: 2}, 'nooo why fail??'); * expect({a: 1}, 'nooo why fail??').to.eql({b: 2}); * * The alias `.eqls` can be used interchangeably with `.eql`. * * The `.deep.equal` assertion is almost identical to `.eql` but with one * difference: `.deep.equal` causes deep equality comparisons to also be used * for any other assertions that follow in the chain. * * @name eql * @alias eqls * @param {Mixed} obj * @param {String} msg _optional_ * @namespace BDD * @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(n[, msg]) * * Asserts that the target is a number or a date greater than the given number or date `n` respectively. * However, it's often best to assert that the target is equal to its expected * value. * * expect(2).to.equal(2); // Recommended * expect(2).to.be.above(1); // Not recommended * * Add `.lengthOf` earlier in the chain to assert that the value of the * target's `length` property is greater than the given number `n`. * * expect('foo').to.have.lengthOf(3); // Recommended * expect('foo').to.have.lengthOf.above(2); // Not recommended * * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended * expect([1, 2, 3]).to.have.lengthOf.above(2); // Not recommended * * Add `.not` earlier in the chain to negate `.above`. * * expect(2).to.equal(2); // Recommended * expect(1).to.not.be.above(2); // Not recommended * * `.above` accepts an optional `msg` argument which is a custom error message * to show when the assertion fails. The message can also be given as the * second argument to `expect`. * * expect(1).to.be.above(2, 'nooo why fail??'); * expect(1, 'nooo why fail??').to.be.above(2); * * The aliases `.gt` and `.greaterThan` can be used interchangeably with * `.above`. * * @name above * @alias gt * @alias greaterThan * @param {Number} n * @param {String} msg _optional_ * @namespace BDD * @api public */ function assertAbove (n, msg) { if (msg) flag(this, 'message', msg); var obj = flag(this, 'object') , doLength = flag(this, 'doLength') , flagMsg = flag(this, 'message') , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '') , ssfi = flag(this, 'ssfi') , objType = _.type(obj).toLowerCase() , nType = _.type(n).toLowerCase() , shouldThrow = true; if (doLength) { new Assertion(obj, flagMsg, ssfi, true).to.have.property('length'); } if (!doLength && (objType === 'date' && nType !== 'date')) { errorMessage = msgPrefix + 'the argument to above must be a date'; } else if (nType !== 'number' && (doLength || objType === 'number')) { errorMessage = msgPrefix + 'the argument to above must be a number'; } else if (!doLength && (objType !== 'date' && objType !== 'number')) { var printObj = (objType === 'string') ? "'" + obj + "'" : obj; errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date'; } else { shouldThrow = false; } if (shouldThrow) { throw new AssertionError(errorMessage, undefined, ssfi); } if (doLength) { 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 #{exp}' , 'expected #{this} to be at most #{exp}' , n ); } } Assertion.addMethod('above', assertAbove); Assertion.addMethod('gt', assertAbove); Assertion.addMethod('greaterThan', assertAbove); /** * ### .least(n[, msg]) * * Asserts that the target is a number or a date greater than or equal to the given * number or date `n` respectively. However, it's often best to assert that the target is equal to * its expected value. * * expect(2).to.equal(2); // Recommended * expect(2).to.be.at.least(1); // Not recommended * expect(2).to.be.at.least(2); // Not recommended * * Add `.lengthOf` earlier in the chain to assert that the value of the * target's `length` property is greater than or equal to the given number * `n`. * * expect('foo').to.have.lengthOf(3); // Recommended * expect('foo').to.have.lengthOf.at.least(2); // Not recommended * * expect([1, 2, 3]).to.have.lengthOf(3); // Recommended * expect([1, 2, 3]).to.have.lengthOf.at.least(2); // Not recommended * * Add `.not` earlier in the chain to n