chai-as-promised
chai-as-promised copied to clipboard
eventually implies fulfilled
Hey chai-as-promised team :smile:
The setup
- Node: 7.9.0
- Mocha: 3.5.3
- Chai: 4.1.2
- Chai-as-promised: 7.1.1
The situation
Basically, I'm wondering why using expect().to.eventually.equal()
and expect().to.be.fulfilled.and.eventually.equal()
behave differently.
Here's my reduced test case:
function someFunction(reject = false) {
if (reject) {
return Promise.reject(new TypeError('NOTOK'))
}
return Promise.resolve('OK')
}
describe.only('someFunction()', () => {
it('should resolve OK', () => {
const result = someFunction()
return expect(result).to.be.eventually.equal('OK')
})
it('should reject NOTOK', () => {
const result = someFunction(true)
return expect(result).to.be.rejectedWith('NOTOK')
})
it('should reject NOTOK', () => {
const result = someFunction(true)
return expect(result).to.eventually.equal('OK')
})
it('should reject NOTOK', () => {
const result = someFunction(true)
return expect(result).to.be.fulfilled.and.eventually.equal('OK')
})
})
The first two tests pass as expected.
The third test gives me the TypeError with a stack trace to the line where the TypeError was thrown (inside the tested function).
1) someFunction() should reject NOTOK:
TypeError: NOTOK
at ...
The fourth test warns me about a failed assertion which is the behaviour I'm waiting for.
2) someFunction() should reject NOTOK:
AssertionError: expected promise to be fulfilled but it was rejected with 'TypeError: NOTOK'
My questions
- Is it normal to have 2 different behaviours? What do you think?
- By reading #185, I though
eventually.equals
implied a fulfilled promise.
- By reading #185, I though
- Would it be OK to always log an AssertionError when an "implied fulfilled" promise is rejected?
It it's something that should be fixed, I can try to work on a PR but I may need a few hints.
Thanks for you help :wink:
Basically, I'm wondering why using
expect().to.eventually.equal()
andexpect().to.be.fulfilled.and.eventually.equal()
behave differently.
@hsablonniere In the case of expect().to.be.fulfilled.and.eventually.equal()
, an assertion is explicitly performed to check whether or not the promise is fulfilled. When this assertion fails, you get the explicit "expected promise to be fulfilled but it was rejected" message.
In the case of expect().to.eventually.equal()
, no such explicit assertion is performed to verify that the promise is fulfilled. However, the wiring of chai-as-promised
requires the promise to be fulfilled in order for overwritten assertions such as .equal
to even get called. Because .equal
is never called, it ends up being the rejected promise itself that is returned to the test runner, signaling the test has failed.
I think it's an interesting idea for chai-as-promised
to return an AssertionError
with the message "expected promise to be fulfilled but it was rejected" even when no explicit fulfillment check is performed. This might be achievable by adding a .catch
here that checks to see if the reason for the rejected promise is an AssertionError
, and if it's not, then it throws an AssertionError
. But this plugin belongs to @domenic; it's his call if he wants to pursue this further.
Just a small note:
In your tests you're using pre-fulfilled/rejected promises, but when using pending promises, I think it is correct that should.eventually.equal()
and should.be.fulfilled.and.eventually.equal()
behave differently.
The first one allows the promise to be pending, as long as it becomes fulfilled before the test timeouts.
The second one does not, it checks immediately if the promise is fulfilled.
The test that should be equivalent to should.eventually.equal()
is should.eventually.be.fulfilled.and.eventually.equal()
EDIT: or maybe it should be should.eventually.be.fulfilled.and.equal()
?