Skip to content

Cypress - Fixtures

Cypress - Managing Test Data with Fixtures

Section titled “Cypress - Managing Test Data with Fixtures”

Cypress fixtures are used to manage static data that your tests might need. They are typically external files (e.g., JSON, CSV, images, HTML) stored in the cypress/fixtures folder. Fixtures help in separating test data from test logic, making tests cleaner and more maintainable, especially for data-driven testing.

By default, Cypress looks for fixture files within the cypress/fixtures directory. You can organize your fixtures in subfolders within this directory.

The cy.fixture() command is used to load a fixture file. It yields the content of the file, which can then be used in subsequent Cypress commands or assertions.

cy.fixture(filePath)
cy.fixture(filePath, encoding)
cy.fixture(filePath, options)
cy.fixture(filePath, encoding, options)

Where:

  • filePath: Path to the fixture file (relative to the cypress/fixtures folder). E.g., ‘user.json’, ‘test-data/credentials.json’.
  • encoding (optional): Encoding to be used (e.g., ‘utf8’, ‘ascii’). Defaults to ‘utf8’ for most text-based files. For binary files like images, Cypress often infers this or you might set it to null.
  • options (optional): An object to modify default behavior, such as timeout. The default timeout for cy.fixture() is fixturesFolder.

Let’s say you have a cypress/fixtures/user.json file with the following content:

{
"username": "testUser",
"email": "test@example.com",
"password": "securePassword123"
}

You can load and use this data in your test:

describe('Login Functionality', () => {
it('should login with valid credentials from fixture', () => {
cy.fixture('user.json').then((userData) => {
cy.visit('/login');
cy.get('input[name="username"]').type(userData.username);
cy.get('input[name="password"]').type(userData.password);
cy.get('button[type="submit"]').click();
cy.url().should('include', '/dashboard');
cy.contains(`Welcome, ${userData.username}`).should('be.visible');
});
});
});

Using Fixtures with beforeEach or before Hooks

Section titled “Using Fixtures with beforeEach or before Hooks”

For data that’s used across multiple tests in a suite, it’s common to load fixtures in a beforeEach or before hook. You can use an alias (.as()) or the this context (with standard functions, not arrow functions for hooks/tests) to make the data available.

describe('User Profile Tests', () => {
beforeEach(() => {
// Load fixture and alias it
cy.fixture('userProfile.json').as('profileData');
cy.visit('/profile');
});
it('should display user information correctly', function() { // Use 'function' for 'this' context with aliases
// Access aliased data using this.profileData
cy.get('#userNameDisplay').should('contain.text', this.profileData.name);
cy.get('#userEmailDisplay').should('contain.text', this.profileData.email);
});
it('should allow updating profile details', function() {
cy.get('input[name="name"]').clear().type(this.profileData.newName);
// ... other actions
});
});

To use this.profileData, the test (it) and hook (beforeEach) must be standard functions, not arrow functions, because arrow functions do not have their own this binding.

Using this Context Directly (Traditional Approach)

Section titled “Using this Context Directly (Traditional Approach)”
describe('Registration Form', function() { // Note: using 'function' for 'this' context
before(function() {
cy.fixture('registrationData.json').then(function(data) {
this.testData = data; // Assign to 'this' context
});
});
it('should fill and submit the registration form', function() {
cy.visit('/register');
cy.get('input[name="fullName"]').type(this.testData.fullName);
cy.get('input[name="email"]').type(this.testData.email);
// ... fill other fields using this.testData
cy.get('button[type="submit"]').click();
cy.contains('Registration successful!').should('be.visible');
});
});

Fixtures are not limited to JSON. You can load images, text files, HTML, etc.

  • Images: cy.fixture('logo.png').then(fileContent => cy.get('input[type="file"]').attachFile({ fileContent, fileName: 'logo.png', mimeType: 'image/png' })); (using cypress-file-upload plugin as an example for attaching).
  • Text Files: cy.fixture('sample.txt').should('contain', 'Expected text');

Fixtures are essential for data-driven testing, where you run the same test logic with multiple data sets.

Example: cypress/fixtures/loginCredentials.json

[
{ "username": "validUser", "password": "validPass", "shouldSucceed": true },
{ "username": "invalidUser", "password": "wrongPass", "shouldSucceed": false },
{ "username": "validUser", "password": "", "shouldSucceed": false }
]

Test file:

describe('Login Data-Driven Tests', () => {
beforeEach(() => {
cy.visit('/login');
});
it('processes multiple login attempts from fixture', () => {
cy.fixture('loginCredentials.json').then((credentialsList) => {
credentialsList.forEach((creds) => {
cy.get('input[name="username"]').clear().type(creds.username || ''); // Handle empty username
cy.get('input[name="password"]').clear().type(creds.password || ''); // Handle empty password
cy.get('button[type="submit"]').click();
if (creds.shouldSucceed) {
cy.url().should('include', '/dashboard');
cy.visit('/login'); // Navigate back for next iteration if needed
} else {
cy.get('.error-message').should('be.visible');
// Clear fields or refresh page as needed for next iteration
cy.reload(); // Simple way to reset for next iteration
}
});
});
});
});

Note: For more complex data-driven scenarios, iterating within a single it block can make debugging harder. Consider generating tests dynamically if each data set represents a distinct test case. See Cypress documentation on dynamic tests.

Further Reading: