Cy.tick() broken in Cypress tests

I’m testing that a timeout screen appears after 5 seconds with Cypress’ cy.tick() mocking. However, the test fails and the timeout screen appears after the Cypress timeout. I have used cy.tick() successfully in other tests, so I know I’m using it correctly:

describe('successful request', () => {
  beforeEach(() => {
    cy.clock();
    // ... other setup ...
  });

  describe('request timed out (no WS response after 5 secs)', () => {
    it('shows a timeout error when the HTTP request succeeds but a WS verification is not received', () => {
      cy.tick(5000);
      cy.contains('Timed out');
    });
  });
});

The app code works correctly:

export const handleStatusMessage = (message: MessageEvent): ThunkAction =>
  (dispatch: ThunkDispatch<{}, {}, any>, getState: () => AppState) => {
    const { status }: StatusMessage = JSON.parse(message.data);

    // clear the timer, that we set last time
    const oldTimer = getState().meta.statusTimer;
    if (oldTimer) clearTimeout(oldTimer);

    // start a new timer. if we don't receive a status within the timeout period,
    // this timer will finish and report a timeout.
    const newTimer = setTimeout(() => {
      dispatch(reportError('Timeout'));
    }, STATUS_TIMEOUT_MS);

    // report that we've received a status, replacing the old timer.
    dispatch(reportStatusReceived(newTimer));

    // handle actual status...

When testing with Cypress, I’m experiencing an issue where the timeout screen appears after the Cypress timeout instead of after 5 seconds. I have used cy.tick() correctly in other tests, and the app code works correctly, so I’m unsure why I’m seeing this issue.

The issue might be that the cy.clock() command is not resetting the clock to epoch time, which causes the setTimeout function to use the wrong reference time. Try adding cy.clock(Date.now()) before cy.tick(5000) to reset the clock to the current time before ticking.