The Cypress Test Runner — Time Travel, DOM Snapshots and Interactive Debugging

The Cypress Test Runner is not just a test executor — it is a full diagnostic environment. Every command your test executes is logged in a clickable Command Log on the left side. Hovering over any command shows a DOM snapshot of exactly what the page looked like at that moment — before and after the command ran. This “time travel” capability means you can debug a failed test by visually stepping through every command, seeing exactly what the test saw at each step, without adding console.log statements or re-running the test.

Time Travel, DOM Snapshots and Interactive Debugging

The Test Runner’s debugging features make Cypress one of the easiest automation tools to troubleshoot when tests fail.

// ── Using the Test Runner for debugging ──

describe('Debugging Demo', () => {
  it('demonstrates time-travel debugging', () => {
    cy.visit('/');

    // Each of these commands appears in the Command Log
    cy.get('[data-test="username"]').type('standard_user');
    cy.get('[data-test="password"]').type('secret_sauce');
    cy.get('[data-test="login-button"]').click();

    // After the test runs, you can:
    // 1. HOVER over any command in the log → page shows that moment's DOM
    // 2. CLICK a command → pin it and inspect in DevTools
    // 3. See before/after states for each command
  });

  it('demonstrates debugging with cy.pause()', () => {
    cy.visit('/');
    cy.get('[data-test="username"]').type('standard_user');

    // ── cy.pause() — freeze execution at this point ──
    // In open mode, the test stops here. You can:
    //   - Inspect the page in DevTools
    //   - Check element states
    //   - Click "Resume" or "Next" to continue step by step
    cy.pause();

    cy.get('[data-test="password"]').type('secret_sauce');
    cy.get('[data-test="login-button"]').click();
  });

  it('demonstrates debugging with cy.debug()', () => {
    cy.visit('/');
    cy.get('[data-test="username"]')
      .type('standard_user')
      .debug();  // Opens browser DevTools debugger at this point
    // The yielded subject is available as `subject` in the console
  });

  it('demonstrates .then() for inspecting values', () => {
    cy.visit('/inventory.html');

    cy.get('.inventory_item').then(($items) => {
      // $items is a jQuery-wrapped collection
      console.log(`Found ${$items.length} products`);

      // You can use standard JavaScript/jQuery here
      const names = [...$items].map(el =>
        el.querySelector('.inventory_item_name')?.textContent
      );
      console.log('Product names:', names);

      // Assert inside .then()
      expect($items).to.have.length(6);
    });
  });
});


// ── Test Runner features reference ──
/*
  COMMAND LOG (left panel):
    - Every cy command appears as a clickable entry
    - Shows command name, selector, result, and duration
    - Green = passed, Red = failed, Blue = in progress
    - Click to pin and inspect in DevTools

  TIME TRAVEL (hover):
    - Hover over any command → page shows DOM at that moment
    - "before" state (grey) and "after" state (purple) toggle
    - See exactly what changed with each command

  APP PREVIEW (right panel):
    - Live browser showing the app under test
    - Updates in real-time as tests execute
    - Right-click → Inspect Element works normally

  DEBUGGING TOOLS:
    cy.pause()          Pause execution, resume step-by-step
    cy.debug()          Open browser debugger at the current point
    .then(cb)           Inspect values with console.log
    debugger;           Standard JS debugger statement (in .then())

  SELECTOR PLAYGROUND:
    - Click the crosshair icon in the Test Runner toolbar
    - Click any element on the page
    - Cypress suggests the best selector for that element
    - Copy the selector directly into your test code
*/

console.log("Test Runner debugging features:");
console.log("  Time travel: hover over commands to see DOM snapshots");
console.log("  cy.pause(): freeze and step through commands");
console.log("  cy.debug(): open DevTools at a specific point");
console.log("  Selector Playground: click elements to get selectors");
Note: The Selector Playground is a built-in tool in the Test Runner toolbar (crosshair icon) that generates selectors for any element you click on the page. It prioritises data-cy, data-test, and data-testid attributes first, then falls back to ID, class, and other attributes. This is the fastest way to find the right selector for a new element — click it in the Playground, copy the suggested selector, and paste it into your test. It is the Cypress equivalent of inspecting elements in DevTools but specifically optimised for test selectors.
Tip: Use cy.pause() during test development to freeze execution at any point and inspect the page state. This is far more powerful than re-running the test with a debugger statement because cy.pause() lets you click “Next” to advance one command at a time — effectively stepping through your test like a debugger steps through code lines. Use it whenever a test behaves unexpectedly to see exactly what the page looks like between each command.
Warning: Time-travel debugging only works in open mode (npx cypress open). In run mode (npx cypress run, used in CI), tests execute headlessly without the Test Runner UI. For CI debugging, rely on screenshots (auto-captured on failure), videos (if enabled), and the terminal output which includes the Command Log in text form. Always reproduce CI failures locally in open mode for the full debugging experience.

Common Mistakes

Mistake 1 — Debugging by adding cy.wait() instead of using time-travel

❌ Wrong: Adding cy.wait(5000) between commands to “slow things down and see what happens.”

✅ Correct: Using cy.pause() to freeze at the problematic point, or hovering over commands in the Command Log to see DOM snapshots at each step. Time-travel shows you what happened without modifying the test.

Mistake 2 — Not using the Selector Playground for new selectors

❌ Wrong: Manually inspecting the DOM in DevTools and guessing at CSS selectors.

✅ Correct: Clicking the Selector Playground crosshair, clicking the target element, and using the suggested selector — which is automatically optimised for test stability.

🧠 Test Yourself

What does “time travel” mean in the Cypress Test Runner?