← StatePort

Debugging guides

Cypress Test Replay: inspect the failure, then reproduce it locally

Roman Novikov ·

The export test failed on its first CI attempt and passed on retry. The failure screenshot shows a spinner. The passing attempt shows a download. Neither image explains whether the first attempt hit a rate limit, used different data or simply ran the assertion too early.

Keep the failed attempt and its network timeline. The retry cannot tell you which response the first attempt received.

Start in Cypress Test Replay. Look for the request after the export click before changing an assertion timeout.

Read the failed attempt before rebuilding it

Test Replay includes the commands and browser context captured during the test, with network and console information available for investigation. That is substantially more useful than treating the failure as a video alone. 1

Cypress’s cy-cloud CLI can query recorded run and replay data as JSON, including a timeline for a particular attempt. Downloaded replay data is cached locally. The CLI authenticates against Cypress Cloud and follows the user’s access permissions. 2

Keep the identifiers of the run, spec, test and attempt together. A command timeline from the successful retry can otherwise make the failed request seem to have never happened.

Did the first export receive a 429?

In this invented export case, suppose the failed attempt shows HTTP 429 from the export endpoint. The UI then spins until the test times out. The hypothesis is that the app does not handle the rate-limit response, not that the spinner needs a longer assertion timeout.

First check the status and response that were actually observed. If the body is unavailable, use a synthetic fixture derived from the documented API contract and label it accordingly. Do not present guessed fields as captured evidence.

Next separate application behaviour from the test setup. A job that reuses one account across workers could create rate limiting that a solo local run never sees. That would still expose an error-handling path, but the conditions causing it matter to the final fix.

Build the smallest failing test

Cypress’s cy.intercept() can stub a response for a targeted request. Install the intercept before the action that starts that request, then check the user-visible result. 3

This template assumes your local app has an export button and a status element with the indicated test IDs. It is not a test result from a real customer app.

it('explains an export rate limit', () => {
  cy.intercept('POST', '**/api/exports', {
    statusCode: 429,
    body: { code: 'RATE_LIMITED', retryAfterSeconds: 15 },
  }).as('startExport');

  cy.visit('/reports');
  cy.get('[data-testid="export-button"]').click();
  cy.wait('@startExport').its('response.statusCode').should('eq', 429);
  cy.get('[data-testid="export-status"]')
    .should('contain.text', 'Try again shortly');
});

Set Cypress’s baseUrl to your local app and use the test suite’s authorised authentication and data setup. Replace the example selectors and message with the actual acceptance criterion. The network assertion confirms which stubbed response arrived. The status assertion checks the UI response. Neither establishes the live service’s rate-limit policy or whether a later retry will succeed.

If this test reproduces the stuck spinner and catches the patch, keep it as the regression check.

Do not erase CI differences too early

Record the application build and browser used by the failed CI attempt. For this rate-limit case, compare account reuse and parallel jobs before investigating unrelated settings. Check viewport, locale or timezone when the evidence points to them.

If the error only appears under concurrency, replacing all traffic with one recorded response can help test the UI’s handling of that response. It does not reproduce the server-side concurrency mechanism. A local pass is therefore not sufficient to declare the CI flake fixed.

The final regression check belongs back in the affected test and CI environment. Keep the original failure available for comparison instead of overwriting it with a convenient passing artifact.

When a State Card helps between test runs

Some failing setups are expensive to reach interactively: a prepared report, a selected workspace and several unsaved filters before the export begins. When you have such a supported case, capture it in StatePort, review it and test a reopen. 4

Use Local app to run the changed frontend against retained matching dependencies. That can be useful for inspecting the screen between edits without reconstructing all the preceding UI work. Missing material and replay limitations remain visible. 5

This is not a replacement for Cypress’s assertions, CI coordination or Test Replay. Nor does this article promise that a Cypress Cloud replay download can be imported as a State Card. The described path uses a separate supported StatePort capture.

Put the regression check back in CI

The intercept test can cover rate-limit messaging. Rerun the affected CI test to investigate why the original job hit the limit and whether the proposed fix addresses that path. A Card can help with UI work between those checks; it does not replace either one.

Link the failed attempt, the focused test and the final CI result in the existing issue. Add a Card only when another developer needs the prepared screen.

For more on the distinction between old-run inspection and a fresh execution, see Playwright traces and HAR replay. Review StatePort beta scope before assuming a CI-specific failure can be captured locally.

Sources

Written by StatePort; checked on 13 October 2026. The export case and test are illustrative. No CI reliability improvement or direct Cypress Cloud import is claimed.

  1. Cypress: Test Replay
  2. Cypress: Cloud CLI
  3. Cypress: cy.intercept
  4. StatePort: capture a first Card
  5. StatePort: reproduce a saved State Card