20 expect - ranhs/soda-test GitHub Wiki

When writing unit-tests, usally to validate that all went right, we check values of our execution using the chai expect method. This page gives a list of possible ways to use expect. Note that this is not the full list, you need to look at chai documentation.
Soda-Topical automaticly extens the expect method with the plugins chai-as-promise and sinon-chai. This list includes also some of those extensions.

Basic usage

We will always starts with calling the expect method and passing it a value. On the return value of expect you can call many prperteis and methods. Each property and method, returns same type of expect object (in many cases the same object) that you can continue calling those properties and methods on it. Some of the properties/methods also validate something, casing the test to fail if the validation has failed. the chain callins of the properties and method can create a centence that will be easy to read and understand what it is checking.
In this page we'll give examples for common usages, explain what does this check on the value, and what is the checked value after this call.

Expect usage

to.equal

expect(value1).to.equal(value2)

validation: The value of value1 is the same as the value of value2. If the case of reference value, it is the same reference.
result checked value: value1
synonym: you may use equals instead of equal
you may obmit or add the property to

expect(2).to.equal(2).to.equal(2)
const obj = {}
expect(obj).to.equal(obj)
expect(2).equals(2)

to.not.equal

expect(value1).to.not.equal(value2)

validation The value of value1 is not the same as the value of value2. In the case of reference value, it is not the same refence.
result checked value: value2

expect(3).to.not.equal(2).to.equal(2)
expect({}).to.not.equal({})

to.deep.equal

expect(value1).to.deep.equal(value2)

validation: The value of value1 is the same as the value of value2. In the case of reference value, the values may or may not have the same refernce, but all their inner values are the same recursivly. Works for objects and arrays.
result checked value: value1 with deep flag still set.

expect(2).to.deep.equal(2).to.equal(2)
expect({a:2,b:'#'}).to.deep.equal({b:'#',a:2}).to.equal({a:2,b'#'})

to.not.deep.equal

expect(value1).to.not.deep.equal(value2)

validation: The value of value1 is different from the value of value2. In the case of reference value, the values are not the same refernce, and there is a different in their inner values. Works for objects and arrays.
result checked value: value2 with deep flag still set.

expect(3).to.not.deep.equal(2).to.equal(2)
expect({a:2,b:'#'}).to.not.deep.equal({a:3,b:'#'}).to.equal({a:3,b:'#'})

to.have.proeprty

expect(obj).to.have.property(name)
expect(obj).to.have.property(name,value)

validation: The given obj has a property that is named name. If value specified, it also validate the property value is equal to value
result checked value: obj[name] or value

expect({a:2,b:'#'}).to.have.property('a').equal(2)
expect({a:2,b:'#'}).to.have.property('a',2)
expect({a:2,b:'#'}).to.have.property('b').not.equal('$')

to.not.have.property

expect(obj).to.not.have.property(name)
expect(obj).to.not.have.property(name,value)

validation: The given obj does not have a property that is named name. If value specified validation also satisfy if the obj have a preropty of name name but its value is not equal to value
result checked value: obj[name] with the not flag still set
(Note: you cannot cancel the not flag by using the not property again)

expect({a:2,b:'#'}).to.not.have.property('c')
expect({a:2,b:'#'}).to.not.have.property('c').to.equals('@')
expect({a:2,b:'#'}).to.not.have.property('b','@')

Types validations

to.be.a

expect(var).to.be.a(type)

validation: The given var is of the given type. (type is a string that is the name of the JS type
result checked value: var
synonym: You may use an instead of a
You may obmit to.be

expect(12).to.be.a('number')
expect("12").to.be.a('string')
expect({}).to.be.an('object')
expect([]).to.be.an('array')

to.be.instanceOf

expect(objectInstance).to.be.instanceOf(classType)

validation: The given objectInstance is an object that is of the given classType
result checked value: objectInstance
synonym: You may use instanceof instead of instanceOf

class A {a: number = 1}
class B extends A {b: number = 2}
...
expect(new A()).to.be.instanceOf(A)
expect(new B()).to.be.instanceOf(B)
expect(new B()).to.be.instanceOf(A)
expect(new A()).to.not.be.instanceOf(B)
expect(new A()).to.be.instanceOf(A).to.be.an('object').to.have.property('a',1)

not flag

Whenever using the not property on expect retrun value (before the condition) it will cause the condition writen after it to be satesfy if and only if the condition is not satesfy.
expect(2).to.equal(2)
expect(3).to.not.equal(2)
expect({a:2}).to.deep.equal({a:2})
expect({a:2,b:3}.to.not.deep.equal({a:2})

Numeric Comparation

The following validation works only for values of type number or Date The result checked value is always value1.

to.be.above

expect(value1).to.be.above(value2)

validation: value2 > value1
synonym: you may use greaterThan instead of above

expect(2).to.be.above(1)
expect(2).to.be.greaterThan(1)

to.be.below

expect(value1).to.be.below(value2)

validation: value2 < value1
synonym: you may use lessThan instead of above

expect(2).to.be.below(3)
expect(2).to.be.lessThan(3)

Specific Values

In JavaScript there are some spcial values (e.g. null, undefined). You can check that a value equal to once of them in the was we already know:
expect(result).to.equal(null)

But you can do this using chai proeprties for those values:

expect(result).to.be.null
expect(result2).to.not.be.null

Those are some of the supported special values:

expect(false).to.be.false
expect(true).to.be.true
expect(null).to.be.null
expect(undefined).to.be.undefined
expect({}).to.be.empty
expect([]).to.be.empty
expect(undefined).to.not.exist
expect(null).to.not.exist

spy and stubs

to.have.been.calledOnce

expect(methodSpy).to.have.been.calledOnce
expect(methodStub).to.have.been.calledOnce

validation: The given methodSpy or methodStub is a SinonSpy or SinonStub that was called exacly one time since it was created/reset
result checked value: methodSpy / methodStub
synonym: you may obmit to.have.been

@it('should call demo once')
callDemo( @spy(ExpectTest, 'demo') demoSpy: SinonSpy): TR {
    ExpectTest.demo()
    expect(demospy).to.have.been.calledOnce
    expect(demospy).to.have.been.calledOnce.calledOnce
}

to.have.been.calledTwice

expect(methodSpy).to.have.been.calledTwice
expect(methodStub).to.have.been.calledTwice

validation: The given methodSpy or methodStub is a SinonSpy or SinonStub that was called exacly 2 times since it was created/reset
result checked value: methodSpy / methodStub
synonym: you may obmit to.have.been

@it('should call demo twice')
callDemo( @spy(ExpectTest, 'demo') demoSpy: SinonSpy): TR {
    ExpectTest.demo()
    ExpectTest.demo()
    expect(demospy).to.have.been.calledTwice
    expect(demospy).to.have.been.calledTwice.not.calledOnce
}

to.have.been.calledThrice

expect(methodSpy).to.have.been.calledThrice
expect(methodStub).to.have.been.calledThrice

validation: The given methodSpy or methodStub is a SinonSpy or SinonStub that was called exacly 3 times since it was created/reset
result checked value: methodSpy / methodStub
synonym: you may obmit to.have.been

@it('should call demo 3 times')
callDemo( @spy(ExpectTest, 'demo') demoSpy: SinonSpy): TR {
    ExpectTest.demo()
    ExpectTest.demo()
    ExpectTest.demo()
    expect(demospy).to.have.been.calledThrice
    expect(demospy).to.have.been.calledThrice.not.calledOnce
}

to.have.been.called

expect(methodSpy).to.have.been.called
expect(methodStub).to.have.been.called

validation: The given methodSpy or methodStub is a SinonSpy or SinonStub that was called at least once since it was created/reset
result checked value: methodSpy / methodStub
synonym: you may obmit to.have.been

@it('should call demo')
callDemo( @spy(ExpectTest, 'demo') demoSpy: SinonSpy): TR {
    expect(demospy).to.not.have.been.called
    ExpectTest.demo()
    expect(demospy).to.have.been.called
    ExpectTest.demo()
    ExpectTest.demo()
    expect(demospy).to.have.been.called.calledThrice
}

to.have.been.calledWith

expect(methodSpy).to.have.been.calledWith(args)
expect(methodStub).to.have.been.calledWith(args)

validation: The given methodSpy or methodStub is a SinonSpy or SinonStub that had a call with the given arguments
result checked value: methodSpy / methodStub
synonym: you may obmit to.have.been

@it('should call demo1 with expected arguments')
callDemo( @spy(ExpectTest, 'demo1') demo1Spy: SinonSpy): TR {
    ExpectTest.demo1(12,"a")
    expect(demo1spy).to.have.been.calledWith(12,"a")
    expect(demo1spy).to.have.been.calledOnce.calledWith(12)
    ExpectTest.demo1(13,"b")
    expect(demo1spy).to.have.been.calledWith(12,"a").calledWith(13,"b").calledTwice
}

to.have.been.calledWithMatch

expect(methodSpy).to.have.been.calledWithMatch(args)
expect(methodStub).to.have.been.calledWithMatch(args)

validation: The given methodSpy or methodStub is a SinonSpy or SinonStub that had a call with the given arguments. For object argument, you don't need to specify all properties to have a match
result checked value: methodSpy / methodStub
synonym: you may obmit to.have.been

@it('should call demo2 with expected arguments')
callDemo( @spy(ExpectTest, 'demo2') demo2Spy: SinonSpy): TR {
    ExpectTest.demo2({a:'a',b:12},12)
    expect(demo2spy).to.have.been.calledWithMatch({b:12},12)
    expect(demo1spy).to.have.been.calledWithMatch({a:'a'}).calledOnce
}

to.have.been.calledWithNew

expect(constructorSpy).to.have.been.calledWithNew
expect(constructorStub).to.have.been.calledWithNew

validation: The given constructorSpy or constructorStub is a class constructor that was called (using the new keyword)
result check value: constructorSpy / constructorStub

import { DerivedClass } from './class'
...
@it('should call DerivedClass with new keyword')
createDerviedClass( @spy('./class','DerviedClass') derivedclassSpy: SinonSpy): TR {
    const dc = new DerivedClass()
    expect(derivedclassSpy).to.have.been.calledWithNew
    expect(dc).to.be.instanceOf(DerivedClass)
    expect(derivedclassSpy).to.have.been.calledWithNew.calledOnce
}

Promise

to.eventually.be.fulfilled

await expect(promise).to.eventually.be.fulfilled

validation: The given promise is a promise. The action awaits for the promise to be resolved, and validate it is resolved. Validation fails if and when the promise is rejected.
result check value: promise with the eventually flag
await return value: the resolution value.
synonym: you may obmit to and/or be
when using fulfilled you may obmit eventually

await expect( Promise.resolve() ).to.eventually.be.fulfilled
await expect( Promise.resolve() ).to.eventually.be.fulfilled.fulfilled
const rv = await expect( Promise.resolve(12) ).to.eventually.be.fulfilled
expect(rv).to.equal(12)

to.eventually.be.equal

await expect(promise).to.eventually.be.euqal(value)

validation: The given promise is a promise. The action awaits for the promise to be resolved, and validate it was resolved with the given value. Validation fails if and when the promise is rejected, or resolves with a differnt value.
result check value: promise with the eventually
await return value: the resolution value.
synonym: you may obmit to and/or be

await expect( Promise.resolve(12)).to.eventually.be.equal(12)
await expect( Promise.resolve(12)).to.eventually.be.equal(12).fulfilled
const rv = await expect( Promise.resolve(12) ).to.eventually.be.equal(12)
expect(rv).to.equal(12)

to.eventually.be.rejected

await expect(promise).to.eventually.be.rejected

validation: The given promise is a promise. The action awaits for the promise to be rejected, and validate it is rejected. Validation fails if and when the promise is resolved.
result check value: promise with the eventually flag, but resolved insted of rejected
await return value: the rejected value.
synonym: you may obmit to and/or be
when using rejected you may obmit eventually

await expect( Promise.reject() ).to.eventually.be.rejected
await expect( Promise.reject(12) ).to.eventually.be.rejected.to.equal(12)
const rv = await expect( Promise.reject(12) ).to.eventually.be.rejected
expect(rv).to.equal(12)

to.eventually.be.rejectedWith

await expect(promise).to.eventually.be.rejectedWith(value)

validation: The given promise is a promise. The action awaits for the promise to be rejected, and validate it is rejected with the given value or with an Error object that its message property is value. Validation fails if and when promise is resolved, or rejected with differnt value.
result check value: promise with the eventually flag, but resolved instead of rejected)
await return value: the rejected value.
synonym: you may obmit to and/or be
when using rejected you may obmit eventually

await( Promise.reject('kuku') ).to.eventually.be.rejectedWith('kuku')
await( Promise.reject(new Error('kuku')) ).to.eventually.be.rejectedWith('kuku')
await( Promise.reject('kuku') ).to.eventually.be.rejectedWith('kuku').to.equal('kuku')
await( Promise.reject(new Error('kuku')) ).to.eventually.be.rejectedWith('kuku').to.have.property('message','kuku')
let rv = await( Promise.reject('kuku') ).to.eventually.be.rejectedWith('kuku')
expect(rv).to.equal(rv)
let rv = await( Promise.reject(new Error('kuku')) ).to.eventually.be.rejectedWith('kuku')
expect(rv).to.have.property('message','kuku')

eventually keyword

You may use the eventually keyword when calling expect on a promise. After using the key work you may use all the regular properties and methods to validate the value the promise will be resolved to, after it is resolved. Validations with the eventually keywords need to we called with await to let the promise be resolved. If the promise is rejected the evalution fails (unless you used the rejected method, or the rejectedWith function).
You may get the return valeu on the await to get the resolved value, for more validations.
await expect(Promise.resolve(12)).to.eventually.equal(12)
await expect(Promise.resolve(13)).to.eventually.not.equal(12)
await expect(Promise.resolve({a:11})).to.eventually.exist
await expect(Promise.resolve({a:11})).to.eventually.be.an('object')
await expect(Promise.resolve({a:11})).to.eventually.have.property('a',11)
await expect(Promise.resolve(true)).to.eventually.be.true
await expect(Promise.resolve(100)).to.eventually.be.above(10)
const rv = await expect(Promise.resolve(100)).to.eventually.not.be.below(100)
expect(rv).to.equal(100)

⚠️ **GitHub.com Fallback** ⚠️