fake-timers icon indicating copy to clipboard operation
fake-timers copied to clipboard

Event timeStamp not using fake-timers

Open mansona opened this issue 3 years ago • 4 comments

We understand you have a problem and are in a hurry, but please provide us with some info to make it much more likely for your issue to be understood, worked on and resolved quickly.

  • FakeTimers version : latest
  • Environment : Browser
  • Example URL : https://github.com/sinonjs/fake-timers/pull/433
  • Other libraries you are using: none

What did you expect to happen?

I'm trying to create 2 events with a certain time between them:

    window.dispatchEvent(new KeyboardEvent('keypress', { key: 'A' }));
    this.clock.tick(70);
    window.dispatchEvent(new KeyboardEvent('keypress', { key: 'B' }));

and then if I checked the difference of those timestamps I was expecting that they be exactly 70ms apart:

const eventDiff = secondEvent.timeStamp - firstEvent.timeStamp;
assert.equals(eventDiff, 150);

What actually happens

The Events seem to just ignore the fake-timer implementation.

How to reproduce

See https://github.com/sinonjs/fake-timers/pull/433

mansona avatar Jun 14 '22 13:06 mansona

Oooh, I wonder if we are able to fix that. If they maintain a reference to an internal clock, the answer is no.

fatso83 avatar Jun 14 '22 15:06 fatso83

well that's exactly why I asked here @fatso83 😂 I figured someone might be able to shed some light on it. I was trying to find some details on how that timeStamp is generated online but I kinda don't know what I'm looking for and didn't get very far 😞

mansona avatar Jun 14 '22 15:06 mansona

We can (probably) mock KeyboardEvent.prototype.timeStamp to return the fake time?

benjamingr avatar Jun 14 '22 19:06 benjamingr

I would say that faking UI event code in the browser is actually not a core feature of fake-timers, so not sure we should spend time implement it, but I think this is a pretty valid use case we could at least document how one could implement. I had never heard of it, so I researched this a bit on MDN and it seems that KeyboardEvent < UIEvent < Event and the timeStamp comes from the top of the hierarchy: the Event class.

This value is the number of milliseconds elapsed from the beginning of the time origin until the event was created. If the global object is Window, the time origin is the moment the user clicked on the link, or the script that initiated the loading of the document

That means we would just need to replace thetimeStamp field is with a something that returns something we want, like the current clock time in ms. When playing in DevTools right now on this page, I could see this working fine:

// Set up something to capture events for us to play with in DevTools console
document.getElementById('new_comment_field').addEventListener('keyup', function(args) { console.log(args); })

// replace the `timeStamp` on the prototype
// use `sinon.replace()` or similar if you want restore functionality
Object.defineProperty(window.Event.prototype, 'timeStamp', { get(){ return 101; } })

So if you then replace 101 in the code above with Date.now() for instance, your test should work just fine. Skjermbilde 2022-06-17 kl  21 35 19 Skjermbilde 2022-06-17 kl  21 35 32

fatso83 avatar Jun 17 '22 19:06 fatso83

Closed as a workaround exists for a niche issue.

fatso83 avatar Oct 05 '23 21:10 fatso83