Learn Cypress - Fixtures & Test Data
Episode 6 of 23

Learn Cypress - Fixtures & Test Data

This episode covers test data management: storing static data in cypress/fixtures, loading JSON via cy.fixture, data-driven testing with external datasets, and mocking data and request stubs with cy.intercept.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Good tests separate data from logic. You don't want to change tests every time a dataset changes, and you don't want real user data leaking into tests. Episode 6 introduces fixtures — static data files that Cypress loads — and how to use them for data-driven testing and mocking.

By the end of this episode, your tests will use data that can be swapped from a single file without touching a line of logic.

Managing Test Data with Fixtures

Fixtures are stored in cypress/fixtures as JSON files. Example user dataset:

cypress/fixtures/users.json
{
  "admin": {
    "email": "admin@example.com",
    "nama": "Arman Admin"
  },
  "member": {
    "email": "member@example.com",
    "nama": "Dwi Member"
  }
}

This file is the single source of data for many tests. Need to add a new role? Just edit the JSON, without touching test code.

Loading Data with cy.fixture

cy.fixture() loads a file from the fixtures folder:

JSLoading a fixture with cy.fixture
beforeEach(() => {
  cy.fixture("users").as("users");
});
 
it("displays the admin name", function () {
  cy.get("[data-cy=user-name]").should("have.text", this.users.admin.nama);
});

cy.fixture("users") loads cypress/fixtures/users.json. With .as("users"), the data is stored as an alias accessible via this.users inside the test — that's why the test uses a regular function (), not an arrow function, because arrow functions don't bind Mocha's this.

Load and Transform in One Step

You can also load a fixture and process it in a single chain:

JSFixture with .then
cy.fixture("users").then((users) => {
  cy.get("[data-cy=email]").type(users.admin.email);
});

cy.fixture("users").then((users) => { ... }) gives you the JSON object directly inside the callback — a useful pattern when data is consumed right after being loaded.

Data-Driven Testing with External Datasets

Data-driven testing runs the same logic with many data points. Combine a fixture with an array:

JSData-driven test
describe("Form validation", () => {
  const cases = [
    { email: "", message: "Email is required" },
    { email: "not-an-email", message: "Invalid email format" },
  ];
 
  cases.forEach((c) => {
    it(`rejects email ${c.email || "empty"}`, () => {
      cy.get("[data-cy=email]").type(c.email);
      cy.get("[data-cy=submit]").click();
      cy.contains(c.message).should("be.visible");
    });
  });
});

Note the syntax rejects email ${c.email || "empty"} — a template literal used to build a descriptive test name. The forEach loop generates several tests from a single definition.

Using CSV from a Fixture

For large datasets, store the data as CSV in fixtures and parse it on load:

JSParse a CSV fixture
cy.fixture("products.csv").then((csv) => {
  const rows = csv.split("\n").slice(1);
  expect(rows).to.have.length.gt(10);
});

cy.fixture("products.csv") can load non-JSON files. Splitting off the header with .slice(1) and then processing the rows lets you test datasets with hundreds of rows using a single piece of logic.

Mocking Data and Request Stubs

Storing API Responses as Fixtures

Fixtures are very useful for stubbing API responses. Store a sample response as a fixture:

cypress/fixtures/api/products.json
[
  { "id": 1, "nama": "Kopi", "harga": 45000 },
  { "id": 2, "nama": "Teh", "harga": 20000 }
]

Then point cy.intercept at that fixture:

JSStub an API with a fixture
cy.intercept("GET", "/api/products", { fixture: "api/products" }).as("products");
 
cy.visit("/catalog");
cy.wait("@products");
 
cy.get("[data-cy=product]").should("have.length", 2);

cy.intercept("GET", "/api/products", { fixture: "api/products" }) replaces the real response with the fixture contents. cy.wait("@products") waits for the intercepted request. The result: tests run fast, deterministic, and without depending on the backend.

Info

This stub only covers the frontend under test. If you need to test real backend behavior, use cy.request() or full integration, which we'll cover in episode 12.

Closing

Episode 6 introduced fixtures as a test data source: storing static data in cypress/fixtures, loading it with cy.fixture() then using .as() or .then(), running data-driven testing with arrays and template literals, and stubbing API responses with fixtures through cy.intercept.

The key takeaways:

  • Fixtures are static data files in cypress/fixtures.
  • cy.fixture("users") loads a file; .as() makes it accessible via this.
  • Use a regular function (), not an arrow, when accessing this in a test.
  • Data-driven testing uses a forEach loop to build many tests.
  • Stub APIs with cy.intercept(..., { fixture }) to make tests deterministic.

In the next episode, episode 7, we will cover custom commands and utilities — adding custom commands in commands.js, creating reusable helpers for test flows, setting up baseUrl and environment vars, and organizing test utilities. Your test vocabulary starts to extend itself.

Learn Cypress - Fixtures & Test Data | Learn Cypress