BDD

The BDD styles are expect and should. Both use the same chainable language to construct assertions, but they differ in the way an assertion is initially constructed. Check out the Style Guide for a comparison.

API Reference

Language Chains

The following are provided as chainable getters to improve the readability of your assertions. They do not provide testing capabilities unless they have been overwritten by a plugin.

Chains

  • to
  • be
  • been
  • is
  • that
  • which
  • and
  • has
  • have
  • with
  • at
  • of
  • same

.not

Negates any of assertions following in the chain.

expect(foo).to.not.equal('bar');
expect(goodFn).to.not.throw(Error);
expect({ foo: 'baz' }).to.have.property('foo')
  .and.not.equal('bar');

.deep

Sets the deep flag, later used by the equal and property assertions.

expect(foo).to.deep.equal({ bar: 'baz' });
expect({ foo: { bar: { baz: 'quux' } } })
  .to.have.deep.property('foo.bar.baz', 'quux');

.deep.property special characters can be escaped by adding two slashes before the . or [].

var deepCss = { '.link': { '[target]': 42 }};
expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);

.any

Sets the any flag, (opposite of the all flag) later used in the keys assertion.

expect(foo).to.have.any.keys('bar', 'baz');

.all

Sets the all flag (opposite of the any flag) later used by the keys assertion.

expect(foo).to.have.all.keys('bar', 'baz');

.a(type)

  • @param { String } type
  • @param { String } message _optional_

The a and an assertions are aliases that can be used either as language chains or to assert a value’s type.

// typeof
expect('test').to.be.a('string');
expect({ foo: 'bar' }).to.be.an('object');
expect(null).to.be.a('null');
expect(undefined).to.be.an('undefined');
expect(new Error).to.be.an('error');
expect(new Promise).to.be.a('promise');
expect(new Float32Array()).to.be.a('float32array');
expect(Symbol()).to.be.a('symbol');

// es6 overrides
expect({[Symbol.toStringTag]:()=>'foo'}).to.be.a('foo');

// language chain
expect(foo).to.be.an.instanceof(Foo);

.include(value)

  • @param { Object | String | Number } obj
  • @param { String } message _optional_

The include and contain assertions can be used as either property based language chains or as methods to assert the inclusion of an object in an array or a substring in a string. When used as language chains, they toggle the contains flag for the keys assertion.

expect([1,2,3]).to.include(2);
expect('foobar').to.contain('foo');
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');

.ok

Asserts that the target is truthy.

expect('everything').to.be.ok;
expect(1).to.be.ok;
expect(false).to.not.be.ok;
expect(undefined).to.not.be.ok;
expect(null).to.not.be.ok;

.true

Asserts that the target is true.

expect(true).to.be.true;
expect(1).to.not.be.true;

.false

Asserts that the target is false.

expect(false).to.be.false;
expect(0).to.not.be.false;

.null

Asserts that the target is null.

expect(null).to.be.null;
expect(undefined).to.not.be.null;

.undefined

Asserts that the target is undefined.

expect(undefined).to.be.undefined;
expect(null).to.not.be.undefined;

.NaN

Asserts that the target is NaN.

expect('foo').to.be.NaN;
expect(4).not.to.be.NaN;

.exist

Asserts that the target is neither null nor undefined.

var foo = 'hi'
  , bar = null
  , baz;

expect(foo).to.exist;
expect(bar).to.not.exist;
expect(baz).to.not.exist;

.empty

Asserts that the target’s length is 0. For arrays and strings, it checks the length property. For objects, it gets the count of enumerable keys.

expect([]).to.be.empty;
expect('').to.be.empty;
expect({}).to.be.empty;

.arguments

Asserts that the target is an arguments object.

function test () {
  expect(arguments).to.be.arguments;
}

.equal(value)

  • @param { Mixed } value
  • @param { String } message _optional_

Asserts that the target is strictly equal (===) to value. Alternately, if the deep flag is set, asserts that the target is deeply equal to value.

expect('hello').to.equal('hello');
expect(42).to.equal(42);
expect(1).to.not.equal(true);
expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });

.eql(value)

  • @param { Mixed } value
  • @param { String } message _optional_

Asserts that the target is deeply equal to value.

expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);

.above(value)

  • @param { Number } value
  • @param { String } message _optional_

Asserts that the target is greater than value.

expect(10).to.be.above(5);

Can also be used in conjunction with length to assert a minimum length. The benefit being a more informative error message than if the length was supplied directly.

expect('foo').to.have.length.above(2);
expect([ 1, 2, 3 ]).to.have.length.above(2);

.least(value)

  • @param { Number } value
  • @param { String } message _optional_

Asserts that the target is greater than or equal to value.

expect(10).to.be.at.least(10);

Can also be used in conjunction with length to assert a minimum length. The benefit being a more informative error message than if the length was supplied directly.

expect('foo').to.have.length.of.at.least(2);
expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);

.below(value)

  • @param { Number } value
  • @param { String } message _optional_

Asserts that the target is less than value.

expect(5).to.be.below(10);

Can also be used in conjunction with length to assert a maximum length. The benefit being a more informative error message than if the length was supplied directly.

expect('foo').to.have.length.below(4);
expect([ 1, 2, 3 ]).to.have.length.below(4);

.most(value)

  • @param { Number } value
  • @param { String } message _optional_

Asserts that the target is less than or equal to value.

expect(5).to.be.at.most(5);

Can also be used in conjunction with length to assert a maximum length. The benefit being a more informative error message than if the length was supplied directly.

expect('foo').to.have.length.of.at.most(4);
expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);

.within(start, finish)

  • @param { Number } start lowerbound inclusive
  • @param { Number } finish upperbound inclusive
  • @param { String } message _optional_

Asserts that the target is within a range.

expect(7).to.be.within(5,10);

Can also be used in conjunction with length to assert a length range. The benefit being a more informative error message than if the length was supplied directly.

expect('foo').to.have.length.within(2,4);
expect([ 1, 2, 3 ]).to.have.length.within(2,4);

.instanceof(constructor)

  • @param { Constructor } constructor
  • @param { String } message _optional_

Asserts that the target is an instance of constructor.

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

expect(Chai).to.be.an.instanceof(Tea);
expect([ 1, 2, 3 ]).to.be.instanceof(Array);

.property(name, [value])

  • @param { String } name
  • @param { Mixed } value (optional)
  • @param { String } message _optional_

Asserts that the target has a property name, optionally asserting that the value of that property is strictly equal to value. If the deep flag is set, you can use dot- and bracket-notation for deep references into objects and arrays.

// simple referencing
var obj = { foo: 'bar' };
expect(obj).to.have.property('foo');
expect(obj).to.have.property('foo', 'bar');

// deep referencing
var deepObj = {
    green: { tea: 'matcha' }
  , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
};

expect(deepObj).to.have.deep.property('green.tea', 'matcha');
expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');

You can also use an array as the starting point of a deep.property assertion, or traverse nested arrays.

var arr = [
    [ 'chai', 'matcha', 'konacha' ]
  , [ { tea: 'chai' }
    , { tea: 'matcha' }
    , { tea: 'konacha' } ]
];

expect(arr).to.have.deep.property('[0][1]', 'matcha');
expect(arr).to.have.deep.property('[1][2].tea', 'konacha');

Furthermore, property changes the subject of the assertion to be the value of that property from the original object. This permits for further chainable assertions on that property.

expect(obj).to.have.property('foo')
  .that.is.a('string');
expect(deepObj).to.have.property('green')
  .that.is.an('object')
  .that.deep.equals({ tea: 'matcha' });
expect(deepObj).to.have.property('teas')
  .that.is.an('array')
  .with.deep.property('[2]')
    .that.deep.equals({ tea: 'konacha' });

Note that dots and bracket in name must be backslash-escaped when the deep flag is set, while they must NOT be escaped when the deep flag is not set.

// simple referencing
var css = { '.link[target]': 42 };
expect(css).to.have.property('.link[target]', 42);

// deep referencing
var deepCss = { '.link': { '[target]': 42 }};
expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);

.ownProperty(name)

  • @param { String } name
  • @param { String } message _optional_

Asserts that the target has an own property name.

expect('test').to.have.ownProperty('length');

.ownPropertyDescriptor(name[, descriptor[, message]])

  • @param { String } name
  • @param { Object } descriptor _optional_
  • @param { String } message _optional_

Asserts that the target has an own property descriptor name, that optionally matches descriptor.

expect('test').to.have.ownPropertyDescriptor('length');
expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 });
expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 });
expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false);
expect('test').ownPropertyDescriptor('length').to.have.keys('value');

.length

Sets the doLength flag later used as a chain precursor to a value comparison for the length property.

expect('foo').to.have.length.above(2);
expect([ 1, 2, 3 ]).to.have.length.above(2);
expect('foo').to.have.length.below(4);
expect([ 1, 2, 3 ]).to.have.length.below(4);
expect('foo').to.have.length.within(2,4);
expect([ 1, 2, 3 ]).to.have.length.within(2,4);

Deprecation notice: Using length as an assertion will be deprecated in version 2.4.0 and removed in 3.0.0. Code using the old style of asserting for length property value using length(value) should be switched to use lengthOf(value) instead.

.lengthOf(value[, message])

  • @param { Number } length
  • @param { String } message _optional_

Asserts that the target’s length property has the expected value.

expect([ 1, 2, 3]).to.have.lengthOf(3);
expect('foobar').to.have.lengthOf(6);

.match(regexp)

  • @param { RegExp } RegularExpression
  • @param { String } message _optional_

Asserts that the target matches a regular expression.

expect('foobar').to.match(/^foo/);

.string(string)

  • @param { String } string
  • @param { String } message _optional_

Asserts that the string target contains another string.

expect('foobar').to.have.string('bar');

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

  • @param { String | Array | Object } keys

Asserts that the target contains any or all of the passed-in keys. Use in combination with any, all, contains, or have will affect what will pass.

When used in conjunction with any, at least one key that is passed in must exist in the target object. This is regardless whether or not the have or contain qualifiers are used. Note, either any or all should be used in the assertion. If neither are used, the assertion is defaulted to all.

When both all and contain are used, the target object must have at least all of the passed-in keys but may have more keys not listed.

When both all and have are used, the target object must both contain all of the passed-in keys AND the number of keys in the target object must match the number of keys passed in (in other words, a target object must have all and only all of the passed-in keys).

expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz');
expect({ foo: 1, bar: 2 }).to.have.any.keys('foo');
expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz');
expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']);
expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6});
expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']);
expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7});
expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']);
expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys({'bar': 6});

.throw(constructor)

Asserts that the function target will throw a specific error, or specific type of error (as determined using instanceof), optionally with a RegExp or string inclusion test for the error’s message.

var err = new ReferenceError('This is a bad function.');
var fn = function () { throw err; }
expect(fn).to.throw(ReferenceError);
expect(fn).to.throw(Error);
expect(fn).to.throw(/bad function/);
expect(fn).to.not.throw('good function');
expect(fn).to.throw(ReferenceError, /bad function/);
expect(fn).to.throw(err);

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/);

.respondTo(method)

  • @param { String } method
  • @param { String } message _optional_

Asserts that the object or class target will respond to a method.

Klass.prototype.bar = function(){};
expect(Klass).to.respondTo('bar');
expect(obj).to.respondTo('bar');

To check if a constructor will respond to a static function, set the itself flag.

Klass.baz = function(){};
expect(Klass).itself.to.respondTo('baz');

.itself

Sets the itself flag, later used by the respondTo assertion.

function Foo() {}
Foo.bar = function() {}
Foo.prototype.baz = function() {}

expect(Foo).itself.to.respondTo('bar');
expect(Foo).itself.not.to.respondTo('baz');

.satisfy(method)

  • @param { Function } matcher
  • @param { String } message _optional_

Asserts that the target passes a given truth test.

expect(1).to.satisfy(function(num) { return num > 0; });

.closeTo(expected, delta)

  • @param { Number } expected
  • @param { Number } delta
  • @param { String } message _optional_

Asserts that the target is equal expected, to within a +/- delta range.

expect(1.5).to.be.closeTo(1, 0.5);

.members(set)

  • @param { Array } set
  • @param { String } message _optional_

Asserts that the target is a superset of set, or that the target and set have the same strictly-equal (===) members. Alternately, if the deep flag is set, set members are compared for deep equality.

expect([1, 2, 3]).to.include.members([3, 2]);
expect([1, 2, 3]).to.not.include.members([3, 2, 8]);

expect([4, 2]).to.have.members([2, 4]);
expect([5, 2]).to.not.have.members([5, 2, 1]);

expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);

.oneOf(list)

  • @param { Array.<*> } list
  • @param { String } message _optional_

Assert that a value appears somewhere in the top level of array list.

expect('a').to.be.oneOf(['a', 'b', 'c']);
expect(9).to.not.be.oneOf(['z']);
expect([3]).to.not.be.oneOf([1, 2, [3]]);

var three = [3];
// for object-types, contents are not compared
expect(three).to.not.be.oneOf([1, 2, [3]]);
// comparing references works
expect(three).to.be.oneOf([1, 2, three]);

.change(function)

  • @param { String } object
  • @param { String } property name
  • @param { String } message _optional_

Asserts that a function changes an object property

var obj = { val: 10 };
var fn = function() { obj.val += 3 };
var noChangeFn = function() { return 'foo' + 'bar'; }
expect(fn).to.change(obj, 'val');
expect(noChangeFn).to.not.change(obj, 'val')

.increase(function)

  • @param { String } object
  • @param { String } property name
  • @param { String } message _optional_

Asserts that a function increases an object property

var obj = { val: 10 };
var fn = function() { obj.val = 15 };
expect(fn).to.increase(obj, 'val');

.decrease(function)

  • @param { String } object
  • @param { String } property name
  • @param { String } message _optional_

Asserts that a function decreases an object property

var obj = { val: 10 };
var fn = function() { obj.val = 5 };
expect(fn).to.decrease(obj, 'val');

.extensible

Asserts that the target is extensible (can have new properties added to it).

var nonExtensibleObject = Object.preventExtensions({});
var sealedObject = Object.seal({});
var frozenObject = Object.freeze({});

expect({}).to.be.extensible;
expect(nonExtensibleObject).to.not.be.extensible;
expect(sealedObject).to.not.be.extensible;
expect(frozenObject).to.not.be.extensible;

.sealed

Asserts that the target is sealed (cannot have new properties added to it and its existing properties cannot be removed).

var sealedObject = Object.seal({});
var frozenObject = Object.freeze({});

expect(sealedObject).to.be.sealed;
expect(frozenObject).to.be.sealed;
expect({}).to.not.be.sealed;

.frozen

Asserts that the target is frozen (cannot have new properties added to it and its existing properties cannot be modified).

var frozenObject = Object.freeze({});

expect(frozenObject).to.be.frozen;
expect({}).to.not.be.frozen;