Cy Clock and RxJS timers #26868
Replies: 2 comments 1 reply
-
Hi @medchat-layton, To work around this problem, you can use cy.tick() to manually advance time in the Cypress environment. cy.tick() simulates the passage of time by running all pending timers until the specified time has been reached. This allows you to trigger the timers in your application that depend on the system clock. It's important to note that Cypress replaces the browser's native timers with its own implementation, which gives it control over time in the testing environment. This means that when you use cy.tick(), you're advancing time in the Cypress environment rather than the actual system clock. The timers in your application, including those from third-party libraries like RxJS, will be controlled by the Cypress timer implementation. The behavior you described, where you need to use cy.clock() or cy.tick() to test transitions between active and inactive periods, is a valid use case. By setting the system time and then using cy.tick() to advance time, you can trigger the necessary updates in your application and verify the expected behavior. |
Beta Was this translation helpful? Give feedback.
-
Yeah this has become apparent to me now. I read the docs on this several times but what still is not clear to me from reading them (though abundantly clear now that I've figured it out) is that the cypress timeout implementation is not coupled in any way to the system time. There's an example in there mentioning this but I don't feel like how cypress handles timers is very clear. I'd love to see a documentation update along the following lines:
That's a little rough around the edges, but I already typed this once and the browser crashed so I don't have the time to write it beautifully again 😅 Hope this is helpful. Thanks again for the clarification. |
Beta Was this translation helpful? Give feedback.
-
We have a medium-to-large sized enterprise application that we've been building for about 6 or 7 years. Cypress came along for us early-ish on in the process of building it and changed everything.
However, one of the curious problems we've always had has been issues with cy.clock. I always figured that between app update checking (long polled), certain auth-related timers, and third party libs, there was something that never quite could make any of our tests using cy.clock reliable. Without fail they would be flakey.
That said I finally came across a scenario where I absolutely require cy.clock, so I decided to try to tackle this problem. The issue, it seems, stems from a poor understanding of how Cypress handles time control vs how the internals of libraries like rxjs work.
I'll say this up front - I won't be able to provide code examples here for reasons of NDA/security, as well as the fact that the application is just too large to make figuring out reproducible scenarios - which I'm not sure I can even do, because I'm still fuzzy on the problem - a feasible task. Sorry in advance for that.
However I think a conceptual discussion is still very viable. Basically, I have an experience where users can send messages between each other, however there are "active time periods" (think of them as business hours, basically). These are long-running periods that span many hours, across any day of the week.
In order to test switches from active to inactive periods, I need to use cy.clock (or stub extremely small time periods but still would have to wait several seconds to test all of the scenarios I want to test). Basically, launch the app in an "inactive" period, then setSystemTime to an active one, etc.
The components that respond to this have a scheduling mechanism that, upon crossing a window boundary, check active state and the UI updates from there. Pretty straightforward. These window boundaries are detected using rxjs timers.
What I understand is that calling
clock.setSystemTime
doesn't tick timers. What was NOT clear from the documentation, however, was that in order to fire a timer, you seem to have to tick the entire duration of the timer. You can't justsetSystemTime
and thentick(100)
to trick the timers into thinking they've ticked ahead.I'm confused on how cypress handles this internally. Given that it hijacks the browser's internal setTimeout/setInterval/etc etc systems, is there anyone who could shed light on the difference between setting system time manually, which doesnt trigger timers, and just using tick to do so? Because it looks a lot like I need to use tick no matter what since our app will literally crash in test if we don't due to critical timers in various sub-systems that keep certain parts of the app running.
Would love any light being shed on these questions.
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions