Cypress
A JavaScript-first E2E framework that runs inside the browser — giving you real-time reloading and time-travel debugging that makes frontend testing genuinely enjoyable.
1 The Hook — The Wellington Startup's "Heisenbug"
A Wellington-based SaaS startup had a bug that only appeared on the third step of a complex multi-page onboarding form. Developers couldn't reproduce it, and Selenium logs just showed "Timeout waiting for element."
They switched to Cypress and ran the test in the interactive runner. Using Time Travel, they clicked through the command log and saw exactly what happened: at step 3, a specific network request was failing with a 422 error, causing the UI to lock up. Because Cypress runs inside the browser, it caught the network error that the external driver had missed. They fixed the bug in 20 minutes.
2 The Rule — Don't Just Assert; Observe
Use the Cypress runner to watch your tests live. If a test fails, use the Command Log to go back in time and inspect the state of the DOM and Network.
Cypress isn't just a test runner; it's a development environment. Use it to build your features while writing your tests simultaneously.
3 The Analogy — The Flight Recorder
The Black Box.
Selenium is like an air traffic controller watching a radar: they see where the plane is, but not what the pilot sees. Cypress is like the Flight Data Recorder inside the cockpit: it records every button press, every gauge reading, and every radio call. When things go wrong, you don't guess — you just play back the tape.
Senior engineer insight
The moment Cypress clicked for me was when I stopped thinking of it as a test runner and started using it as a development tool. I'd open cypress open alongside my editor and write the feature and the test at the same time — the feedback loop was so tight I could see exactly where my React state management was wrong before I'd even written an assertion. That tight coupling to the browser's execution context is what separates it from every external driver I'd used before.
The most common mistake teams make: they treat Cypress like Selenium with nicer syntax, run it only in CI in headless mode, and miss the entire point of the time-travel debugger.
From the field
A team at a Wellington fintech building Revenue NZ-integrated tax software assumed their Cypress suite was comprehensive because it covered 90% of user journeys. What they hadn't accounted for was the Revenue NZ gateway returning subtly different payload shapes across staging and production environments. Their stubs were too clean — perfectly shaped JSON that never reflected real Revenue NZ response quirks. When they finally wired up cy.intercept() to replay captured production traffic (anonymised), they found three edge cases that had been silently corrupting tax calculations for seven months. The lesson: stub the unhappy path as hard as you stub the happy path, and seed your stubs from real traffic whenever compliance is involved.
4 Watch Me Do It — NZ SaaS Payment Stubbing
Scenario: Testing a "Successful Payment" screen without actually hitting a live Payment Gateway.
describe('Checkout Flow', () => {
it('shows success message on successful payment', () => {
// 1. Intercept the payment API call
cy.intercept('POST', '/api/v1/nz-payment', {
statusCode: 200,
body: { status: 'success', txnId: 'NZ-12345' }
}).as('paymentRequest');
// 2. Visit the checkout page
cy.visit('/checkout');
// 3. Fill details and submit
cy.get('[data-testid="pay-button"]').click();
// 4. Wait for the mocked request
cy.wait('@paymentRequest');
// 5. Assert the UI response
cy.contains('Thank you for your order!').should('be.visible');
});
});
5 Decision Tool — Why Cypress?
✅ Choose Cypress for...
- Modern React/Vue/Angular frontends
- Fast local development cycles
- Teams that want to mock/stub APIs easily
- Component-level UI testing
❌ Choose Playwright for...
- Testing across multiple tabs/windows
- High-fidelity Safari (WebKit) testing
- Complex iFrame scenarios
- Massive parallel execution on cheap CI
6 Common Mistakes
🚫 Using async/await
Don't: const val = await cy.get('...').text();
Actually: Cypress commands are a queue, not Promises. Use .then(($el) => { ... }) or aliases if you need to access values.
🚫 Storing Elements in Variables
Don't: const $btn = cy.get('button'); $btn.click();
Do: cy.get('button').click();
The DOM changes constantly. Chaining ensures Cypress re-queries the element if it goes stale.
7 Now You Try — Setup
Install Cypress in your project:
npm install cypress --save-dev
Open the interactive runner to create your config and example tests:
npx cypress open
Why teams fail here
- Over-relying on UI selectors that devs never agreed to maintain — tests break on every redesign because nobody owns
data-testidattributes as a first-class contract. - Stubbing everything so aggressively the tests stop testing reality — 100% mocked network means your suite can pass while your real API returns 500s in production.
- Ignoring Cypress's single-origin constraint until it's too late — NZ SaaS products that authenticate through a third-party IdP (like OneLogin or Azure AD) hit the cross-origin limit and have to retrofit workarounds mid-project.
- Treating flaky tests as acceptable background noise — one unstable test seeds distrust in the whole suite; teams start skipping failures and the automation becomes ceremonial rather than protective.
Key takeaway
Cypress earns its place when your team treats it as a development accelerator, not a post-coding checkbox — the time-travel debugger only pays off if someone actually opens the runner.
8 Self-Check
Q1. Can Cypress test a flow that involves opening a new browser tab?
No. Cypress runs inside a single tab. To test multi-tab flows, you usually have to use a "workaround" (like removing target="_blank") or use Playwright instead.
Q2. What is cy.intercept() used for?
Network Stubbing and Mocking. It allows you to "catch" network requests from your app and return fake data, making it easy to test how your UI handles different server responses without needing a live backend.
9 Interview Prep
"What makes Cypress different from Selenium?"
Answer: "The main difference is architecture. Selenium runs outside the browser and communicates over a network (WebDriver protocol). Cypress runs inside the browser, sharing the same execution loop as the application. This allows for native access to the DOM, zero communication lag, and features like automatic waiting and time-travel debugging."
10 Next Step
UI testing is great, but the fastest tests live at the API level. Let's look at the industry standard tool for API manual and automated testing: Postman.