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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: Jest should expose @sinonjs/fake-timers async APIs #13435

Closed
yjaaidi opened this issue Oct 12, 2022 · 6 comments · Fixed by #13981
Closed

[Feature]: Jest should expose @sinonjs/fake-timers async APIs #13435

yjaaidi opened this issue Oct 12, 2022 · 6 comments · Fixed by #13981

Comments

@yjaaidi
Copy link

yjaaidi commented Oct 12, 2022

🚀 Feature Proposal

Jest should expose @sinonjs/fake-timers async APIs: tickAsync(time), nextAsync(), runAllAsync() & runToLastAsync().

Motivation

There are circumstances where microtasks should be flushed between different timers.
This will often happen when the system under test is mixing microtasks (promises, async / await) and timers.

🚫 Here is an example that will not work:

const spy = jest.fn();

setTimeout(async () => {
  await Promise.resolve();
  setTimeout(spy, 10);
}, 10);

jest.advanceTimersByTime(20);

expect(spy).toBeCalled();

🫤 The common way of testing this with jest needs coupling the test to implementation details as one must know that they have to advance the timer, flush some microtasks and advance the second timer with a logic similar to this one.

const spy = jest.fn();

setTimeout(async () => {
  await Promise.resolve();
  setTimeout(spy, 10);
}, 10);

jest.advanceTimersByTime(10);
await flushMicrotasks()
jest.advanceTimersByTime(10);

expect(spy).toBeCalled();

where one must implement a custom function like this one to manually flush microtasks:

async function flushMicrotasks() {
  await new Promise(resolve => jest.requireActual('timers').setImmediate(resolve));
}

✅ Sinon's async API makes it easier as it will flush microtasks when necessary:

const spy = jest.fn();

setTimeout(async () => {
  await Promise.resolve();
  setTimeout(spy, 10);
}, 10);

await clock.tickAsync(20);

expect(spy).toBeCalled();

Example

This could look like this:

const spy = jest.fn();

setTimeout(async () => {
  await Promise.resolve();
  setTimeout(spy, 10);
}, 10);

await jest.tickAsync(20);

expect(spy).toBeCalled();

Pitch

While this will of course increase the Jest surface, this will help with:

  • making the tests more maintainable & stable
  • not having to manually set up sinon fake timers as it's hard to decide when one should use jest timers or sinon's
  • encourage developers to write tests

Cf. related issues & problems

@github-actions
Copy link

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.

@github-actions github-actions bot added the Stale label Nov 11, 2022
@SimenB
Copy link
Member

SimenB commented Nov 11, 2022

Happy to take a PR adding this 👍

@SimenB SimenB added Help Wanted and removed Stale labels Nov 11, 2022
@yjaaidi
Copy link
Author

yjaaidi commented Nov 30, 2022

Hi @SimenB! Sorry that I just noticed your reply.
I'll be happy to help with a PR as soon as I can!

@github-actions
Copy link

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.

@SimenB
Copy link
Member

SimenB commented Mar 6, 2023

@github-actions
Copy link

github-actions bot commented Apr 6, 2023

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants