FakeTimers don't work with nested promises
- Dominant language
- TypeScript
- Stars
- 45.5k
- Forks
- 6.7k
- Avg merge
- 17h 22m
- Merged PRs (30d)
- 24
Description
## 🐛 Bug Report
## To Reproduce
```js
test("jest bug", async () => {
jest.useFakeTimers();
const fn = jest.fn();
const mainPromise = Promise.resolve(5);
const waitPromise = new Promise(resolve => setTimeout(() => resolve(mainPromise), 100));
waitPromise.then(fn); // this must be called after 100ms timeout is finished
expect(setTimeout).toBeCalled(); // it works
jest.advanceTimersToNextTimer();
await Promise.resolve(); // wait for previous promiseThen execution
expect(fn).toBeCalled(); // it doesn't work
});
```
## Expected behavior
The **fn** to be called
## envinfo
System:
OS: Windows 10 10.0.18363
CPU: (12) x64 Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
Binaries:
Node: 13.10.1 - C:\Program Files\nodejs\node.EXE
npm: 6.13.7 - C:\Program Files\nodejs\npm.CMD
npmPackages:
jest: ^25.2.0 => 25.2.0
## Notes
The similar behavior without nested setTimeout-promise works fine
``` js
test("jest no bug", async () => {
jest.useFakeTimers();
const fn = jest.fn();
const waitPromise = new Promise(resolve => setTimeout(() => resolve(5), 100)).then(fn);
waitPromise.then(fn);
expect(setTimeout).toBeCalled(); // it works
jest.advanceTimersToNextTimer();
await Promise.resolve(); // wait for previous promiseThen exectution
expect(fn).toBeCalled(); // it works!!!
});
```
```
Contributor guide
Research direction
Start by running the nested-promise reproduction with fake timers and compare it with the non-nested example in the issue. Trace fake-timer advancement and promise callbacks, then add a regression test showing that fn is called after the 100ms timer and nested promise chain complete.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100