Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

eventually implies fulfilled #223

Open
hsablonniere opened this issue Sep 21, 2017 · 2 comments
Open

eventually implies fulfilled #223

hsablonniere opened this issue Sep 21, 2017 · 2 comments

Comments

@hsablonniere
Copy link

Hey chai-as-promised team 馃槃

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?
  • 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 馃槈

@meeber
Copy link
Contributor

meeber commented Sep 23, 2017

Basically, I'm wondering why using expect().to.eventually.equal() and expect().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.

@brocoli
Copy link

brocoli commented Apr 26, 2018

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()?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants