You know what Cypress is. Time to install it. This lesson takes you from an empty folder to a fully scaffolded TypeScript Cypress project — including a working cypress.config.ts, a typed tsconfig.json, and a real test file you can run before the lesson ends. Every command in this lesson is meant to be typed into your terminal as you read.
Prerequisites
Before you start, you need:
- Node.js v18 or later. Run
node --versionto confirm. If you're on Node 16, upgrade — Cypress 13+ won't install cleanly on older runtimes. - A code editor. VS Code is what every example in this course assumes. The Cypress team publishes first-party TypeScript types, and VS Code's hover-tooltips on
cy.*commands are one of the things you'll come to rely on. - Working knowledge of JavaScript and TypeScript as covered in JavaScript for QA and TypeScript for QA. We won't re-explain
const, generics, or interfaces here.
If node --version prints something v18 or higher and you can open a terminal in VS Code, you're ready.
Creating the project
We'll build a real e-commerce test project across this course — the same scaffold you'd use at work. Start clean:
mkdir cypress-ecommerce-tests
cd cypress-ecommerce-tests
npm init -y
npm install cypress typescript --save-devThree things happened:
npm init -ycreatedpackage.jsonwith default values.npm install cypress typescript --save-devdownloaded both packages intonode_modulesand added them todevDependencies. Cypress is around 200 MB on disk because it bundles its own Electron browser — that's normal, not a mistake.- The
--save-devflag pinned both as development dependencies, since they're tools you use to test the app rather than ship in production.
You don't need to install @types/cypress separately. Cypress ships its own TypeScript declarations inside the cypress package itself. Same for the test runner Mocha — its globals are typed and pulled in automatically.
First launch — the scaffolder
The first time you run cypress open, the Cypress desktop app walks you through scaffolding. Run it now:
npx cypress openA window appears. Click E2E Testing. Cypress detects this is a fresh project and offers to create a starter folder structure. Click Continue. It then asks you to pick a browser — choose Chrome if you have it (Edge and Firefox work too; bundled Electron is a fine fallback).
After scaffolding completes, your project tree looks like this:
cypress-ecommerce-tests/
├── cypress/
│ ├── e2e/ ← spec files (.cy.ts) live here
│ ├── fixtures/ ← test data (JSON, CSV, etc.)
│ ├── support/
│ │ ├── commands.ts ← custom commands
│ │ └── e2e.ts ← runs before every spec
│ └── downloads/ ← files saved during tests
├── cypress.config.ts ← top-level Cypress config
├── tsconfig.json ← TypeScript config (auto-created)
├── package.json
└── package-lock.json
Each folder has a job. cypress/e2e/ is where you put your tests. cypress/fixtures/ is where you put deterministic test data — JSON files, CSV uploads, anything a test needs to read. cypress/support/commands.ts is where you'll define custom commands like cy.login(...) later in chapter 5. cypress/support/e2e.ts is the global setup file that runs before every spec — you'll wire up cross-cutting plugins like cypress-axe here in chapter 7.
Reading cypress.config.ts
Open cypress.config.ts at the project root:
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});defineConfig is a typed wrapper that gives you autocomplete on every config option — hover over it in VS Code and you'll see the full schema. Three options you'll change immediately:
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
baseUrl: "http://localhost:3000",
viewportWidth: 1280,
viewportHeight: 720,
setupNodeEvents(on, config) {
// hooks for fixtures, plugins, env vars
},
},
});baseUrllets you callcy.visit("/products")instead of the full URL. Without it,cy.visit("/")errors out.viewportWidthandviewportHeightcontrol the browser window size during tests. Set them once here and every test inherits them.
Save the file. The runner picks up changes live; no restart needed.
The TypeScript config
Cypress auto-generates cypress/tsconfig.json (note: it's nested under cypress/, not the root):
{
"compilerOptions": {
"target": "ES2020",
"lib": ["ES2020", "DOM"],
"types": ["cypress", "node"],
"moduleResolution": "node"
},
"include": ["**/*.ts"]
}The line that matters most is "types": ["cypress"]. That's what wires cy, Cypress, describe, and it into the global scope for every file in cypress/. Without it, the editor underlines the entire framework as undeclared. If you ever see "Cannot find name 'cy'," check this line first.
Verify with a one-line test
Drop this into cypress/e2e/sanity.cy.ts:
describe("Sanity check", () => {
it("Cypress is wired up correctly", () => {
cy.wrap("hello cypress").should("equal", "hello cypress");
});
});Save the file. The Cypress runner shows it in the spec list. Click it. The browser opens, the test runs, and you see a green check next to "Cypress is wired up correctly". cy.wrap doesn't need a real app — it just wraps a value in a Cypress chainable so we can run an assertion against it. If this passes, your installation is healthy.
Add npm scripts
Stop typing npx cypress every time. In package.json:
{
"scripts": {
"cy:open": "cypress open",
"cy:run": "cypress run",
"cy:run:chrome": "cypress run --browser chrome"
}
}Now npm run cy:open launches the runner and npm run cy:run does a headless CI-style run. Every Cypress project in this course uses these three scripts as the standard surface — get into the habit now.
The full installation flow
Step 1 of 5
npm init
mkdir + cd + npm init -y to create package.json. The folder name (e.g. cypress-ecommerce-tests) is yours; everything else lives below it.
Recommended VS Code extensions
While the runner is open, pull up VS Code and install these:
- Cypress Snippets (
andrew-codes.cypress-snippets) — autocomplete for common Cypress patterns. - ESLint (
dbaeumer.vscode-eslint) — catches typos and dead code in your specs. - Prettier (
esbenp.prettier-vscode) — auto-formats.tsand.cy.tsfiles on save.
Add eslint-plugin-cypress to the project if you want lint rules tuned for Cypress: npm install eslint eslint-plugin-cypress --save-dev. The full Cypress reference is on the Cypress tools page and the commands cheat sheet.
⚠️ Common mistakes
- Editing the root
tsconfig.jsoninstead ofcypress/tsconfig.json. Cypress test files live undercypress/and read the nested config — that's the file that needs"types": ["cypress"]. Adding the same line at the project root has no effect on test files. The symptom is "Cannot find name 'cy'" everywhere even though you swear you fixed it. - Skipping
npx cypress openand trying to scaffold by hand. The first launch generates not just folders but also tunedtsconfig.json, support stubs, and example specs you can delete. Hand-rolling means you'll forget something subtle (like the support file being loaded before every spec) and spend an hour debugging it. - Installing
@types/cypressfrom npm. It used to exist; it doesn't apply to modern Cypress. The official types are bundled inside thecypresspackage. Installing the deprecated@typespackage can shadow the real ones and break autocomplete in confusing ways. If you have it inpackage.json, remove it.
🎯 Practice task
Build the project you'll use for the rest of this course. 20-30 minutes.
-
Create a folder
cypress-ecommerce-tests/and run the four install commands from the lesson. Confirmnode_modules/cypressexists andpackage.jsonlistscypressandtypescriptunderdevDependencies. -
Run
npx cypress openand let it scaffold. Inspect the generated tree and confirm the structure matches the diagram in the lesson. -
Open
cypress.config.tsand addbaseUrl: "https://example.cypress.io"(a public Cypress demo site). Save. -
Create
cypress/e2e/sanity.cy.tswith the one-line test from the lesson. Run it from the runner — it should pass. -
Now create a second spec,
cypress/e2e/visit.cy.ts:describe("Demo site", () => { it("loads the Cypress example homepage", () => { cy.visit("/"); cy.get("h1").should("be.visible"); }); });Click it in the runner. The Cypress example page loads, the test passes, and you've made your first real navigation.
-
Add the three npm scripts (
cy:open,cy:run,cy:run:chrome) topackage.json. Runnpm run cy:runfrom the terminal — you should see both specs execute headlessly with a green summary. -
Stretch: in
cypress/tsconfig.json, deliberately remove"cypress"from thetypesarray. Save. Open any spec — thecyglobal is now red squiggles in VS Code. Put"cypress"back. Watch the squiggles disappear. You've just felt exactly what the type-resolution wiring buys you.
The next lesson takes this scaffolded project and writes a multi-test spec against a real e-commerce flow — products, search, filters — with assertions that use should, each, and beforeEach.