Skip to main content
Cypress App

clock

cy.clock() overrides native global functions related to time allowing them to be controlled synchronously via cy.tick() or the yielded clock object. By default, this includes controlling:

  • setTimeout and clearTimeout
  • setInterval and clearInterval
  • requestAnimationFrame and cancelAnimationFrame
  • requestIdleCallback
  • Date objects
  • performance, such as performance.now()
  • Intl.DateTimeFormat, which formats the faked current time when no date is passed

The clock starts at the unix epoch (timestamp of 0) unless you pass a now value. Without a now value, new Date in your application returns a time of January 1st, 1970.

Syntax​

cy.clock()
cy.clock(now)
cy.clock(now, functionNames)
cy.clock(options)
cy.clock(now, options)
cy.clock(now, functionNames, options)

Usage​

Correct Usage

cy.clock()

Arguments​

now (number, Date)

A timestamp or Date object specifying where the clock should start. Pass 0 (or null) to start at the unix epoch while still passing functionNames.

functionNames (Array)

Names of the native functions the clock should override. When omitted, or when passed an empty array, cy.clock() overrides the default set listed above. Valid names are setTimeout, clearTimeout, setInterval, clearInterval, Date, requestAnimationFrame, cancelAnimationFrame, requestIdleCallback, cancelIdleCallback, performance, and Intl.

options (Object)

Pass in an options object to change the default behavior of cy.clock().

OptionDefaultDescription
logtrueDisplays the command in the Command log

Yields ​

cy.clock() yields a clock object with the following methods. If a clock already exists in the current test, cy.clock() yields that existing clock and ignores any arguments passed to it.

  • clock.tick(milliseconds)

    Move the clock the specified number of milliseconds. Any timers within the affected range of time are called.

  • clock.restore()

    Restore all overridden native functions. This is automatically called between tests, so should not generally be needed.

    clock.restore() returns native timer APIs (setTimeout, setInterval, etc.) to the window. New timers created after restore() run in real time. Timers registered while the fake clock was active are discarded and don't resume automatically.

  • clock.setSystemTime(now)

    Change the system time to the new now. Now can be a timestamp, date object, or not passed in which defaults to 0. It doesn't call any timers or change the time left before they trigger.

You can also access the clock object via this.clock in a .then() callback, as long as the test is written with a function () {} callback rather than an arrow function, so this refers to the test context.

Examples​

No Args​

Create a clock and use it to trigger a setInterval​

src/timer.js
let seconds = 0

setInterval(() => {
$('#seconds-elapsed').text(++seconds + ' seconds')
}, 1000)
cypress/e2e/timer.cy.js
cy.clock()
cy.visit('/index.html')
cy.tick(1000)
cy.get('#seconds-elapsed').should('have.text', '1 seconds')
cy.tick(1000)
cy.get('#seconds-elapsed').should('have.text', '2 seconds')

Test a debounced search input with cy.clock()​

A debounced input waits for the user to stop typing before it acts. With cy.clock(), you control exactly when that wait ends, so you can assert both that nothing happens too early and that the request fires on time.

src/search.js
let debounceTimer

$('#search').on('input', (e) => {
clearTimeout(debounceTimer)
debounceTimer = setTimeout(() => {
fetch(`/api/search?q=${e.target.value}`)
}, 300)
})
cypress/e2e/search.cy.js
cy.intercept('GET', '/api/search*').as('search')
cy.clock()
cy.visit('/products')
cy.get('#search').type('shoes')
// the debounce hasn't elapsed, so no request has been sent
cy.get('@search.all').should('have.length', 0)
cy.tick(300)
cy.wait('@search')

Test an inactivity timeout with cy.clock()​

Session expiry warnings and automatic logouts often wait many minutes before they trigger. Move the clock forward instead of waiting in real time.

cy.clock()
cy.visit('/dashboard')
cy.tick(15 * 60 * 1000) // 15 minutes
cy.contains('Your session has expired').should('be.visible')

Access the clock object to synchronously move time​

In most cases, it's easier to use cy.tick() to move time, but you can also use the clock object yielded by cy.clock().

cy.clock().then((clock) => {
clock.tick(1000)
})

You can call cy.clock() again for this purpose later in a chain if necessary. It yields the clock that already exists and ignores any arguments, so it can't change now or functionNames. Use clock.setSystemTime() to change the current time.

cy.clock()
cy.get('input').type('Jane Lane')
cy.clock().then((clock) => {
clock.tick(1000)
})

The clock object is also available via this.clock in any .then() callback. Use a function () {} test callback so this refers to the test context.

it('ticks the clock', function () {
cy.clock()
cy.get('form').then(($form) => {
this.clock.tick(1000)
// do something with $form ...
})
})

Access the clock object to restore native functions​

In general, it should not be necessary to manually restore the native functions that cy.clock() overrides since this is done automatically between tests. But if you need to, the clock object yield has a .restore() method.

cy.clock().then((clock) => {
clock.restore()
})

Or via this.clock:

it('restores the clock', function () {
cy.clock()
cy.get('.timer').then(($timer) => {
this.clock.restore()
// do something with $timer ...
})
})

Now​

Specify a now timestamp​

const now = new Date(2021, 3, 14) // month is 0-indexed

cy.clock(now)
cy.visit('/index.html')
cy.get('#date').should('have.value', '04/14/2021')

Start every test on the same date with cy.clock()​

Call cy.clock() in a beforeEach() hook so every test sees the same current date. Cypress restores the clock automatically after each test, so each test starts with a fresh clock set to the same now.

beforeEach(() => {
cy.clock(Date.UTC(2026, 0, 15))
cy.visit('/reports')
})

Test a midnight date rollover with cy.clock()​

Combine a now value with cy.tick() to test what happens when time crosses a boundary, such as midnight. This example assumes the app updates its displayed date on a timer.

cy.clock(new Date(2026, 0, 31, 23, 59, 59)) // one second before midnight
cy.visit('/calendar')
cy.get('#today').should('contain', 'January 31')
cy.tick(1000)
cy.get('#today').should('contain', 'February 1')

Function names​

Specify which functions to override​

This example overrides only setTimeout and clearTimeout and leaves the other time-related functions as they are.

cy.clock(null, ['setTimeout', 'clearTimeout'])

You must specify Date to override the current datetime. The example below affects the current datetime without affecting scheduled timers.

cy.clock(Date.UTC(2018, 10, 30), ['Date'])

Freeze the date and keep animations running with cy.clock()​

By default, cy.clock() also overrides requestAnimationFrame, so JavaScript animations and any rendering that relies on animation frames only advance when you call cy.tick(). To freeze the date and control timeouts while leaving animation frames running in real time, list only the functions you want to override.

cy.clock(Date.UTC(2026, 0, 1), ['Date', 'setTimeout', 'clearTimeout'])

Using cy.clock() with cy.tick()​

Restore clock​

You can restore the clock and allow your application to resume normally without manipulating native global functions related to time. This is automatically called between tests.

caution

clock.restore() returns native timer APIs (setTimeout, setInterval, etc.) to the window. New timers created after restore() run in real time. Timers registered while the fake clock was active are discarded and don't resume automatically. If your application code needs to keep running after restore(), it must re-register those timers itself. Timers your application registered before cy.clock() was called were never faked, so they keep running in real time.

cy.clock()
cy.visit('http://localhost:3333')
cy.get('#search').type('Acme Company')
cy.tick(1000)
// more test code here

// restore the clock
cy.clock().then((clock) => {
clock.restore()
})
// more test code here

You could also restore by using .invoke() to invoke the restore function.

cy.clock().invoke('restore')

Change current system time​

This example tests that a timer still displays correctly after it has run for an hour, without triggering an hour's worth of setInterval or requestAnimationFrame callbacks and overloading your CPU.

cy.clock(0)
cy.visit('http://localhost:3333')
cy.clock().then((clock) => {
clock.setSystemTime(60 * 60 * 1000 - 60)
// setSystemTime doesn't trigger any timers, so we run the last frame
// with tick to trigger a callback to update the timer.
clock.tick(60)
})
// the timer shows an hour has passed and still fits on the page
cy.get('#timer').should('contain', '1:00:00').and('be.visible')
// more test code here

You could also change the system time by using .invoke() to invoke the setSystemTime function.

cy.clock().invoke('setSystemTime', 60 * 60 * 1000)

Notes​

iframes​

iframes not supported​

cy.clock() only applies to the top window on a web page. It doesn't override the time functions of any iframe embedded on the page.

Behavior​

CSS animations and transitions ignore cy.clock()​

cy.clock() overrides JavaScript time functions only. CSS animations and CSS transitions run on the browser's own clock, so they keep playing in real time and cy.tick() doesn't move them forward.

clock behavior before cy.mount()​

Using the cy.mount() command in a Cypress Component Test renders your component but doesn't affect the behavior of the page or window object. This means you can mount directly after calling cy.clock() to test the component against any changes you've made to the yielded clock object.

clock behavior before cy.visit()​

If you call cy.clock() before visiting a page with cy.visit(), Cypress overrides the page's native global functions on window load, before any of your app code runs. So even if setTimeout, for example, is called on page load, it can still be controlled via cy.tick(). This also applies if, during the course of a test, the page under test is reloaded or changed.

Each new page gets a fresh fake clock that starts again at the original now value (or the unix epoch). Time you advanced with cy.tick() on the previous page and timers it registered don't carry over to the new page.

Rules​

Requirements ​

  • cy.clock() requires being chained off of cy.

Assertions ​

  • cy.clock() is a utility command.
  • cy.clock() will not run assertions. Assertions will pass through as if this command did not exist.

Timeouts ​

  • cy.clock() cannot time out.

Command Log​

Create a clock and tick it 1 second

cy.clock()
cy.tick(1000)

The command above displays in the Command Log as:

Command Log clock

When clicking on the clock command within the command log, the console outputs the following:

console.log clock command

History​

VersionChanges
10.7.0Added setSystemTime to yielded clock object

See also​