Build an E2E Test Suite with Cypress

Write and run automated end-to-end tests for a web app using Cypress.

Introduction

30 Second Summary

Every time you use a website, you are clicking buttons, filling out forms, and navigating between pages. Someone has to make sure all of that actually works before real users touch it.

In this project, you will build a professional end-to-end test suite using Cypress that tests a real web application. You will write tests that navigate pages, query elements, interact with forms, and validate results.

What You'll Build

You will build a complete E2E test suite with multiple organized spec files that test the official Cypress Kitchen Sink demo application.

By the end of this project, you'll have:

  • A fully configured Cypress project with multiple spec files covering navigation, element querying, and form interactions.
  • Hands-on experience with the core Cypress commands that QA automation interviews test: cy.visit(), cy.get(), cy.contains(), .should(), .type(), and .click().
  • A test suite you can run headlessly from the command line, exactly how tests run in a CI/CD pipeline.
  • A secret mission to intercept and validate network requests using cy.intercept(), an advanced technique for API-aware testing.

Are there any prerequisites?

None. This project includes full setup instructions for Node.js, VS Code, and Cypress on Windows. You do not need any prior testing experience.

Install Node.js, VS Code, and Cypress

Before you can write a single test, you need three tools on your machine: Node.js to run JavaScript outside the browser, VS Code to write your test code, and Cypress to execute your tests against a real web application.

In this step, you will install all three and launch Cypress for the first time to scaffold your project structure.

In This Step, Get Ready To:
  • Install Node.js and VS Code on your Windows machine.
  • Create a project folder and initialize it with npm.
  • Install Cypress and launch the test runner for the first time.
Install Node.js and VS Code

Node.js is a JavaScript runtime that lets you run JavaScript outside of a web browser.

Cypress is built on Node.js, so you need it installed before anything else.

  • Go to https://nodejs.org and download the LTS version (v24.x).
  • Run the Windows installer and accept all the defaults.
  • Open a new terminal (Command Prompt or PowerShell) after installation completes.
  • Verify Node.js installed correctly by running the following commands.
node --version
npm --version

I see version numbers

You should see a version number for each command, like v24.x.x for Node and 10.x.x or higher for npm. You are good to go.

I see an error

If you see 'node' is not recognized, your terminal was likely open before the installation finished.

  • Close your terminal completely and open a fresh one.
  • Run node --version again.

Still not working?

If a fresh terminal still does not recognize the command, try restarting your computer. The Node.js installer updates your system PATH, and a restart ensures it takes effect. Help me troubleshoot my Node.js installation on Windows.

Now install your code editor.

Pro tip: already have VS Code?

If VS Code is already installed on your machine, skip the download and move on to the next substep.

Create a Project Folder and Initialize It

Every Node.js project starts with a package.json file. This file tracks your project's dependencies and scripts. You will create one now so you can install Cypress as a dependency.

  • Create a new folder on your computer called cypress-test-suite.
  • Open VS Code.
  • Click File, then Open Folder, and select your cypress-test-suite folder.
  • Open the integrated terminal by clicking Terminal, then New Terminal.
  • Run the following command to initialize your project.
npm init -y

What does this command do?

The npm init -y command creates a package.json file with default values. The -y flag skips all the interactive prompts and accepts the defaults automatically.

You should see a new package.json file appear in your VS Code file explorer.

Install Cypress and Launch It for the First Time

Cypress is an end-to-end testing framework that runs directly in the browser. Unlike Selenium, which controls the browser from the outside, Cypress executes inside the browser alongside your application. This gives it access to everything happening on the page in real time.

  • Run the following command in your VS Code terminal to install Cypress.
npm install cypress --save-dev

What does this command do?

This installs Cypress as a development dependency in your project. The --save-dev flag means Cypress is only needed during development and testing, not in production. The command also downloads the Cypress binary, which is the actual test runner application.

This will take a minute or two as it downloads the Cypress binary. Wait for it to finish completely.

Now launch the Cypress Launchpad. This is a setup wizard that scaffolds your project with the configuration files Cypress needs.

  • Run the following command.
npx cypress open

The Cypress Launchpad window opens. This is where you configure what type of testing you want to do.

  • Click E2E Testing.

Cypress shows you the configuration files it will create. These include cypress.config.js at your project root and support files in the cypress/support/ folder.

  • Click Continue to let Cypress scaffold these files.
  • Choose a browser from the list. Chrome or the bundled Electron browser both work.
  • Click Start E2E Testing in [browser name].

The Cypress test runner opens in your chosen browser. You should see a welcome screen with an option to create your first spec. You do not need to create one here because you will write your own in the next step.

  • Close the Cypress browser window and the Launchpad for now.

Switch back to VS Code and look at your file explorer. Cypress has created several new files and folders.

What should I see?

Your project should now contain:

  • cypress.config.js at the project root. This is the main Cypress configuration file.
  • cypress/support/commands.js for custom Cypress commands.
  • cypress/support/e2e.js which loads before every test file.
  • cypress/fixtures/example.json with sample fixture data.

What is E2E testing?

End-to-end testing simulates a real user interacting with your application from start to finish. Instead of testing individual functions in isolation, E2E tests open a real browser, click buttons, fill in forms, and verify that the whole application works together.

Your environment is fully set up. You have Node.js, VS Code, and a scaffolded Cypress project ready to go. Next up, you will write your first real test and watch Cypress execute it in the browser.

Write Your First Navigation Test

Your Cypress project is scaffolded and ready to go. Now it is time to write your first actual test. In this step, you will create a spec file that navigates to the Kitchen Sink demo app and verifies that pages load correctly.

In This Step, Get Ready To:
  • Create your first Cypress spec file and write a test that loads a web page.
  • Run your test in the interactive Cypress test runner and watch it execute in real time.
  • Add a navigation test that clicks a link and verifies the URL changes.
Create Your First Spec File

Cypress looks for test files inside the cypress/e2e/ folder. Each test file needs a .cy.js extension so Cypress recognizes it as a spec.

  • In VS Code, create a new file at cypress/e2e/navigation.cy.js.
  • Paste the following code into the file.
describe('Navigation Tests', () => {
  it('successfully loads the Kitchen Sink homepage', () => {
    // Visit the Cypress demo application
    cy.visit('https://example.cypress.io')

    // Verify the page title contains the expected text
    cy.title().should('include', 'Kitchen Sink')
  })
})

What does this code do?

describe groups related tests together under a label. it defines a single test case. These come from Mocha, which is bundled with Cypress.

cy.visit() navigates the browser to a URL. cy.title() grabs the page's <title> element. .should('include', 'Kitchen Sink') is an assertion that checks the title contains the expected text. If the assertion fails, the test fails.

Run Your Test in the Cypress Test Runner

The Cypress test runner lets you watch your tests execute in a real browser. You can see every command as it happens and inspect the DOM at each step.

  • Open your terminal in VS Code and run the following command.
npx cypress open
  • Select E2E Testing when prompted.
  • Pick a browser (Chrome or the bundled Electron browser) and click Start E2E Testing.
  • Click on navigation.cy.js in the spec list to run your test.

Watch the Cypress test runner execute your test in real time. You should see the test pass with a green checkmark.

What should I see?

The left panel shows the Command Log with each command that ran: VISIT, TITLE, and ASSERT. The right panel shows the actual browser view of the Kitchen Sink app. A green checkmark next to your test name means it passed.

Add a Test for Page Navigation

A single test proves the page loads. Now you need to verify that clicking a link actually takes the user to the correct page. This follows the Arrange-Act-Assert pattern: arrange the starting state (visit the homepage), act (click a link), and assert the result (check the URL).

  • Add a second it block inside your existing describe block, right after the first test.
describe('Navigation Tests', () => {
  it('successfully loads the Kitchen Sink homepage', () => {
    cy.visit('https://example.cypress.io')
    cy.title().should('include', 'Kitchen Sink')
  })

  it('navigates to the Querying page and verifies the URL', () => {
    // Arrange: start at the homepage
    cy.visit('https://example.cypress.io')

    // Act: find the Querying link by its text and click it
    cy.contains('Querying').click()

    // Assert: verify the URL changed to the querying page
    cy.url().should('include', '/commands/querying')
  })
})

What does this code do?

cy.contains('Querying') searches the page for an element containing the text "Querying". .click() clicks on that element, just like a real user would.

cy.url() grabs the current URL from the browser's address bar. The .should('include', '/commands/querying') assertion checks that the URL contains the expected path after the click.

  • Save the file.

If the Cypress test runner is still open, it automatically detects the file change and re-runs both tests. You should see two green checkmarks.

Pro tip: auto-reload

Cypress watches your spec files for changes and re-runs tests automatically when you save. Keep the test runner open in the background while you code. This tight feedback loop is one of the reasons Cypress is popular for test development.

Test failing or not showing up?

Make sure your file is saved at exactly cypress/e2e/navigation.cy.js. The .cy.js extension is required for Cypress to recognize the file as a spec. If the test runner does not show your file, close it and re-run npx cypress open. Help me debug my Cypress test.

You now have two passing tests that verify page loading and link navigation. Next up, you will learn how to query specific elements on a page using CSS selectors and data attributes.

Query Elements and Make Assertions

Your navigation tests prove the app loads and links work. Now you need to find specific elements on the page and verify they have the right content, classes, and attributes. This is the core of Cypress testing. Every real-world test you write will use element queries and assertions, and interviewers will ask you to explain your selector strategy.

In This Step, Get Ready To:
  • Find elements by CSS selector, text content, and data attributes.
  • Write assertions that verify element properties like text, classes, and attributes.
  • Use time-travel debugging to inspect each command in the Cypress test runner.
Create a Querying Test Spec

The cy.get() command is how you select elements in Cypress. It accepts any CSS selector, just like document.querySelector() in JavaScript. You'll start by selecting an element by its ID.

  • Create a new file at cypress/e2e/querying.cy.js.
  • Write a describe block called Querying Tests.
  • Add an it block called finds elements by CSS selector using cy.get().
  • Inside the test, visit https://example.cypress.io/commands/querying.
  • Use cy.get('#query-btn') to select the button by its ID and assert it contains the text "Button".
describe('Querying Tests', () => {
  it('finds elements by CSS selector using cy.get()', () => {
    cy.visit('https://example.cypress.io/commands/querying')

    // Select the button by its CSS ID selector
    cy.get('#query-btn').should('contain', 'Button')
  })
})

What does cy.get() do?

cy.get() searches the DOM for elements matching a CSS selector. The #query-btn selector finds the element with id="query-btn". The .should('contain', 'Button') part is an assertion that checks the element's text content includes the word "Button".

Test Querying by Text Content and Data Attributes

CSS selectors are just one way to find elements. cy.contains() lets you find elements by their visible text. Data attributes like data-test-id are the gold standard for test selectors because they survive CSS refactors and UI redesigns. Interviewers love asking about this.

  • Add a second it block called finds elements by text content using cy.contains().
  • Visit the same querying page.
  • Use cy.get('.query-list').contains('bananas') to find the list item containing "bananas".
  • Assert it has the class third using .should('have.class', 'third').
  • Add a third it block called finds elements by data attribute.
  • Use cy.get('[data-test-id="test-example"]') to select the element by its data attribute.
  • Assert it has the class example using .should('have.class', 'example').

Your complete querying.cy.js file should now look like this:

describe('Querying Tests', () => {
  it('finds elements by CSS selector using cy.get()', () => {
    cy.visit('https://example.cypress.io/commands/querying')

    // Select the button by its CSS ID selector
    cy.get('#query-btn').should('contain', 'Button')
  })

  it('finds elements by text content using cy.contains()', () => {
    cy.visit('https://example.cypress.io/commands/querying')

    // Find the list item containing "bananas" within the query-list
    cy.get('.query-list')
      .contains('bananas')
      .should('have.class', 'third')
  })

  it('finds elements by data attribute', () => {
    cy.visit('https://example.cypress.io/commands/querying')

    // Best practice: use data attributes for test selectors
    cy.get('[data-test-id="test-example"]')
      .should('have.class', 'example')
  })
})

Why use data attributes instead of CSS classes?

CSS classes and IDs can change when developers restyle the app. A data-test-id attribute exists purely for testing. It won't be removed during a CSS refactor, which makes your tests more stable.

This is one of the most common interview questions for QA Automation roles. The recommended selector priority is: data attributes first, then IDs, then CSS classes as a last resort.

What is the difference between cy.get() and cy.contains()?

cy.get() finds elements by CSS selector (IDs, classes, attributes). cy.contains() finds elements by their visible text content. You can also chain them together, like cy.get('.query-list').contains('bananas'), to narrow the search to a specific container first.

Run and Review the Querying Tests
  • Save the file.
  • Switch to the Cypress test runner.
  • Click on querying.cy.js to run it.

All three tests should pass with green checkmarks.

  • Click on any test in the Command Log to see the individual commands that ran.
  • Hover over each command to see the DOM snapshot at that exact moment.

This is called time-travel debugging. Cypress takes a snapshot of the DOM after every command, so you can step backwards through your test to see exactly what the page looked like at each point. This is one of Cypress's most powerful features and something you should be ready to discuss in interviews.

What should I see?

The Command Log on the left side of the test runner shows each command (VISIT, GET, CONTAINS, ASSERT) with a green checkmark. When you hover over a command, the right side of the runner highlights the matching element on the page and shows the DOM state at that moment.

Test failing with "Timed out" error?

If a test fails because Cypress could not find an element, double-check that the selector matches exactly. Selectors are case-sensitive. Make sure you are visiting the correct URL (https://example.cypress.io/commands/querying) and that the page loads fully before Cypress queries the DOM.

Still stuck? Help me debug my failing Cypress querying test.

You now have two spec files covering navigation and querying. Next up, you'll test real user interactions like typing into inputs, clicking buttons, and submitting forms.

Test Form Interactions with Actions

Your querying tests can find any element on the page. Now it is time to interact with those elements the way a real user would.

Clicking buttons, typing into inputs, and submitting forms are the bread and butter of E2E testing. These are the actions that break in production and the ones your test suite needs to cover. In this step, you will write tests that simulate real user behavior on the Cypress Kitchen Sink actions page.

In This Step, Get Ready To:
  • Type into input fields and verify the entered value.
  • Submit a form and assert a success message appears.
  • Refactor your tests with a beforeEach hook to follow the Arrange-Act-Assert pattern.
Create an Actions Test Spec with Typing and Clicking

The .type() command simulates a user typing into an input field, keystroke by keystroke. After typing, you can assert the input's value to confirm the text was entered correctly.

  • Create a new file at cypress/e2e/actions.cy.js.
  • Add the following code to create your first actions test.
describe('Actions Tests', () => {
  it('types into an input field and verifies the value', () => {
    cy.visit('https://example.cypress.io/commands/actions')

    // Select the email input by its class and type into it
    cy.get('.action-email')
      .type('testuser@example.com')
      .should('have.value', 'testuser@example.com')
  })
})

What does this code do?

cy.get('.action-email') selects the email input field by its CSS class. .type() simulates typing each character into the field. .should('have.value', ...) asserts that the input's value attribute matches the string you typed. This chain of commands reads like a sentence: get the email field, type into it, and verify the value.

  • Run npx cypress open and select E2E Testing.
  • Click on actions.cy.js to run the test.

You should see Cypress navigate to the actions page, type into the email field character by character, and pass the assertion with a green checkmark.

Add a Form Submission Test

Form submissions are one of the most common user interactions on the web. Cypress provides a .submit() command that triggers a form's submit event, just like pressing Enter or clicking a submit button.

  • Add a second it block inside your describe block, after the first test.
  it('submits a form and verifies the result', () => {
    cy.visit('https://example.cypress.io/commands/actions')

    // Find the form, locate the text input inside it, and type a coupon code
    cy.get('.action-form')
      .find('[type="text"]')
      .type('HALFOFF')

    // Submit the form
    cy.get('.action-form').submit()

    // Verify the success message appears after the form
    cy.get('.action-form')
      .next()
      .should('contain', 'Your form has been submitted!')
  })

What does this code do?

This test chains several commands together. .find() searches within the form element for a text input. .submit() triggers the form's native submit event. .next() selects the next sibling element after the form, which is where the Kitchen Sink app displays its success message.

  • Save the file.

If the Cypress test runner is still open, it auto-reloads and runs both tests. You should see two passing tests.

Add a Click Test and Use beforeEach for DRY Setup

Notice how every test starts with the same cy.visit() call. This is repetitive. The beforeEach hook runs before every test in a describe block, so you can move shared setup into it. This follows the Arrange-Act-Assert pattern: arrange the starting state once, then each test only contains the act and assert steps.

  • Replace the entire contents of actions.cy.js with the refactored version below.
describe('Actions Tests', () => {
  // Runs before every test - navigates to the actions page
  beforeEach(() => {
    cy.visit('https://example.cypress.io/commands/actions')
  })

  it('types into an input field and verifies the value', () => {
    cy.get('.action-email')
      .type('testuser@example.com')
      .should('have.value', 'testuser@example.com')
  })

  it('submits a form and verifies the result', () => {
    cy.get('.action-form')
      .find('[type="text"]')
      .type('HALFOFF')

    cy.get('.action-form').submit()

    cy.get('.action-form')
      .next()
      .should('contain', 'Your form has been submitted!')
  })

  it('clicks a button and verifies the popover appears', () => {
    // Click the action button
    cy.get('.action-btn').click()

    // Verify the button shows it was clicked
    cy.get('.action-btn')
      .should('contain', 'This popover shows up on click')
  })
})

What is the Arrange-Act-Assert pattern?

Arrange-Act-Assert is a standard way to structure tests. Arrange sets up the starting conditions (visiting the page). Act performs the user action (typing, clicking, submitting). Assert verifies the expected outcome (checking values, messages, visibility).

By putting the Arrange step in beforeEach, each test starts with a clean page load. This also keeps your tests DRY (Don't Repeat Yourself). Interviewers love asking about this pattern.

  • Save the file and switch to the Cypress test runner.
  • Click on actions.cy.js to run all three tests.

All three tests should pass. Click on any test in the Command Log to see the time-travel snapshots for each command.

Pro tip: watch the beforeEach

In the Command Log, you will see a BEFORE EACH section before every test showing the cy.visit() command. This confirms that each test gets a fresh page load, preventing tests from leaking state into each other.

Your test suite can now navigate pages, query elements, and interact with forms. Next up, you will externalize your test data into fixtures and learn how to run your entire suite headlessly from the command line.

Use Fixtures for Test Data and Run Headlessly

Your tests work, but they have a problem. The email address and coupon code are hardcoded directly into your test file. If those values ever change, you would need to hunt through every test to update them. Fixtures solve this by storing test data in a separate JSON file that any spec can reference. In this step, you will also set up npm scripts to run your tests headlessly from the command line, exactly how CI/CD pipelines execute them.

In This Step, Get Ready To:
  • Create a fixture file to externalize test data from your spec files.
  • Add npm scripts for interactive and headless test execution.
  • Review your complete project structure and confirm all tests pass.
Create a Fixture File with Test Data

Cypress looks for fixture files in the cypress/fixtures/ folder by default. You will create a JSON file with the test data your actions spec currently has hardcoded.

  • Create a new file at cypress/fixtures/testdata.json.
  • Add the following JSON object with your test data:
{
  "email": "testuser@example.com",
  "couponCode": "HALFOFF"
}

Now update your actions.cy.js to load this fixture instead of using hardcoded strings.

  • Open cypress/e2e/actions.cy.js.
  • Replace the entire file with the following code:
describe('Actions Tests', function () {
  // Load fixture data once before all tests in this block
  before(function () {
    cy.fixture('testdata').then(function (data) {
      this.testData = data
    })
  })

  // Visit the actions page before each test for a fresh state
  beforeEach(function () {
    cy.visit('https://example.cypress.io/commands/actions')
  })

  it('types into an input field and verifies the value', function () {
    cy.get('.action-email')
      .type(this.testData.email)
      .should('have.value', this.testData.email)
  })

  it('submits a form and verifies the result', function () {
    cy.get('.action-form')
      .find('[type="text"]')
      .type(this.testData.couponCode)

    cy.get('.action-form').submit()

    cy.get('.action-form')
      .next()
      .should('contain', 'Your form has been submitted!')
  })

  it('clicks a button and verifies the popover appears', function () {
    cy.get('.action-btn').click()
  })
})

You Must Use function() Instead of Arrow Functions

Notice that every describe, before, beforeEach, and it block uses function() instead of arrow functions (() =>). Arrow functions do not bind this, so this.testData would be undefined. This is one of the most common Cypress gotchas and a frequent interview question.

What is a Fixture?

A fixture is a file containing static test data that your tests can load and reference. Instead of scattering values like email addresses and coupon codes throughout your spec files, you store them in one place. When the test data changes, you update a single file instead of every test.

Why before Instead of beforeEach for Fixtures?

The before hook runs once before all tests in the describe block. The beforeEach hook runs before every single test. Fixture data is static JSON that does not change between tests, so loading it once with before is efficient. Page visits go in beforeEach because each test should start with a fresh page load.

Add npm Scripts for Running Tests

Typing npx cypress open and npx cypress run every time gets tedious. npm scripts give you short, memorable commands. They also standardize how your team runs tests.

  • Open package.json in VS Code.
  • Find the "scripts" section and replace it with the following:
"scripts": {
  "cy:open": "cypress open",
  "cy:run": "cypress run"
}

What Do These Scripts Do?

npm run cy:open launches the interactive Cypress test runner where you can watch tests execute in a browser. npm run cy:run runs all tests headlessly in the terminal using the bundled Electron browser. Headless mode is how CI/CD pipelines execute tests because there is no graphical interface on a build server.

Time to run your entire test suite headlessly.

  • Run the following command in your terminal:
npm run cy:run

Watch Cypress execute all your spec files one by one in the terminal. No browser window opens. You should see each spec file name followed by a list of passing tests.

What Should I See?

The terminal output shows a summary table with each spec file, the number of tests, the number of passing tests, and the execution time. All tests should show green checkmarks. At the bottom, you will see a total count like "All specs passed!" with the overall run time.

Tests Failing with this.testData Is Undefined?

This means you are using arrow functions somewhere in your actions.cy.js file. Check that every describe, before, beforeEach, and it block uses function() syntax. Help me debug my fixture loading issue.

Review Your Project Structure and Verify All Tests Pass

Before wrapping up, take a moment to review what you have built. Understanding your project structure is important because interviewers will ask you to describe how you organize your test suites.

  • Open the file explorer in VS Code and review your project structure.

Your project should look like this:

your-project/
├── cypress/
│   ├── e2e/
│   │   ├── actions.cy.js       # Form interaction tests
│   │   ├── navigation.cy.js    # Page load and URL tests
│   │   └── querying.cy.js      # Element selector tests
│   ├── fixtures/
│   │   └── testdata.json       # Shared test data
│   └── support/
│       ├── commands.js          # Custom commands (auto-generated)
│       └── e2e.js               # Support file (auto-generated)
├── cypress.config.js            # Cypress configuration
├── package.json                 # Project config with npm scripts
└── package-lock.json

Why This Structure Matters in Interviews

Interviewers want to see that you organize tests by feature area, not by test type. Each spec file covers a specific area of the application (navigation, querying, actions). Fixtures live in their own folder so any spec can access shared data. The support/ folder is where you would add custom commands as your test suite grows.

  • Run npm run cy:run one final time to confirm every test passes.

All specs should pass. This is the complete test suite you can walk an interviewer through.

You now have a professional, organized test suite with externalized test data and two ways to run it. Next up, try the Secret Mission to add network request interception, an advanced technique that will set you apart in senior QA interviews.

Secret mission

Intercept and Validate Network Requests

Ready to level up? Network request interception with cy.intercept() is an advanced Cypress feature that comes up in senior QA automation interviews. In this secret mission, you will spy on real HTTP requests and validate their responses and payloads.

Before you go

Clean Up Your Resources

This project runs entirely on your local machine, so there are no ongoing cloud costs. Decide whether to keep your resources as they are, pause them to come back later, or delete them entirely.

Resources you used:

  • Node.js and npm installed on your machine.
  • VS Code installed on your machine.
  • Cypress installed as a dev dependency in your project folder (including the Cypress binary).
  • Your project folder containing cypress.config.js, package.json, spec files, fixtures, and the node_modules folder.

Keep everything running

No action needed. Choose this if you are still actively building or plan to extend your test suite soon. Everything stays in place and ready to use.

  • Your project folder, Node.js, VS Code, and Cypress all remain installed.
  • You can run npm run cy:open or npm run cy:run anytime to re-run your tests.

Pause - I'll come back to this later

Free up disk space by removing the heaviest folder while keeping your project files intact. You can reinstall dependencies quickly when you come back.

  • Delete the node_modules folder inside your project directory. This is the largest folder and can be fully restored later.
  • Keep your project folder with all your spec files, cypress.config.js, package.json, and fixtures.
  • When you are ready to resume, open the project folder in VS Code, open the terminal, and run npm install to restore everything.
  • Keep Node.js and VS Code installed so you do not have to reinstall them.

Delete - I don't want to use this again

Remove all project resources and start fresh. Follow these steps to clean everything up.

  • Delete your entire project folder (the folder containing cypress.config.js and package.json).
  • Clear the Cypress binary cache by running npx cypress cache clear in any terminal before deleting the project folder.
  • Optionally uninstall Node.js from Settings > Apps > Apps & features if you no longer need it for other projects.
  • Optionally uninstall VS Code the same way if you do not plan to use it.

Mission accomplished

That's a Wrap!

Nice work! You just built a professional E2E test suite from scratch using Cypress. You have a real, runnable project you can demo in interviews to prove you can write, organize, and execute automated tests for web applications.

Here's what you accomplished:

  • Set up a Cypress project from zero on Windows, including Node.js, npm, and the Cypress test runner.
  • Wrote organized test specs across multiple files using core Cypress commands like cy.visit(), cy.get(), cy.contains(), .type(), .click(), and .should().
  • Used fixtures to externalize test data and ran your full suite headlessly with npm run cy:run, the same way CI/CD pipelines execute tests.
  • Intercepted and validated network requests using cy.intercept(), an advanced technique for API-aware testing that comes up in senior QA automation interviews.

Ready to quiz yourself?