earl icon indicating copy to clipboard operation
earl copied to clipboard

Add waitForExpect functionality to earl

Open sz-piotr opened this issue 5 years ago • 9 comments

Maybe we can just re-export https://www.npmjs.com/package/wait-for-expect or copy the code directly https://github.com/TheBrainFamily/wait-for-expect/blob/master/src/index.ts.

It is great for testing async code and we could have a recipes section that teaches people how to do this.

And we could name the function wait

sz-piotr avatar Nov 23 '20 19:11 sz-piotr

I am all for adding it - usually, I implement something similar.

Perhaps it could be more general like wait for (async) function not to throw.

IMO it's related to https://github.com/earl-js/earl/issues/68 and is a good example on a util function.

krzkaczor avatar Nov 23 '20 19:11 krzkaczor

Would it be possible to integrate this with a testing framework in a way that, in case the test times out, waitForExpect would re-throw the last error, instead of failing with a generic "test timed out" message?

For me that seems to be the most painfull part when debugging tests with waitForExpect

dmaretskyi avatar Dec 01 '20 20:12 dmaretskyi

Very interesting proposal. It would be cool to have it indeed...

Possible implementation:

  1. When wait is called:
  2. Read timeout T from mocha context
  3. Set mocha timeout to T + 1
  4. Do timeout detection inside wait based on T value and rethrow the correct error if timeout occurs. This basically bypasses mocha timeout mechanism.

After googling for 5 minutes I couldn't find a cleaner solution but I might be wrong. CC: @boneskull

EDIT: I just realized that with this approach you would need to measure execution time before wait. It gets even uglier 😆

krzkaczor avatar Dec 01 '20 20:12 krzkaczor

I don't understand what I'm being asked, if anything

boneskull avatar Dec 01 '20 20:12 boneskull

@boneskull sorry, let me clarify: we try to build wait function that will retry a piece of code until it works (or test runner timeouts). Something along these lines: https://www.npmjs.com/package/wait-for-expect

await waitForExpect(() => {
  expect(numberToChange).toEqual(100);
});

If this assertion fails, mocha will simply timeout with a not very helpful message. Now, we are trying to find a way to throw somehow our own custom message (rethrow last error from the fn that we awaited for?).

In the previous post, I presented a possible solution manipulating mocha's timeout value, It's not clean but perhaps it will work. My question is: can you think of a better way to implement this? Maybe there is a way to hook custom logic on timeout errors or something like this.

PS: earl is an assertion library that tries to be a test runner agnostic but we are focused on delivering the best possible DX for mocha.

krzkaczor avatar Dec 01 '20 20:12 krzkaczor

I don't see the point of setting Mocha's timeout to a value greater than (+1) whatever your assertion function uses; you could just disable the timeout altogether (this.timeout(0)).

otherwise there are several ways to do this "automatically"--which only suppress the timeout when needed--but none that do not require the user to at least configure something or pass a command-line option. root hook plugins or a custom interface may do the job... or just set the mocha timeout reasonably higher than whatever the max timeout in the assertion uses and use that value globally

boneskull avatar Dec 01 '20 20:12 boneskull

I don't see the point of setting Mocha's timeout to a value greater than (+1) whatever your assertion function uses; you could just disable the timeout altogether (this.timeout(0)).

I thought about cases when timeout happens due to reasons unrelated to the usage of wait fn. But yeah... I would prefer to avoid this at all.

otherwise there are several ways to do this "automatically"--which only suppress the timeout when needed--but none that do not require the user to at least configure something or pass a command-line option. root hook plugins or a custom interface may do the job...

Can you elaborate on how can we actually achieve this? Any docs/examples pointers would be awesome. We already require users to setup test runner integration (ie. --require "earljs/mocha" which uses mochaGlobalSetup) for some extra features so this is not a problem.

krzkaczor avatar Dec 01 '20 20:12 krzkaczor

Disabling mocha test timeout once we start waiting, and the re-enabling it to the previous value after waitForExpect's promise has been resolved/rejected seems like the cleanest approach to me.

This can even be done without any additional configuration from the user.

dmaretskyi avatar Dec 02 '20 20:12 dmaretskyi

(btw mochaGlobalSetup will be changing slightly in next major. it will run before any test files are loaded. right now it's run after files are loaded but before tests begin)

boneskull avatar Dec 02 '20 21:12 boneskull

Closing this as we aren't planning to add this functionality for the foreseeable future.

sz-piotr avatar Mar 19 '23 13:03 sz-piotr