In short
Cypress opens your real app in a real browser and clicks through it like a user, while you watch each step. Seeing a test run live makes debugging feel much less mysterious.
An end-to-end testing tool that runs tests inside a real browser, letting you script and watch full user flows (login, checkout, etc.) as they actually happen.

Think of it like this
A mystery shopper
Companies send a mystery shopper to their own store: walk in, ask for a product, pay, check the bill. Cypress is a mystery shopper for your website, doing the same visit every time and reporting anything odd.
Watch it happen
The login test, live in a browser
intercept /api/login
1/6Cypress sets up a fake reply for the login API before anything loads.
The big ideas
What you need to know
Commands chain
cy.get(...).type(...).should(...) reads like a sentence. Cypress queues the commands and runs them in order.
Automatic retries
should() keeps retrying until it passes or times out, so you rarely need manual waits.
Fake the backend when needed
cy.intercept can stub API responses, so you can test error screens without breaking the real server.
Time travel
In the Cypress app, hover over any step to see a snapshot of the page at that moment.
See it in code
Walk through the code
1describe("Login", () => {2 it("takes a student to the dashboard", () => {3 cy.intercept("POST", "/api/login", { statusCode: 200, body: { name: "Aman" } }).as("login");4 cy.visit("/login");5 6 cy.get("[data-cy=email]").type("aman@college.edu");7 cy.get("[data-cy=password]").type("test-password");8 cy.contains("button", "Log in").click();9 10 cy.wait("@login");11 cy.url().should("include", "/dashboard");12 cy.contains("Welcome, Aman").should("be.visible");13 });14});1/4Stub the login API and name it @login so the test can wait for it.
data-cy attributes give tests a stable hook that won't break when designers change classes. cy.wait("@login") waits for that exact request, not a fixed time.
Save yourself the pain
Common mistakes
Oops
Writing cy.wait(3000) to 'let the page load'.
Do this instead
Wait for something specific, like an aliased request or a should() on an element. Fixed waits are slow and flaky.
Oops
Trying to save cy.get() results in a variable like const btn = cy.get(...).
Do this instead
Cypress commands are queued, not returned immediately. Chain off them, or use .then() or aliases.
Your mission
Mystery-shop your own project
Quick check
Your Cypress test sometimes fails because the API is slow. What's the best fix?
Go deeper
- 1Write a Cypress test that logs into a demo app and asserts a redirect.
- 2Use the Cypress Test Runner's time-travel debugging to inspect each step.
- 3Target elements with `data-cy` attributes rather than fragile CSS selectors.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.