Best JavaScript code snippet using chai
assertions.js
Source:assertions.js  
1/*!2 * chai3 * http://chaijs.com4 * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>5 * MIT Licensed6 */7module.exports = function (chai, _) {8  var Assertion = chai.Assertion9    , toString = Object.prototype.toString10    , flag = _.flag;11  /**12   * ### Language Chains13   *14   * The following are provided as chainable getters to15   * improve the readability of your assertions. They16   * do not provide an testing capability unless they17   * have been overwritten by a plugin.18   *19   * **Chains**20   *21   * - to22   * - be23   * - been24   * - is25   * - that26   * - and27   * - has28   * - have29   * - with30   * - at31   * - of32   * - same33   *34   * @name language chains35   * @api public36   */37  [ 'to', 'be', 'been'38  , 'is', 'and', 'has', 'have'39  , 'with', 'that', 'at'40  , 'of', 'same' ].forEach(function (chain) {41    Assertion.addProperty(chain, function () {42      return this;43    });44  });45  /**46   * ### .not47   *48   * Negates any of assertions following in the chain.49   *50   *     expect(foo).to.not.equal('bar');51   *     expect(goodFn).to.not.throw(Error);52   *     expect({ foo: 'baz' }).to.have.property('foo')53   *       .and.not.equal('bar');54   *55   * @name not56   * @api public57   */58  Assertion.addProperty('not', function () {59    flag(this, 'negate', true);60  });61  /**62   * ### .deep63   *64   * Sets the `deep` flag, later used by the `equal` and65   * `property` assertions.66   *67   *     expect(foo).to.deep.equal({ bar: 'baz' });68   *     expect({ foo: { bar: { baz: 'quux' } } })69   *       .to.have.deep.property('foo.bar.baz', 'quux');70   *71   * @name deep72   * @api public73   */74  Assertion.addProperty('deep', function () {75    flag(this, 'deep', true);76  });77  /**78   * ### .a(type)79   *80   * The `a` and `an` assertions are aliases that can be81   * used either as language chains or to assert a value's82   * type.83   *84   *     // typeof85   *     expect('test').to.be.a('string');86   *     expect({ foo: 'bar' }).to.be.an('object');87   *     expect(null).to.be.a('null');88   *     expect(undefined).to.be.an('undefined');89   *90   *     // language chain91   *     expect(foo).to.be.an.instanceof(Foo);92   *93   * @name a94   * @alias an95   * @param {String} type96   * @param {String} message _optional_97   * @api public98   */99  function an (type, msg) {100    if (msg) flag(this, 'message', msg);101    type = type.toLowerCase();102    var obj = flag(this, 'object')103      , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';104    this.assert(105        type === _.type(obj)106      , 'expected #{this} to be ' + article + type107      , 'expected #{this} not to be ' + article + type108    );109  }110  Assertion.addChainableMethod('an', an);111  Assertion.addChainableMethod('a', an);112  /**113   * ### .include(value)114   *115   * The `include` and `contain` assertions can be used as either property116   * based language chains or as methods to assert the inclusion of an object117   * in an array or a substring in a string. When used as language chains,118   * they toggle the `contain` flag for the `keys` assertion.119   *120   *     expect([1,2,3]).to.include(2);121   *     expect('foobar').to.contain('foo');122   *     expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');123   *124   * @name include125   * @alias contain126   * @param {Object|String|Number} obj127   * @param {String} message _optional_128   * @api public129   */130  function includeChainingBehavior () {131    flag(this, 'contains', true);132  }133  function include (val, msg) {134    if (msg) flag(this, 'message', msg);135    var obj = flag(this, 'object');136    if (_.type(val) === 'object') {137      if (!flag(this, 'negate')) {138        for (var k in val) new Assertion(obj).property(k, val[k]);139        return;140      }141      var subset = {}142      for (var k in val) subset[k] = obj[k]143      var expected = _.eql(subset, val);144    } else {145      var expected = obj && ~obj.indexOf(val)146    }147    this.assert(148        expected149      , 'expected #{this} to include ' + _.inspect(val)150      , 'expected #{this} to not include ' + _.inspect(val));151  }152  Assertion.addChainableMethod('include', include, includeChainingBehavior);153  Assertion.addChainableMethod('contain', include, includeChainingBehavior);154  /**155   * ### .ok156   *157   * Asserts that the target is truthy.158   *159   *     expect('everthing').to.be.ok;160   *     expect(1).to.be.ok;161   *     expect(false).to.not.be.ok;162   *     expect(undefined).to.not.be.ok;163   *     expect(null).to.not.be.ok;164   *165   * @name ok166   * @api public167   */168  Assertion.addProperty('ok', function () {169    this.assert(170        flag(this, 'object')171      , 'expected #{this} to be truthy'172      , 'expected #{this} to be falsy');173  });174  /**175   * ### .true176   *177   * Asserts that the target is `true`.178   *179   *     expect(true).to.be.true;180   *     expect(1).to.not.be.true;181   *182   * @name true183   * @api public184   */185  Assertion.addProperty('true', function () {186    this.assert(187        true === flag(this, 'object')188      , 'expected #{this} to be true'189      , 'expected #{this} to be false'190      , this.negate ? false : true191    );192  });193  /**194   * ### .false195   *196   * Asserts that the target is `false`.197   *198   *     expect(false).to.be.false;199   *     expect(0).to.not.be.false;200   *201   * @name false202   * @api public203   */204  Assertion.addProperty('false', function () {205    this.assert(206        false === flag(this, 'object')207      , 'expected #{this} to be false'208      , 'expected #{this} to be true'209      , this.negate ? true : false210    );211  });212  /**213   * ### .null214   *215   * Asserts that the target is `null`.216   *217   *     expect(null).to.be.null;218   *     expect(undefined).not.to.be.null;219   *220   * @name null221   * @api public222   */223  Assertion.addProperty('null', function () {224    this.assert(225        null === flag(this, 'object')226      , 'expected #{this} to be null'227      , 'expected #{this} not to be null'228    );229  });230  /**231   * ### .undefined232   *233   * Asserts that the target is `undefined`.234   *235   *     expect(undefined).to.be.undefined;236   *     expect(null).to.not.be.undefined;237   *238   * @name undefined239   * @api public240   */241  Assertion.addProperty('undefined', function () {242    this.assert(243        undefined === flag(this, 'object')244      , 'expected #{this} to be undefined'245      , 'expected #{this} not to be undefined'246    );247  });248  /**249   * ### .exist250   *251   * Asserts that the target is neither `null` nor `undefined`.252   *253   *     var foo = 'hi'254   *       , bar = null255   *       , baz;256   *257   *     expect(foo).to.exist;258   *     expect(bar).to.not.exist;259   *     expect(baz).to.not.exist;260   *261   * @name exist262   * @api public263   */264  Assertion.addProperty('exist', function () {265    this.assert(266        null != flag(this, 'object')267      , 'expected #{this} to exist'268      , 'expected #{this} to not exist'269    );270  });271  /**272   * ### .empty273   *274   * Asserts that the target's length is `0`. For arrays, it checks275   * the `length` property. For objects, it gets the count of276   * enumerable keys.277   *278   *     expect([]).to.be.empty;279   *     expect('').to.be.empty;280   *     expect({}).to.be.empty;281   *282   * @name empty283   * @api public284   */285  Assertion.addProperty('empty', function () {286    var obj = flag(this, 'object')287      , expected = obj;288    if (Array.isArray(obj) || 'string' === typeof object) {289      expected = obj.length;290    } else if (typeof obj === 'object') {291      expected = Object.keys(obj).length;292    }293    this.assert(294        !expected295      , 'expected #{this} to be empty'296      , 'expected #{this} not to be empty'297    );298  });299  /**300   * ### .arguments301   *302   * Asserts that the target is an arguments object.303   *304   *     function test () {305   *       expect(arguments).to.be.arguments;306   *     }307   *308   * @name arguments309   * @alias Arguments310   * @api public311   */312  function checkArguments () {313    var obj = flag(this, 'object')314      , type = Object.prototype.toString.call(obj);315    this.assert(316        '[object Arguments]' === type317      , 'expected #{this} to be arguments but got ' + type318      , 'expected #{this} to not be arguments'319    );320  }321  Assertion.addProperty('arguments', checkArguments);322  Assertion.addProperty('Arguments', checkArguments);323  /**324   * ### .equal(value)325   *326   * Asserts that the target is strictly equal (`===`) to `value`.327   * Alternately, if the `deep` flag is set, asserts that328   * the target is deeply equal to `value`.329   *330   *     expect('hello').to.equal('hello');331   *     expect(42).to.equal(42);332   *     expect(1).to.not.equal(true);333   *     expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });334   *     expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });335   *336   * @name equal337   * @alias equals338   * @alias eq339   * @alias deep.equal340   * @param {Mixed} value341   * @param {String} message _optional_342   * @api public343   */344  function assertEqual (val, msg) {345    if (msg) flag(this, 'message', msg);346    var obj = flag(this, 'object');347    if (flag(this, 'deep')) {348      return this.eql(val);349    } else {350      this.assert(351          val === obj352        , 'expected #{this} to equal #{exp}'353        , 'expected #{this} to not equal #{exp}'354        , val355        , this._obj356        , true357      );358    }359  }360  Assertion.addMethod('equal', assertEqual);361  Assertion.addMethod('equals', assertEqual);362  Assertion.addMethod('eq', assertEqual);363  /**364   * ### .eql(value)365   *366   * Asserts that the target is deeply equal to `value`.367   *368   *     expect({ foo: 'bar' }).to.eql({ foo: 'bar' });369   *     expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);370   *371   * @name eql372   * @alias eqls373   * @param {Mixed} value374   * @param {String} message _optional_375   * @api public376   */377  function assertEql(obj, msg) {378    if (msg) flag(this, 'message', msg);379    this.assert(380        _.eql(obj, flag(this, 'object'))381      , 'expected #{this} to deeply equal #{exp}'382      , 'expected #{this} to not deeply equal #{exp}'383      , obj384      , this._obj385      , true386    );387  }388  Assertion.addMethod('eql', assertEql);389  Assertion.addMethod('eqls', assertEql);390  /**391   * ### .above(value)392   *393   * Asserts that the target is greater than `value`.394   *395   *     expect(10).to.be.above(5);396   *397   * Can also be used in conjunction with `length` to398   * assert a minimum length. The benefit being a399   * more informative error message than if the length400   * was supplied directly.401   *402   *     expect('foo').to.have.length.above(2);403   *     expect([ 1, 2, 3 ]).to.have.length.above(2);404   *405   * @name above406   * @alias gt407   * @alias greaterThan408   * @param {Number} value409   * @param {String} message _optional_410   * @api public411   */412  function assertAbove (n, msg) {413    if (msg) flag(this, 'message', msg);414    var obj = flag(this, 'object');415    if (flag(this, 'doLength')) {416      new Assertion(obj, msg).to.have.property('length');417      var len = obj.length;418      this.assert(419          len > n420        , 'expected #{this} to have a length above #{exp} but got #{act}'421        , 'expected #{this} to not have a length above #{exp}'422        , n423        , len424      );425    } else {426      this.assert(427          obj > n428        , 'expected #{this} to be above ' + n429        , 'expected #{this} to be at most ' + n430      );431    }432  }433  Assertion.addMethod('above', assertAbove);434  Assertion.addMethod('gt', assertAbove);435  Assertion.addMethod('greaterThan', assertAbove);436  /**437   * ### .least(value)438   *439   * Asserts that the target is greater than or equal to `value`.440   *441   *     expect(10).to.be.at.least(10);442   *443   * Can also be used in conjunction with `length` to444   * assert a minimum length. The benefit being a445   * more informative error message than if the length446   * was supplied directly.447   *448   *     expect('foo').to.have.length.of.at.least(2);449   *     expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);450   *451   * @name least452   * @alias gte453   * @param {Number} value454   * @param {String} message _optional_455   * @api public456   */457  function assertLeast (n, msg) {458    if (msg) flag(this, 'message', msg);459    var obj = flag(this, 'object');460    if (flag(this, 'doLength')) {461      new Assertion(obj, msg).to.have.property('length');462      var len = obj.length;463      this.assert(464          len >= n465        , 'expected #{this} to have a length at least #{exp} but got #{act}'466        , 'expected #{this} to have a length below #{exp}'467        , n468        , len469      );470    } else {471      this.assert(472          obj >= n473        , 'expected #{this} to be at least ' + n474        , 'expected #{this} to be below ' + n475      );476    }477  }478  Assertion.addMethod('least', assertLeast);479  Assertion.addMethod('gte', assertLeast);480  /**481   * ### .below(value)482   *483   * Asserts that the target is less than `value`.484   *485   *     expect(5).to.be.below(10);486   *487   * Can also be used in conjunction with `length` to488   * assert a maximum length. The benefit being a489   * more informative error message than if the length490   * was supplied directly.491   *492   *     expect('foo').to.have.length.below(4);493   *     expect([ 1, 2, 3 ]).to.have.length.below(4);494   *495   * @name below496   * @alias lt497   * @alias lessThan498   * @param {Number} value499   * @param {String} message _optional_500   * @api public501   */502  function assertBelow (n, msg) {503    if (msg) flag(this, 'message', msg);504    var obj = flag(this, 'object');505    if (flag(this, 'doLength')) {506      new Assertion(obj, msg).to.have.property('length');507      var len = obj.length;508      this.assert(509          len < n510        , 'expected #{this} to have a length below #{exp} but got #{act}'511        , 'expected #{this} to not have a length below #{exp}'512        , n513        , len514      );515    } else {516      this.assert(517          obj < n518        , 'expected #{this} to be below ' + n519        , 'expected #{this} to be at least ' + n520      );521    }522  }523  Assertion.addMethod('below', assertBelow);524  Assertion.addMethod('lt', assertBelow);525  Assertion.addMethod('lessThan', assertBelow);526  /**527   * ### .most(value)528   *529   * Asserts that the target is less than or equal to `value`.530   *531   *     expect(5).to.be.at.most(5);532   *533   * Can also be used in conjunction with `length` to534   * assert a maximum length. The benefit being a535   * more informative error message than if the length536   * was supplied directly.537   *538   *     expect('foo').to.have.length.of.at.most(4);539   *     expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);540   *541   * @name most542   * @alias lte543   * @param {Number} value544   * @param {String} message _optional_545   * @api public546   */547  function assertMost (n, msg) {548    if (msg) flag(this, 'message', msg);549    var obj = flag(this, 'object');550    if (flag(this, 'doLength')) {551      new Assertion(obj, msg).to.have.property('length');552      var len = obj.length;553      this.assert(554          len <= n555        , 'expected #{this} to have a length at most #{exp} but got #{act}'556        , 'expected #{this} to have a length above #{exp}'557        , n558        , len559      );560    } else {561      this.assert(562          obj <= n563        , 'expected #{this} to be at most ' + n564        , 'expected #{this} to be above ' + n565      );566    }567  }568  Assertion.addMethod('most', assertMost);569  Assertion.addMethod('lte', assertMost);570  /**571   * ### .within(start, finish)572   *573   * Asserts that the target is within a range.574   *575   *     expect(7).to.be.within(5,10);576   *577   * Can also be used in conjunction with `length` to578   * assert a length range. The benefit being a579   * more informative error message than if the length580   * was supplied directly.581   *582   *     expect('foo').to.have.length.within(2,4);583   *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);584   *585   * @name within586   * @param {Number} start lowerbound inclusive587   * @param {Number} finish upperbound inclusive588   * @param {String} message _optional_589   * @api public590   */591  Assertion.addMethod('within', function (start, finish, msg) {592    if (msg) flag(this, 'message', msg);593    var obj = flag(this, 'object')594      , range = start + '..' + finish;595    if (flag(this, 'doLength')) {596      new Assertion(obj, msg).to.have.property('length');597      var len = obj.length;598      this.assert(599          len >= start && len <= finish600        , 'expected #{this} to have a length within ' + range601        , 'expected #{this} to not have a length within ' + range602      );603    } else {604      this.assert(605          obj >= start && obj <= finish606        , 'expected #{this} to be within ' + range607        , 'expected #{this} to not be within ' + range608      );609    }610  });611  /**612   * ### .instanceof(constructor)613   *614   * Asserts that the target is an instance of `constructor`.615   *616   *     var Tea = function (name) { this.name = name; }617   *       , Chai = new Tea('chai');618   *619   *     expect(Chai).to.be.an.instanceof(Tea);620   *     expect([ 1, 2, 3 ]).to.be.instanceof(Array);621   *622   * @name instanceof623   * @param {Constructor} constructor624   * @param {String} message _optional_625   * @alias instanceOf626   * @api public627   */628  function assertInstanceOf (constructor, msg) {629    if (msg) flag(this, 'message', msg);630    var name = _.getName(constructor);631    this.assert(632        flag(this, 'object') instanceof constructor633      , 'expected #{this} to be an instance of ' + name634      , 'expected #{this} to not be an instance of ' + name635    );636  };637  Assertion.addMethod('instanceof', assertInstanceOf);638  Assertion.addMethod('instanceOf', assertInstanceOf);639  /**640   * ### .property(name, [value])641   *642   * Asserts that the target has a property `name`, optionally asserting that643   * the value of that property is strictly equal to  `value`.644   * If the `deep` flag is set, you can use dot- and bracket-notation for deep645   * references into objects and arrays.646   *647   *     // simple referencing648   *     var obj = { foo: 'bar' };649   *     expect(obj).to.have.property('foo');650   *     expect(obj).to.have.property('foo', 'bar');651   *652   *     // deep referencing653   *     var deepObj = {654   *         green: { tea: 'matcha' }655   *       , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]656   *     };657   *     expect(deepObj).to.have.deep.property('green.tea', 'matcha');658   *     expect(deepObj).to.have.deep.property('teas[1]', 'matcha');659   *     expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');660   *661   * You can also use an array as the starting point of a `deep.property`662   * assertion, or traverse nested arrays.663   *664   *     var arr = [665   *         [ 'chai', 'matcha', 'konacha' ]666   *       , [ { tea: 'chai' }667   *         , { tea: 'matcha' }668   *         , { tea: 'konacha' } ]669   *     ];670   *671   *     expect(arr).to.have.deep.property('[0][1]', 'matcha');672   *     expect(arr).to.have.deep.property('[1][2].tea', 'konacha');673   *674   * Furthermore, `property` changes the subject of the assertion675   * to be the value of that property from the original object. This676   * permits for further chainable assertions on that property.677   *678   *     expect(obj).to.have.property('foo')679   *       .that.is.a('string');680   *     expect(deepObj).to.have.property('green')681   *       .that.is.an('object')682   *       .that.deep.equals({ tea: 'matcha' });683   *     expect(deepObj).to.have.property('teas')684   *       .that.is.an('array')685   *       .with.deep.property('[2]')686   *         .that.deep.equals({ tea: 'konacha' });687   *688   * @name property689   * @alias deep.property690   * @param {String} name691   * @param {Mixed} value (optional)692   * @param {String} message _optional_693   * @returns value of property for chaining694   * @api public695   */696  Assertion.addMethod('property', function (name, val, msg) {697    if (msg) flag(this, 'message', msg);698    var descriptor = flag(this, 'deep') ? 'deep property ' : 'property '699      , negate = flag(this, 'negate')700      , obj = flag(this, 'object')701      , value = flag(this, 'deep')702        ? _.getPathValue(name, obj)703        : obj[name];704    if (negate && undefined !== val) {705      if (undefined === value) {706        msg = (msg != null) ? msg + ': ' : '';707        throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));708      }709    } else {710      this.assert(711          undefined !== value712        , 'expected #{this} to have a ' + descriptor + _.inspect(name)713        , 'expected #{this} to not have ' + descriptor + _.inspect(name));714    }715    if (undefined !== val) {716      this.assert(717          val === value718        , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'719        , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'720        , val721        , value722      );723    }724    flag(this, 'object', value);725  });726  /**727   * ### .ownProperty(name)728   *729   * Asserts that the target has an own property `name`.730   *731   *     expect('test').to.have.ownProperty('length');732   *733   * @name ownProperty734   * @alias haveOwnProperty735   * @param {String} name736   * @param {String} message _optional_737   * @api public738   */739  function assertOwnProperty (name, msg) {740    if (msg) flag(this, 'message', msg);741    var obj = flag(this, 'object');742    this.assert(743        obj.hasOwnProperty(name)744      , 'expected #{this} to have own property ' + _.inspect(name)745      , 'expected #{this} to not have own property ' + _.inspect(name)746    );747  }748  Assertion.addMethod('ownProperty', assertOwnProperty);749  Assertion.addMethod('haveOwnProperty', assertOwnProperty);750  /**751   * ### .length(value)752   *753   * Asserts that the target's `length` property has754   * the expected value.755   *756   *     expect([ 1, 2, 3]).to.have.length(3);757   *     expect('foobar').to.have.length(6);758   *759   * Can also be used as a chain precursor to a value760   * comparison for the length property.761   *762   *     expect('foo').to.have.length.above(2);763   *     expect([ 1, 2, 3 ]).to.have.length.above(2);764   *     expect('foo').to.have.length.below(4);765   *     expect([ 1, 2, 3 ]).to.have.length.below(4);766   *     expect('foo').to.have.length.within(2,4);767   *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);768   *769   * @name length770   * @alias lengthOf771   * @param {Number} length772   * @param {String} message _optional_773   * @api public774   */775  function assertLengthChain () {776    flag(this, 'doLength', true);777  }778  function assertLength (n, msg) {779    if (msg) flag(this, 'message', msg);780    var obj = flag(this, 'object');781    new Assertion(obj, msg).to.have.property('length');782    var len = obj.length;783    this.assert(784        len == n785      , 'expected #{this} to have a length of #{exp} but got #{act}'786      , 'expected #{this} to not have a length of #{act}'787      , n788      , len789    );790  }791  Assertion.addChainableMethod('length', assertLength, assertLengthChain);792  Assertion.addMethod('lengthOf', assertLength, assertLengthChain);793  /**794   * ### .match(regexp)795   *796   * Asserts that the target matches a regular expression.797   *798   *     expect('foobar').to.match(/^foo/);799   *800   * @name match801   * @param {RegExp} RegularExpression802   * @param {String} message _optional_803   * @api public804   */805  Assertion.addMethod('match', function (re, msg) {806    if (msg) flag(this, 'message', msg);807    var obj = flag(this, 'object');808    this.assert(809        re.exec(obj)810      , 'expected #{this} to match ' + re811      , 'expected #{this} not to match ' + re812    );813  });814  /**815   * ### .string(string)816   *817   * Asserts that the string target contains another string.818   *819   *     expect('foobar').to.have.string('bar');820   *821   * @name string822   * @param {String} string823   * @param {String} message _optional_824   * @api public825   */826  Assertion.addMethod('string', function (str, msg) {827    if (msg) flag(this, 'message', msg);828    var obj = flag(this, 'object');829    new Assertion(obj, msg).is.a('string');830    this.assert(831        ~obj.indexOf(str)832      , 'expected #{this} to contain ' + _.inspect(str)833      , 'expected #{this} to not contain ' + _.inspect(str)834    );835  });836  /**837   * ### .keys(key1, [key2], [...])838   *839   * Asserts that the target has exactly the given keys, or840   * asserts the inclusion of some keys when using the841   * `include` or `contain` modifiers.842   *843   *     expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);844   *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');845   *846   * @name keys847   * @alias key848   * @param {String...|Array} keys849   * @api public850   */851  function assertKeys (keys) {852    var obj = flag(this, 'object')853      , str854      , ok = true;855    keys = keys instanceof Array856      ? keys857      : Array.prototype.slice.call(arguments);858    if (!keys.length) throw new Error('keys required');859    var actual = Object.keys(obj)860      , len = keys.length;861    // Inclusion862    ok = keys.every(function(key){863      return ~actual.indexOf(key);864    });865    // Strict866    if (!flag(this, 'negate') && !flag(this, 'contains')) {867      ok = ok && keys.length == actual.length;868    }869    // Key string870    if (len > 1) {871      keys = keys.map(function(key){872        return _.inspect(key);873      });874      var last = keys.pop();875      str = keys.join(', ') + ', and ' + last;876    } else {877      str = _.inspect(keys[0]);878    }879    // Form880    str = (len > 1 ? 'keys ' : 'key ') + str;881    // Have / include882    str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;883    // Assertion884    this.assert(885        ok886      , 'expected #{this} to ' + str887      , 'expected #{this} to not ' + str888    );889  }890  Assertion.addMethod('keys', assertKeys);891  Assertion.addMethod('key', assertKeys);892  /**893   * ### .throw(constructor)894   *895   * Asserts that the function target will throw a specific error, or specific type of error896   * (as determined using `instanceof`), optionally with a RegExp or string inclusion test897   * for the error's message.898   *899   *     var err = new ReferenceError('This is a bad function.');900   *     var fn = function () { throw err; }901   *     expect(fn).to.throw(ReferenceError);902   *     expect(fn).to.throw(Error);903   *     expect(fn).to.throw(/bad function/);904   *     expect(fn).to.not.throw('good function');905   *     expect(fn).to.throw(ReferenceError, /bad function/);906   *     expect(fn).to.throw(err);907   *     expect(fn).to.not.throw(new RangeError('Out of range.'));908   *909   * Please note that when a throw expectation is negated, it will check each910   * parameter independently, starting with error constructor type. The appropriate way911   * to check for the existence of a type of error but for a message that does not match912   * is to use `and`.913   *914   *     expect(fn).to.throw(ReferenceError)915   *        .and.not.throw(/good function/);916   *917   * @name throw918   * @alias throws919   * @alias Throw920   * @param {ErrorConstructor} constructor921   * @param {String|RegExp} expected error message922   * @param {String} message _optional_923   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types924   * @returns error for chaining (null if no error)925   * @api public926   */927  function assertThrows (constructor, errMsg, msg) {928    if (msg) flag(this, 'message', msg);929    var obj = flag(this, 'object');930    new Assertion(obj, msg).is.a('function');931    var thrown = false932      , desiredError = null933      , name = null934      , thrownError = null;935    if (arguments.length === 0) {936      errMsg = null;937      constructor = null;938    } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {939      errMsg = constructor;940      constructor = null;941    } else if (constructor && constructor instanceof Error) {942      desiredError = constructor;943      constructor = null;944      errMsg = null;945    } else if (typeof constructor === 'function') {946      name = constructor.prototype.name || constructor.name;947      if (name === 'Error' && constructor !== Error) {948        name = (new constructor()).name;949      }950    } else {951      constructor = null;952    }953    try {954      obj();955    } catch (err) {956      // first, check desired error957      if (desiredError) {958        this.assert(959            err === desiredError960          , 'expected #{this} to throw #{exp} but #{act} was thrown'961          , 'expected #{this} to not throw #{exp}'962          , (desiredError instanceof Error ? desiredError.toString() : desiredError)963          , (err instanceof Error ? err.toString() : err)964        );965        flag(this, 'object', err);966        return this;967      }968      // next, check constructor969      if (constructor) {970        this.assert(971            err instanceof constructor972          , 'expected #{this} to throw #{exp} but #{act} was thrown'973          , 'expected #{this} to not throw #{exp} but #{act} was thrown'974          , name975          , (err instanceof Error ? err.toString() : err)976        );977        if (!errMsg) {978          flag(this, 'object', err);979          return this;980        }981      }982      // next, check message983      var message = 'object' === _.type(err) && "message" in err984        ? err.message985        : '' + err;986      if ((message != null) && errMsg && errMsg instanceof RegExp) {987        this.assert(988            errMsg.exec(message)989          , 'expected #{this} to throw error matching #{exp} but got #{act}'990          , 'expected #{this} to throw error not matching #{exp}'991          , errMsg992          , message993        );994        flag(this, 'object', err);995        return this;996      } else if ((message != null) && errMsg && 'string' === typeof errMsg) {997        this.assert(998            ~message.indexOf(errMsg)999          , 'expected #{this} to throw error including #{exp} but got #{act}'1000          , 'expected #{this} to throw error not including #{act}'1001          , errMsg1002          , message1003        );1004        flag(this, 'object', err);1005        return this;1006      } else {1007        thrown = true;1008        thrownError = err;1009      }1010    }1011    var actuallyGot = ''1012      , expectedThrown = name !== null1013        ? name1014        : desiredError1015          ? '#{exp}' //_.inspect(desiredError)1016          : 'an error';1017    if (thrown) {1018      actuallyGot = ' but #{act} was thrown'1019    }1020    this.assert(1021        thrown === true1022      , 'expected #{this} to throw ' + expectedThrown + actuallyGot1023      , 'expected #{this} to not throw ' + expectedThrown + actuallyGot1024      , (desiredError instanceof Error ? desiredError.toString() : desiredError)1025      , (thrownError instanceof Error ? thrownError.toString() : thrownError)1026    );1027    flag(this, 'object', thrownError);1028  };1029  Assertion.addMethod('throw', assertThrows);1030  Assertion.addMethod('throws', assertThrows);1031  Assertion.addMethod('Throw', assertThrows);1032  /**1033   * ### .respondTo(method)1034   *1035   * Asserts that the object or class target will respond to a method.1036   *1037   *     Klass.prototype.bar = function(){};1038   *     expect(Klass).to.respondTo('bar');1039   *     expect(obj).to.respondTo('bar');1040   *1041   * To check if a constructor will respond to a static function,1042   * set the `itself` flag.1043   *1044   *     Klass.baz = function(){};1045   *     expect(Klass).itself.to.respondTo('baz');1046   *1047   * @name respondTo1048   * @param {String} method1049   * @param {String} message _optional_1050   * @api public1051   */1052  Assertion.addMethod('respondTo', function (method, msg) {1053    if (msg) flag(this, 'message', msg);1054    var obj = flag(this, 'object')1055      , itself = flag(this, 'itself')1056      , context = ('function' === _.type(obj) && !itself)1057        ? obj.prototype[method]1058        : obj[method];1059    this.assert(1060        'function' === typeof context1061      , 'expected #{this} to respond to ' + _.inspect(method)1062      , 'expected #{this} to not respond to ' + _.inspect(method)1063    );1064  });1065  /**1066   * ### .itself1067   *1068   * Sets the `itself` flag, later used by the `respondTo` assertion.1069   *1070   *     function Foo() {}1071   *     Foo.bar = function() {}1072   *     Foo.prototype.baz = function() {}1073   *1074   *     expect(Foo).itself.to.respondTo('bar');1075   *     expect(Foo).itself.not.to.respondTo('baz');1076   *1077   * @name itself1078   * @api public1079   */1080  Assertion.addProperty('itself', function () {1081    flag(this, 'itself', true);1082  });1083  /**1084   * ### .satisfy(method)1085   *1086   * Asserts that the target passes a given truth test.1087   *1088   *     expect(1).to.satisfy(function(num) { return num > 0; });1089   *1090   * @name satisfy1091   * @param {Function} matcher1092   * @param {String} message _optional_1093   * @api public1094   */1095  Assertion.addMethod('satisfy', function (matcher, msg) {1096    if (msg) flag(this, 'message', msg);1097    var obj = flag(this, 'object');1098    this.assert(1099        matcher(obj)1100      , 'expected #{this} to satisfy ' + _.objDisplay(matcher)1101      , 'expected #{this} to not satisfy' + _.objDisplay(matcher)1102      , this.negate ? false : true1103      , matcher(obj)1104    );1105  });1106  /**1107   * ### .closeTo(expected, delta)1108   *1109   * Asserts that the target is equal `expected`, to within a +/- `delta` range.1110   *1111   *     expect(1.5).to.be.closeTo(1, 0.5);1112   *1113   * @name closeTo1114   * @param {Number} expected1115   * @param {Number} delta1116   * @param {String} message _optional_1117   * @api public1118   */1119  Assertion.addMethod('closeTo', function (expected, delta, msg) {1120    if (msg) flag(this, 'message', msg);1121    var obj = flag(this, 'object');1122    this.assert(1123        Math.abs(obj - expected) <= delta1124      , 'expected #{this} to be close to ' + expected + ' +/- ' + delta1125      , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta1126    );1127  });1128  function isSubsetOf(subset, superset) {1129    return subset.every(function(elem) {1130      return superset.indexOf(elem) !== -1;1131    })1132  }1133  /**1134   * ### .members(set)1135   *1136   * Asserts that the target is a superset of `set`,1137   * or that the target and `set` have the same members.1138   *1139   *     expect([1, 2, 3]).to.include.members([3, 2]);1140   *     expect([1, 2, 3]).to.not.include.members([3, 2, 8]);1141   *1142   *     expect([4, 2]).to.have.members([2, 4]);1143   *     expect([5, 2]).to.not.have.members([5, 2, 1]);1144   *1145   * @name members1146   * @param {Array} set1147   * @param {String} message _optional_1148   * @api public1149   */1150  Assertion.addMethod('members', function (subset, msg) {1151    if (msg) flag(this, 'message', msg);1152    var obj = flag(this, 'object');1153    new Assertion(obj).to.be.an('array');1154    new Assertion(subset).to.be.an('array');1155    if (flag(this, 'contains')) {1156      return this.assert(1157          isSubsetOf(subset, obj)1158        , 'expected #{this} to be a superset of #{act}'1159        , 'expected #{this} to not be a superset of #{act}'1160        , obj1161        , subset1162      );1163    }1164    this.assert(1165        isSubsetOf(obj, subset) && isSubsetOf(subset, obj)1166        , 'expected #{this} to have the same members as #{act}'1167        , 'expected #{this} to not have the same members as #{act}'1168        , obj1169        , subset1170    );1171  });...chai.js
Source:chai.js  
...769         * @param {String} message _optional_770         * @api public771         */772  773        function assertLeast(n, msg) {774          if (msg) flag(this, 'message', msg);775          var obj = flag(this, 'object');776          if (flag(this, 'doLength')) {777            new Assertion(obj, msg).to.have.property('length');778            var len = obj.length;779            this.assert(780              len >= n781              , 'expected #{this} to have a length at least #{exp} but got #{act}'782              , 'expected #{this} to have a length below #{exp}'783              , n784              , len785            );786          } else {787            this.assert(...Using AI Code Generation
1const assert = require('chai').assert;2const app = require('../app');3sayHelloResult = app.sayHello();4addNumbersResult = app.addNumbers(5,5);5describe('App', function(){6  describe('sayHello()', function(){7    it('sayHello should return hello', function(){8      assert.equal(sayHelloResult,'hello');9    });10    it('sayHello should return type string', function(){11      assert.typeOf(sayHelloResult,'string');12    });13  });14  describe('addNumbers()', function(){15    it('addNumbers should be above 5', function(){16      assert.isAbove(addNumbersResult,5);17    });18    it('addNumbers should return type number', function(){19      assert.typeOf(addNumbersResult,'number');20    });21  });22});Using AI Code Generation
1var chai = require('chai');2var assert = chai.assert;3var expect = chai.expect;4var should = chai.should();5var chaiAsPromised = require('chai-as-promised');6chai.use(chaiAsPromised);7var chaiHttp = require('chai-http');8chai.use(chaiHttp);9var app = require('../server.js');10var server;11var request;12var port = 3000;13var mongoose = require('mongoose');14var User = require('../models/user.js');15var bcrypt = require('bcrypt');16var salt = bcrypt.genSaltSync(10);17var user1 = new User({Using AI Code Generation
1var assert = require('chai').assert;2var assertLeast = require('chai').assertLeast;3var assertMost = require('chai').assertMost;4var assertAtMost = require('chai').assertAtMost;5var assertAtLeast = require('chai').assertAtLeast;6describe('assertLeast', function() {7   it('value should be greater than or equal to 5', function() {8      assertLeast(5, 5);9   });10});11describe('assertMost', function() {12   it('value should be less than or equal to 5', function() {13      assertMost(5, 5);14   });15});16describe('assertAtMost', function() {17   it('value should be less than or equal to 5', function() {18      assertAtMost(5, 5);19   });20});21describe('assertAtLeast', function() {22   it('value should be greater than or equal to 5', function() {23      assertAtLeast(5, 5);24   });25});Using AI Code Generation
1var chai = require('chai');2var assert = chai.assert;3var expect = chai.expect;4var should = chai.should();5var chaiAsPromised = require("chai-as-promised");6chai.use(chaiAsPromised);7var should = chai.should();8var assert = chai.assert;9var expect = chai.expect;10var chai = require('chai');11var assert = chai.assert;12var expect = chai.expect;13var should = chai.should();14var chaiAsPromised = require("chai-as-promised");15chai.use(chaiAsPromised);16describe('Chai', function () {17  describe('Chai', function () {18    it('should pass', function () {19      expect('foo').to.be.a('string');20      expect('foo').to.equal('foo');21      expect('foo').to.have.length(3);22      expect([1, 2, 3]).to.have.length(3);23      expect({ foo: 'bar' }).to.be.an('object');24      expect({ foo: 'bar' }).to.have.property('foo');25      expect({ foo: 'bar' }).to.have.property('foo').that.is.a('string');26      expect('foobar').to.match(/^foo/);27    });28  });29  describe('Assert', function () {30    it('should pass', function () {31      assert.typeOf('foo', 'string');32      assert.equal('foo', 'foo');33      assert.lengthOf('foo', 3);34      assert.lengthOf([1, 2, 3], 3);35      assert.typeOf({ foo: 'bar' }, 'object');36      assert.property({ foo: 'bar' }, 'foo');37      assert.propertyVal({ foo: 'bar' }, 'foo', 'bar');38      assert.match('foobar', /^foo/);39    });40  });41});Using AI Code Generation
1var assert = require('chai').assert;2var assertLeast = require('chai-assert-least');3assertLeast(assert, 2);4assert.least(2, 1);5assert.least(2, 2);6var expect = require('chai').expect;7var expectLeast = require('chai-assert-least');8expectLeast(expect, 2);9expect(2).least(1);10expect(2).least(2);11var should = require('chai').should();12var shouldLeast = require('chai-assert-least');13shouldLeast(should, 2);14(2).should.least(1);15(2).should.least(2);16assertLeast(assert, leastValue);17expectLeast(expect, leastValue);18shouldLeast(should, leastValue);19MIT © [Anshul Gupta](Using AI Code Generation
1const assert = require('chai').assert;2const assertLeast = require('../lib/assertLeast');3const assertMost = require('../lib/assertMost');4const assertBetween = require('../lib/assertBetween');5const assertArray = require('../lib/assertArray');6const assertObject = require('../lib/assertObject');7const assertString = require('../lib/assertString');8const assertNumber = require('../lib/assertNumber');9const assertBoolean = require('../lib/assertBoolean');10const assertFunction = require('../lib/assertFunction');11assertLeast(1, 2, 'The first number is less than the second number');12assertMost(2, 1, 'The first number is greater than the second number');13assertBetween(1, 2, 3, 'The first number is between the second and third number');14assertArray([1, 2, 3], 'The value is an array');15assertObject({a: 1, b: 2}, 'The value is an object');16assertString('string', 'The value is a string');17assertNumber(1, 'The value is a number');18assertBoolean(true, 'The value is a boolean');19assertFunction(() => {}, 'The value is a function');Using AI Code Generation
1const assert = require('chai').assert;2const assertLeast = require('chai').assertLeast;3const assertMost = require('chai').assertMost;4describe('assertLeast', function() {5  it('should return true if the first argument is less than or equal to the second argument', function() {6    assertLeast(5, 10);7  });8});9describe('assertMost', function() {10  it('should return true if the first argument is greater than or equal to the second argument', function() {11    assertMost(10, 5);12  });13});14const assert = require('chai').assert;15const assertApproximatelyEqual = require('chai').assertApproximatelyEqual;16describe('assertApproximatelyEqual', function() {17  it('should return true if the first argument is approximately equal to the second argument', function() {18    assertApproximatelyEqual(5, 5.1, 0.1);19  });20});21const assert = require('chai').assert;22const assertIsNotFalse = require('chai').assertIsNotFalse;23describe('assertIsNotFalse', function() {24  it('should return true if the first argument is not false', function() {25    assertIsNotFalse(true);26  });27});28const assert = require('chai').assert;29const assertIsTrue = require('chai').assertIsTrue;30describe('assertIsTrue', function() {31  it('should return true if the first argument is true', function() {32    assertIsTrue(true);33  });34});35const assert = require('chai').assert;36const assertIsFalse = require('chai').assertIsFalse;37describe('assertIsFalse', function() {38  it('should return true if the first argument is false', function() {39    assertIsFalse(false);40  });41});42const assert = require('chai').assert;43const assertIsNotTrue = require('chai').assertIsNotTrue;44describe('assertIsNotTrue', function() {45  it('should return true if the first argumentUsing AI Code Generation
1var assert = require('chai').assert;2var assertLeast = require('../assertLeast');3describe('assertLeast', function() {4    it('should return true if the first argument is greater than or equal to the second', function() {5        assert.isTrue(assertLeast(5, 4));6        assert.isTrue(assertLeast(5, 5));7        assert.isTrue(assertLeast(5, 3));8        assert.isTrue(assertLeast(5, 0));9        assert.isTrue(assertLeast(5, -1));10    });11    it('should return false if the first argument is less than the second', function() {12        assert.isFalse(assertLeast(5, 6));13        assert.isFalse(assertLeast(5, 7));14        assert.isFalse(assertLeast(5, 8));15        assert.isFalse(assertLeast(5, 9));16        assert.isFalse(assertLeast(5, 10));17    });18});Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
