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)
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)
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;
.undefined
Asserts that the target is undefined
.
expect(undefined).to.be.undefined;
expect(null).to.not.be.undefined;
.exist
Asserts that the target is neither null
nor undefined
.
var foo = 'hi'
, bar = null
, baz;
expect(foo).to.exist;
expect(bar).to.not.exist;
expect(baz).to.not.exist;
.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)
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)
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)
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)
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)
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)
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)
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)
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])
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)
Asserts that the target has an own property name
.
expect('test').to.have.ownProperty('length');
.ownPropertyDescriptor(name[, descriptor[, message]])
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])
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)
Asserts that the target matches a regular expression.
expect('foobar').to.match(/^foo/);
.string(string)
Asserts that the string target contains another string.
expect('foobar').to.have.string('bar');
.keys(key1, [key2], […])
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)
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)
Asserts that the target passes a given truth test.
expect(1).to.satisfy(function(num) { return num > 0; });
.closeTo(expected, delta)
Asserts that the target is equal expected
, to within a +/- delta
range.
expect(1.5).to.be.closeTo(1, 0.5);
.members(set)
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)
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)
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)
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)
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;