BDD Style Introduction

The BDD style is exposed through expect or should interfaces. In both
scenarios, you chain together natural language assertions.

 // expect
 var expect = require('chai').expect;
 expect(foo).to.equal('bar');

 // should
 var should = require('chai').should();
 foo.should.equal('bar');

Differences

The expect interface provides a function as a starting point for chaining
your language assertions. It works on node.js and in all browsers.

The should interface extends Object.prototype to provide a single getter as
the starting point for your language assertions. It works on node.js and in
all browsers except Internet Explorer.

Configuration

By default, Chai does not show stack traces upon an AssertionError. This can
be changed by modifying the includeStack parameter for chai.Assertion. For example:

 var chai = require('chai');
 chai.Assertion.includeStack = true; // defaults to false

to

@apipublic

Language chain.

View Source
Object.defineProperty(Assertion.prototype, 'to',
  { get: function () {
      return this;
    }
  , configurable: true
});
              

be

@apipublic

Language chain.

View Source
Object.defineProperty(Assertion.prototype, 'be',
  { get: function () {
      return this;
    }
  , configurable: true
});
              

been

@apipublic

Language chain. Also tests tense to past for addon
modules that use the tense feature.

View Source
Object.defineProperty(Assertion.prototype, 'been',
  { get: function () {
      flag(this, 'tense', 'past');
      return this;
    }
  , configurable: true
});
              

.a(type)

an()

@aliasan
@param{ String }type
@apipublic

Assert typeof. Also can be used as a language chain.

 expect('test').to.be.a('string');
 expect(foo).to.be.an.instanceof(Foo);
View Source
var an = function () {
  var assert = function(type) {
    var obj = flag(this, 'object')
      , klass = type.charAt(0).toUpperCase() + type.slice(1);

    this.assert(
        '[object ' + klass + ']' === toString.call(obj)
      , 'expected #{this} to be a ' + type
      , 'expected #{this} not to be a ' + type
      , '[object ' + klass + ']'
      , toString.call(obj)
    );

    return this;
  };

  assert.__proto__ = this;
  return assert;
};

Object.defineProperty(Assertion.prototype, 'an',
  { get: an
  , configurable: true
});

Object.defineProperty(Assertion.prototype, 'a',
  { get: an
  , configurable: true
});
              

.include(value)

include()

@aliascontain
@param{ Object | String | Number }obj
@apipublic

Assert the inclusion of an object in an Array or substring in string.
Also toggles the contain flag for the keys assertion if used as property.

 expect([1,2,3]).to.include(2);
View Source
var include = function () {
  flag(this, 'contains', true);

  var assert = function(val) {
    var obj = flag(this, 'object')
    this.assert(
        ~obj.indexOf(val)
      , 'expected #{this} to include ' + util.inspect(val)
      , 'expected #{this} to not include ' + util.inspect(val));

    return this;
  };

  assert.__proto__ = this;
  return assert;
};

Object.defineProperty(Assertion.prototype, 'contain',
  { get: include
  , configurable: true
});

Object.defineProperty(Assertion.prototype, 'include',
  { get: include
  , configurable: true
});
              

is

@apipublic

Language chain.

View Source
Object.defineProperty(Assertion.prototype, 'is',
  { get: function () {
      return this;
    }
  , configurable: true
});
              

and

@apipublic

Language chain.

View Source
Object.defineProperty(Assertion.prototype, 'and',
  { get: function () {
      return this;
    }
  , configurable: true
});
              

have

@apipublic

Language chain.

View Source
Object.defineProperty(Assertion.prototype, 'have',
  { get: function () {
      return this;
    }
  , configurable: true
});
              

with

@apipublic

Language chain.

View Source
Object.defineProperty(Assertion.prototype, 'with',
  { get: function () {
      return this;
    }
  , configurable: true
});
              

.not

@apipublic

Negates any of assertions following in the chain.

View Source
Object.defineProperty(Assertion.prototype, 'not',
  { get: function () {
      flag(this, 'negate', true);
      return this;
    }
  , configurable: true
});
              

.ok

@apipublic

Assert object truthiness.

 expect('everthing').to.be.ok;
 expect(false).to.not.be.ok;
 expect(undefined).to.not.be.ok;
 expect(null).to.not.be.ok;
View Source
Object.defineProperty(Assertion.prototype, 'ok',
  { get: function () {
      this.assert(
          flag(this, 'object')
        , 'expected #{this} to be truthy'
        , 'expected #{this} to be falsy');

      return this;
    }
  , configurable: true
});
              

.true

@apipublic

Assert object is true

View Source
Object.defineProperty(Assertion.prototype, 'true',
  { get: function () {
      this.assert(
          true === flag(this, 'object')
        , 'expected #{this} to be true'
        , 'expected #{this} to be false'
        , this.negate ? false : true
      );

      return this;
    }
  , configurable: true
});
              

.false

@apipublic

Assert object is false

View Source
Object.defineProperty(Assertion.prototype, 'false',
  { get: function () {
      this.assert(
          false === flag(this, 'object')
        , 'expected #{this} to be false'
        , 'expected #{this} to be true'
        , this.negate ? true : false
      );

      return this;
    }
  , configurable: true
});
              

.exist

@apipublic

Assert object exists (null).

 var foo = 'hi'
   , bar;
 expect(foo).to.exist;
 expect(bar).to.not.exist;
View Source
Object.defineProperty(Assertion.prototype, 'exist',
  { get: function () {
      this.assert(
          null != flag(this, 'object')
        , 'expected #{this} to exist'
        , 'expected #{this} to not exist'
      );

      return this;
    }
  , configurable: true
});
              

.empty

@apipublic

Assert object's length to be 0.

 expect([]).to.be.empty;
View Source
Object.defineProperty(Assertion.prototype, 'empty',
  { get: function () {
      var obj = flag(this, 'object')
        , expected = obj;

      if (Array.isArray(obj)) {
        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');

      return this;
    }
  , configurable: true
});
              

.arguments

@apipublic

Assert object is an instanceof arguments.

 function test () {
   expect(arguments).to.be.arguments;
 }
View Source
Object.defineProperty(Assertion.prototype, 'arguments',
  { get: function () {
      var obj = flag(this, 'object');
      this.assert(
          '[object Arguments]' == Object.prototype.toString.call(obj)
        , 'expected #{this} to be arguments'
        , 'expected #{this} to not be arguments'
        , '[object Arguments]'
        , Object.prototype.toString.call(obj)
      );

      return this;
    }
  , configurable: true
});
              

.equal(value)

Assertion.prototype.equal()

@param{ * }value
@apipublic

Assert strict equality.

 expect('hello').to.equal('hello');
View Source
Assertion.prototype.equal = function (val) {
  this.assert(
      val === flag(this, 'object')
    , 'expected #{this} to equal #{exp}'
    , 'expected #{this} to not equal #{exp}'
    , val );

  return this;
};
              

.eql(value)

Assertion.prototype.eql()

@param{ * }value
@apipublic

Assert deep equality.

 expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
View Source
Assertion.prototype.eql = function (obj) {
  this.assert(
      util.eql(obj, flag(this, 'object'))
    , 'expected #{this} to equal #{exp}'
    , 'expected #{this} to not equal #{exp}'
    , obj );

  return this;
};
              

.above(value)

Assertion.prototype.above()

@aliasmt
@param{ Number }value
@apipublic

Assert greater than value.

 expect(10).to.be.above(5);
View Source
Assertion.prototype.above = function (val) {
  this.assert(
      flag(this, 'object') > val
    , 'expected #{this} to be above ' + val
    , 'expected #{this} to be below ' + val);

  return this;
};
              

.below(value)

Assertion.prototype.below()

@aliaslt
@param{ Number }value
@apipublic

Assert less than value.

 expect(5).to.be.below(10);
View Source
Assertion.prototype.below = function (val) {
  this.assert(
      flag(this, 'object') < val
    , 'expected #{this} to be below ' + val
    , 'expected #{this} to be above ' + val);

  return this;
};
              

.within(start, finish)

Assertion.prototype.within()

@param{ Number }startlowerbound inclusive
@param{ Number }finishupperbound inclusive
@apipublic

Assert that a number is within a range.

 expect(7).to.be.within(5,10);
View Source
Assertion.prototype.within = function (start, finish) {
  var obj = flag(this, 'object')
    , range = start + '..' + finish;

  this.assert(
      obj >= start && obj <= finish
    , 'expected #{this} to be within ' + range
    , 'expected #{this} to not be within ' + range);

  return this;
};
              

.instanceof(constructor)

Assertion.prototype.instanceOf()

@param{ Constructor }
@aliasinstanceOf
@apipublic

Assert instanceof.

 var Tea = function (name) { this.name = name; }
   , Chai = new Tea('chai');

 expect(Chai).to.be.an.instanceof(Tea);
View Source
Assertion.prototype.instanceOf = function (constructor) {
  var name = util.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);

  return this;
};
              

.property(name, [value])

Assertion.prototype.property()

@param{ String }name
@param{ * }value(optional)
@returnsvalue of property for chaining
@apipublic

Assert that property of name exists, optionally with value.

 var obj = { foo: 'bar' }
 expect(obj).to.have.property('foo');
 expect(obj).to.have.property('foo', 'bar');
 expect(obj).to.have.property('foo').to.be.a('string');
View Source
Assertion.prototype.property = function (name, val) {
  var obj = flag(this, 'object')
    , value = util.getPathValue(name, obj)
    , negate = flag(this, 'negate');

  if (negate && undefined !== val) {
    if (undefined === value) {
      throw new Error(util.inspect(obj) + ' has no property ' + util.inspect(name));
    }
  } else {
    this.assert(
        undefined !== value
      , 'expected #{this} to have a property ' + util.inspect(name)
      , 'expected #{this} to not have property ' + util.inspect(name));
  }

  if (undefined !== val) {
    this.assert(
        val === value
      , 'expected #{this} to have a property ' + util.inspect(name) + ' of #{exp}, but got #{act}'
      , 'expected #{this} to not have a property ' + util.inspect(name) + ' of #{act}'
      , val
      , value
    );
  }

  flag(this, 'object', value);
  return this;
};
              

.ownProperty(name)

Assertion.prototype.ownProperty()

@aliashaveOwnProperty
@param{ String }name
@apipublic

Assert that has own property by name.

 expect('test').to.have.ownProperty('length');
View Source
Assertion.prototype.ownProperty = function (name) {
  var obj = flag(this, 'object');
  this.assert(
      obj.hasOwnProperty(name)
    , 'expected #{this} to have own property ' + util.inspect(name)
    , 'expected #{this} to not have own property ' + util.inspect(name));
  return this;
};
              

.length(val)

Assertion.prototype.length()

@aliaslengthOf
@param{ Number }length
@apipublic

Assert that object has expected length.

 expect([1,2,3]).to.have.length(3);
 expect('foobar').to.have.length(6);
View Source
Assertion.prototype.length = function (n) {
  var obj = flag(this, 'object');
  new Assertion(obj).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
  );

  return this;
};
              

.match(regexp)

Assertion.prototype.match()

@param{ RegExp }RegularExpression
@apipublic

Assert that matches regular expression.

 expect('foobar').to.match(/^foo/);
View Source
Assertion.prototype.match = function (re) {
  var obj = flag(this, 'object');
  this.assert(
      re.exec(obj)
    , 'expected #{this} to match ' + re
    , 'expected #{this} not to match ' + re);

  return this;
};
              

.string(string)

Assertion.prototype.string()

@param{ String }string
@apipublic

Assert inclusion of string in string.

 expect('foobar').to.have.string('bar');
View Source
Assertion.prototype.string = function (str) {
  var obj = flag(this, 'object');
  new Assertion(obj).is.a('string');

  this.assert(
      ~obj.indexOf(str)
    , 'expected #{this} to contain ' + util.inspect(str)
    , 'expected #{this} to not contain ' + util.inspect(str));

  return this;
};
              

.keys(key1, [key2], [...])

Assertion.prototype.keys()

@aliaskey
@param{ String | Array }Keys
@apipublic

Assert exact keys or the inclusing of keys using the contain modifier.

 expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);
 expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');
View Source
Assertion.prototype.keys = function(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 util.inspect(key);
    });
    var last = keys.pop();
    str = keys.join(', ') + ', and ' + last;
  } else {
    str = util.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
    , keys
    , Object.keys(obj)
  );

  return this;
}
              

.throw(constructor)

Assertion.prototype.Throw()

@aliasthrows
@aliasThrow
@param{ ErrorConstructor }constructor
@see
@apipublic

Assert that a function will throw a specific type of 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/);
View Source
Assertion.prototype.Throw = function (constructor, msg) {
  var obj = flag(this, 'object');
  new Assertion(obj).is.a('function');

  var thrown = false
    , desiredError = null
    , name = null;

  if (arguments.length === 0) {
    msg = null;
    constructor = null;
  } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
    msg = constructor;
    constructor = null;
  } else if (constructor && constructor instanceof Error) {
    desiredError = constructor;
    constructor = null;
    msg = 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 ' + util.inspect(desiredError) + ' but ' + util.inspect(err) + ' was thrown'
        , 'expected #{this} to not throw ' + util.inspect(desiredError)
      );
      return this;
    }
    // next, check constructor
    if (constructor) {
      this.assert(
          err instanceof constructor
        , 'expected #{this} to throw ' + name + ' but a ' + err.name + ' was thrown'
        , 'expected #{this} to not throw ' + name );
      if (!msg) return this;
    }
    // next, check message
    if (err.message && msg && msg instanceof RegExp) {
      this.assert(
          msg.exec(err.message)
        , 'expected #{this} to throw error matching ' + msg + ' but got ' + util.inspect(err.message)
        , 'expected #{this} to throw error not matching ' + msg
      );
      return this;
    } else if (err.message && msg && 'string' === typeof msg) {
      this.assert(
          ~err.message.indexOf(msg)
        , 'expected #{this} to throw error including #{exp} but got #{act}'
        , 'expected #{this} to throw error not including #{act}'
        , msg
        , err.message
      );
      return this;
    } else {
      thrown = true;
    }
  }

  var expectedThrown = name ? name : desiredError ? util.inspect(desiredError) : 'an error';

  this.assert(
      thrown === true
    , 'expected #{this} to throw ' + expectedThrown
    , 'expected #{this} to not throw ' + expectedThrown);

  return this;
};
              

.respondTo(method)

Assertion.prototype.respondTo()

@param{ String }method
@apipublic

Assert that object/class will respond to a method.

 expect(Klass).to.respondTo('bar');
 expect(obj).to.respondTo('bar');
View Source
Assertion.prototype.respondTo = function (method) {
  var obj = flag(this, 'object')
    , context = ('function' === typeof obj)
      ? obj.prototype[method]
      : obj[method];

  this.assert(
      'function' === typeof context
    , 'expected #{this} to respond to ' + util.inspect(method)
    , 'expected #{this} to not respond to ' + util.inspect(method)
    , 'function'
    , typeof context
  );

  return this;
};
              

.satisfy(method)

Assertion.prototype.satisfy()

@param{ Function }matcher
@apipublic

Assert that passes a truth test.

 expect(1).to.satisfy(function(num) { return num > 0; });
View Source
Assertion.prototype.satisfy = function (matcher) {
  var obj = flag(this, 'object');
  this.assert(
      matcher(obj)
    , 'expected #{this} to satisfy ' + util.inspect(matcher)
    , 'expected #{this} to not satisfy' + util.inspect(matcher)
    , this.negate ? false : true
    , matcher(obj)
  );

  return this;
};
              

.closeTo(expected, delta)

Assertion.prototype.closeTo()

@param{ Number }expected
@param{ Number }delta
@apipublic

Assert that actual is equal to +/- delta.

 expect(1.5).to.be.closeTo(1, 0.5);
View Source
Assertion.prototype.closeTo = function (expected, delta) {
  var obj = flag(this, 'object');
  this.assert(
      (obj - delta === expected) || (obj + delta === expected)
    , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
    , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta);

  return this;
};