关于Cypress clock()与tick()的使用疑问:React测试失效排查
Ah, I see the issue here—you're calling cy.clock() after your app has already initialized, which means the setTimeout in your React component has already been registered with the browser's native timer API, not Cypress's mocked one.
The Fix: Start the clock before visiting your app
Cypress's cy.clock() works by replacing the browser's native setTimeout, setInterval, etc., with its own mocked implementations. For this to affect your component's timer, you need to start the clock before your app mounts and creates that setTimeout.
Here's the corrected test code:
describe("My Input",()=>{ beforeEach(()=>{ cy.clock() // Initialize Cypress's clock FIRST cy.visit('/') // Then load the app, which will now use the mocked timer }) it("should get a value of foo after 20 seconds",()=>{ cy.tick(20000); // Fast-forward the mocked timer cy.get('[data-cy=my-input]').should('have.value','foo'); }) })
Why your original code didn't work
In your initial test, you called cy.visit() first. By the time you ran cy.clock(), your React component had already mounted, executed the useEffect, and registered the 20-second timeout with the real browser timer. Cypress can't retroactively take control of timers that were created before cy.clock() was called.
Even the variation where you used cy.clock().then(clock => clock.tick(20000)) failed for the same reason—you were still starting the clock after the app had already set up the timer.
Alternative: Start clock within the test block
If you don't want to initialize the clock for every test in the beforeEach, you can also do it directly in the test case:
it("should get a value of foo after 20 seconds",()=>{ cy.clock() cy.visit('/') cy.tick(20000); cy.get('[data-cy=my-input]').should('have.value','foo'); })
Either way, the key is ensuring cy.clock() runs before your app's code has a chance to create any timers.
内容的提问来源于stack exchange,提问作者itaydafna

