← All posts

Testing

Cypress: End-to-End Testing That Runs in the Browser

Cypress is an end-to-end testing framework that runs in the browser, with time-travel debugging and automatic waiting.

C Testing

End-to-end tests have a reputation for being flaky and painful, largely because older tools drove the browser from the outside and raced against it. Cypress rethought the model: it runs inside the browser alongside your app, which makes it fast, gives it deep access to the running application, and - crucially - lets it automatically wait for elements and requests instead of you sprinkling arbitrary sleeps. Its test runner shows each step with time-travel snapshots, so debugging a failure means clicking back through exactly what happened.

Tests That Wait for You

Commands read clearly, and Cypress retries assertions until they pass or time out - killing a whole category of flakiness:

it('filters tools by category', () => { cy.visit('/tools'); cy.get('[data-filter=category]').select('CLI'); cy.get('.tool-card').should('contain', 'ripgrep'); });

Debugging You Can See

The interactive runner records a snapshot at every step, so a failing test can be replayed frame by frame - you literally see the DOM at the moment it broke. Network stubbing, fixtures, and screenshots on failure round it out.

Rough Edges and Limitations

  • Browser-focused architecture. Its in-browser model has trade-offs; cross-browser and multi-tab scenarios have historically been more limited than some alternatives.
  • E2E is heavier. These tests are slower and more involved than unit tests - use them for critical flows, not everything.
  • Some flakiness remains. Auto-waiting helps enormously but doesn't eliminate every timing issue.

For testing the real user-facing flows of a web app, Cypress's speed and its see-what-broke debugging make E2E testing genuinely approachable.

Internal link suggestion: link "not everything" to the Vitest post - unit tests for the small stuff, Cypress for the flows.