Installing Cypress and Project Setup — From Zero to First Test in Minutes

One of Cypress’s greatest strengths is how quickly you go from zero to a running test. A single npm install command installs Cypress and all its dependencies — including a bundled browser (Electron). There is no separate driver download, no Java runtime, no PATH configuration. Within five minutes of installation, you can have a test running against a live website. This lesson walks through the complete setup, folder structure, and configuration.

Installing Cypress and Exploring the Project Structure

Cypress is installed as a Node.js package and configured via a single JavaScript or TypeScript config file.

// ── Step 1: Initialise a Node.js project ──
// $ mkdir cypress-project && cd cypress-project
// $ npm init -y

// ── Step 2: Install Cypress ──
// $ npm install cypress --save-dev

// ── Step 3: Open Cypress for the first time ──
// $ npx cypress open
// This launches the Test Runner, creates the default folder structure,
// and lets you select E2E or Component testing.

// ── Step 4: Choose E2E Testing in the UI ──
// Cypress generates the following folder structure:

/*
cypress-project/
  cypress/
    e2e/                    # Your test files (.cy.ts or .cy.js)
      spec.cy.ts            # Example test (auto-generated)
    fixtures/               # Static test data (JSON files)
      example.json
    support/
      commands.ts           # Custom Cypress commands
      e2e.ts                # Support file — runs before every test
  cypress.config.ts         # Main configuration file
  package.json
  tsconfig.json             # TypeScript config (if using TS)
*/


// ── cypress.config.ts — Main configuration ──
import { defineConfig } from 'cypress';

export default defineConfig({
  e2e: {
    baseUrl: 'https://www.saucedemo.com',  // Prepended to cy.visit('/')
    defaultCommandTimeout: 6000,            // Retry timeout for commands (ms)
    viewportWidth: 1280,                    // Browser viewport width
    viewportHeight: 720,                    // Browser viewport height
    video: false,                           // Disable video recording (saves time)
    screenshotOnRunFailure: true,           // Auto-screenshot on failure
    retries: {
      runMode: 2,                           // Retry failed tests 2x in CI (cypress run)
      openMode: 0,                          // No retries in interactive mode
    },
    specPattern: 'cypress/e2e/**/*.cy.{js,ts}',  // Test file pattern
    supportFile: 'cypress/support/e2e.ts',
  },
});


// ── package.json scripts ──
/*
{
  "scripts": {
    "cy:open": "cypress open",          // Interactive Test Runner
    "cy:run": "cypress run",            // Headless CLI execution (CI)
    "cy:run:chrome": "cypress run --browser chrome",
    "cy:run:firefox": "cypress run --browser firefox"
  }
}
*/


// ── Verify installation ──
// $ npx cypress verify
// Output: "Cypress is installed correctly"

// ── Run in headless mode (CI) ──
// $ npx cypress run
// Runs all specs headlessly, outputs results to terminal

// ── Run specific spec ──
// $ npx cypress run --spec "cypress/e2e/login.cy.ts"

console.log("Cypress installed and configured!");
console.log("Interactive: npx cypress open");
console.log("Headless CI: npx cypress run");
Note: Cypress has two execution modes: open mode (npx cypress open) launches the interactive Test Runner with time-travel debugging, DOM snapshots, and real-time reloading. Run mode (npx cypress run) executes tests headlessly in the terminal — this is what you use in CI/CD. The retries configuration lets you set different retry counts for each mode: typically 0 retries in open mode (you want to see failures immediately during development) and 1-2 retries in run mode (to handle transient CI flakiness).
Tip: Set baseUrl in cypress.config.ts immediately after installation. This lets you write cy.visit('/') and cy.visit('/login') in your tests instead of repeating the full URL. It also makes switching between environments trivial: CYPRESS_BASE_URL=https://staging.app.com npx cypress run overrides the config value via environment variable without editing any file.
Warning: Do not install Cypress globally (npm install -g cypress). Install it as a dev dependency in each project (npm install --save-dev cypress). Global installations create version conflicts between projects and make CI/CD setup unreliable because the CI machine may not have the global package. Project-local installation ensures every team member and every CI run uses the exact same Cypress version.

Common Mistakes

Mistake 1 — Skipping the cypress.config.ts configuration

❌ Wrong: Using all default settings without configuring baseUrl, timeouts, or viewport — then hardcoding full URLs in every test.

✅ Correct: Setting baseUrl, defaultCommandTimeout, viewportWidth/Height, and retries immediately after installation. These settings apply globally and eliminate repetitive configuration in individual tests.

Mistake 2 — Enabling video recording in development

❌ Wrong: Leaving video: true (the default) during local development — every test run generates a video file, consuming disk space and slowing test completion.

✅ Correct: Setting video: false in config and enabling it only in CI where video evidence of failures is valuable: CYPRESS_VIDEO=true npx cypress run.

🧠 Test Yourself

What is the difference between npx cypress open and npx cypress run?