I'm trying to use chai-as-promised in my Mocha test for some typescript code. I can't quite get the syntax right. So I setup a minimal reproducer:
// Sample promise that resolves on red, fails on other values
export const getRedColor = async (color: string): Promise<string> =>
new Promise((resolve, reject) => {
setTimeout(() => {
if (color === 'red') {
resolve(color);
} else {
reject(new Error(`You picked ${color}, should be red`));
}
}, 1000);
});
First I used async/await to write a test as control, the first 2 pass, the second two are designed to fail.
import * as chai from 'chai';
import { expect } from 'chai';
import 'mocha';
import chaiAsPromised from 'chai-as-promised';
import { getRedColor, isRedColor } from '../src/index';
import { describe } from 'mocha';
describe('Testing failing promises with async/await', () => {
it('should pass on red', async () => {
let result = await getRedColor('red');
expect(result).to.equal('red');
});
it('should throw on blue', async () => {
try {
let result = await getRedColor('blue');
expect.fail('SHould not succeed');
} catch (e: any) {
expect(e.message).to.equal('You picked blue, should be red');
}
});
// Deliberately failing
it('should fail on blue', async () => {
let result = await getRedColor('blue');
expect(result).to.equal('blue');
});
// Deliberately failing
it('should throw on red', async () => {
try {
let result = await getRedColor('red');
expect.fail('Should not succeed');
} catch (e: any) {
expect(e.message).to.equal('You picked red, should be red');
}
});
});
then (in the same file) the same (2 pass/2fail) in chai syntax
describe('Testing failing promises chai-as-promised', () => {
it('should pass on red', () => {
let result = getRedColor('red');
expect(result).to.eventually.equal('red');
});
it('should throw on blue', () => {
let result = getRedColor('blue');
expect(result).to.eventually.rejectedWith('You picked blue, should be red');
});
// Deliberately failing
it('should fail expecting rejection on red', () => {
let result = getRedColor('red');
expect(result).to.eventually.rejected;
});
// Deliberately failing
it('should fail resulting in blue', () => {
let result = getRedColor('blue');
expect(result).to.eventually.eql('blue');
});
});
All test pass - so I must do something wrong. I also checked the documentation which suggests to alter the test to
// Deliberately failing
it('should fail resulting in blue', () => {
let result = getRedColor('blue');
return result.to.eventually.eql('blue');
});
but that leads to an Error
TypeError: Cannot read properties of undefined (reading 'eventually')
What do I miss?
I was close. Missing was either a return statement or a call to notify. These is the working code in return
and notify()
flavor:
describe('Testing failing promises chai-as-promised', () => {
it('should pass on red', () => {
let result = getRedColor('red');
return expect(result).to.eventually.equal('red');
});
it('should throw on blue', () => {
let result = getRedColor('blue');
return expect(result).to.eventually.rejectedWith('You picked blue, should be red');
});
describe('Testing failing promises chai-as-promised', () => {
it('should pass on red', (done) => {
let result = getRedColor('red');
expect(result).to.eventually.equal('red').notify(done);
});
it('should throw on blue', (done) => {
let result = getRedColor('blue');
expect(result).to.eventually.rejectedWith('You picked blue, should be red').notify(done);
});
});
Hope that helps someone struggling with the same details