sinonjs / fake-timers

Fake setTimeout and friends (collectively known as "timers"). Useful in your JavaScript tests. Extracted from Sinon.JS
BSD 3-Clause "New" or "Revised" License
802 stars 105 forks source link

Inconsistent behavior with varying 'now' timestamps in config for FakeTimers.install({ now: <timestamp>, shouldAdvanceTime: true }) #339

Closed daniel-mina97 closed 3 years ago

daniel-mina97 commented 3 years ago

Background I have some ETL (extract, transform, load) code that uses the bottleneck library to throttle some API calls. I am testing this code using nocks (will intercept the API calls and provide some mock data) and jest. For one of my end-to-end tests, I have a transform step that uses the current date to calculate days since an epoch timestamp. I am wanting to mock this "current date" to the epoch timestamp 1601488969000 (Sep 30, 2020) and also allow the bottleneck library to work correctly with its timers. In the end, I should have an object with a keyDaysSinceCreated based on the mocked "current date".

What did you expect to happen? My tests should complete with the thottling/timers in bottleneck going off when the 'now' timestamp is 1601488969000.

What actually happens The test does NOT complete when I set the 'now' timestamp to 1601488969000 or anything near to that - but strangely does complete with other timestamps.

I have the following in my jest test code:

describe(test, () => {
  beforeAll(() => {
    clock = FakeTimers.install({ now: timestamp, shouldAdvanceTime: true });
  });
...
});

When replacing timestamp above with 160148896900 or 16014889690000 (notice the number of zeroes at the end), the tests complete successfully, and in my final object I have a key DaysSinceCreated with the values -16666 and 166838 respectively. However, when I replace timestamp with 1601488969000, the tests never complete, which seems to be due to the timers in Bottleneck not launching for some reason. This seems like weird behavior that the timers and tests are functioning as expected for some timestamps, but not others. Any help and/or guidance would be appreciated!

Note: I'm kind of limited as to what code I can post on here, but please let me know what other information could be helpful and I'll provide as much as I can. Thanks!

benjamingr commented 3 years ago

It's going to be very hard to debug this without a reproduction.

daniel-mina97 commented 3 years ago

I'm working on creating a small dummy project to reproduce this. I'll add the link to it once I have it made.

daniel-mina97 commented 3 years ago

Okay here's a link (https://github.com/daniel-mina97/FakeTimers) to a sample project where I can reproduce the problem. All you have to do after installing the dependencies is run yarn test to see the failing test. In the actual test file I have some different timestamps that you can swap in.

daniel-mina97 commented 3 years ago

After messing around with it some more, I think the core problem is in the bottleneck library. If instead of using fake-timers I just use jest to mock Date.now to return the timestamp, the tests also get hung up. For some reason moving the bottleneck instance inside of the function (as described in the README at https://github.com/daniel-mina97/FakeTimers) fixes both problems... I'll go ahead and close this as I don't think the issue is on y'all's side of things