Cypress - Variables
Cypress - Working with Variables and Aliases
Section titled “Cypress - Working with Variables and Aliases”In Cypress, managing values, elements, or results from commands requires understanding its asynchronous nature and command queue. You cannot simply assign the result of a Cypress command to a standard JavaScript variable like const el = cy.get('.my-element'); and expect el to hold the DOM element directly for immediate use outside the Cypress chain.
Instead, Cypress provides mechanisms like .then() (closures) and .as() (aliases) to work with yielded subjects (values or elements).
Using .then() for Immediate Access (Closures)
Section titled “Using .then() for Immediate Access (Closures)”When a Cypress command yields a subject (e.g., cy.get() yields a DOM element, cy.request() yields a response), you can use .then() to access that subject within a callback function. Inside this callback, you can use standard JavaScript variables (const, let) to store or manipulate the yielded value for the scope of that callback.
it('Captures and compares text using .then()', () => { cy.visit('/counter-app'); // Assume an app with a counter and increment button
cy.get('#counter-value').invoke('text').then((initialText) => { // initialText is the text content of #counter-value const initialCount = parseInt(initialText);
cy.log(`Initial count: ${initialCount}`); // Logs to Cypress Command Log
cy.get('#increment-button').click();
cy.get('#counter-value').invoke('text').then((newText) => { const newCount = parseInt(newText); cy.log(`New count: ${newCount}`);
// Assert that the new count is greater than the initial count expect(newCount).to.be.gt(initialCount); expect(newCount).to.eq(initialCount + 1); }); });});In this example, initialCount and newCount are standard const variables. They are only accessible within their respective .then() callback scopes. This is due to JavaScript closures.
Using Aliases (.as()) for Sharing Context
Section titled “Using Aliases (.as()) for Sharing Context”For sharing subjects (elements, route responses, fixture data) across different Cypress command chains or multiple test steps, Cypress provides aliases. You create an alias using .as('aliasName') and access it later using cy.get('@aliasName').
Aliases are particularly useful for:
- Storing DOM elements to interact with them multiple times without re-querying.
- Storing network request responses for assertions.
- Storing fixture data.
describe('Aliasing Example', () => { beforeEach(() => { cy.visit('/form-page'); // Alias an input field cy.get('input[name="email"]').as('emailInput'); cy.get('button[type="submit"]').as('submitButton'); });
it('Uses aliased elements for interaction', function() { // Use 'function' for 'this' with Cypress aliases // Access the aliased element using cy.get('@aliasName') cy.get('@emailInput').type('test@example.com'); cy.get('@submitButton').click();
// Or access via this.aliasName (if test is not an arrow function) // this.emailInput.type('another@example.com'); // Note: this.emailInput is the jQuery element });
it('Reuses aliased element for assertions', function() { cy.get('@emailInput').type('invalid-email').blur(); cy.get('@emailInput').should('have.class', 'error'); // Example assertion });
it('Stores and uses a value with an alias', () => { cy.get('#some-value-display').invoke('text').as('initialValue');
// ... perform some action that changes the value ... cy.get('#update-button').click();
cy.get('@initialValue').then((originalValue) => { cy.get('#some-value-display').invoke('text').should((newValue) => { expect(newValue).not.to.eq(originalValue); }); }); });});Accessing Aliases:
cy.get('@aliasName'): This is the most common way. It re-queries the DOM if the alias refers to a DOM element, ensuring you always get the current state.this.aliasName: If your test function (it,beforeEach, etc.) is a standardfunction() {}(not an arrow function() => {}), Cypress automatically makes the yielded subject of the alias available onthis. For DOM elements,this.aliasNamewill be the jQuery object yielded at the time of aliasing (it does not re-query).
const, let vs. Cypress Aliases
Section titled “const, let vs. Cypress Aliases”Use const or let inside .then() callbacks for temporary storage of processed values that don’t need to be shared broadly or re-accessed by Cypress commands later in the chain.
Use Cypress aliases (.as() and cy.get('@aliasName')) when you need to:
- Refer to the same DOM element(s) multiple times across different command chains.
- Share data (like network responses or fixture content) between test steps.
- Make yielded subjects available in Mocha’s
thiscontext.
Application Scenario: Verifying UI Updates
Section titled “Application Scenario: Verifying UI Updates”Imagine you have a button that, when clicked, updates a counter on the page. You want to verify the counter increments correctly.
it('Correctly increments a counter', () => { cy.visit('/my-interactive-page');
// Get the initial count and alias it cy.get('#counter').invoke('text').then(parseInt).as('initialCount');
// Click the increment button cy.get('#incrementBtn').click();
// Get the new count and compare with the aliased initial count cy.get('#counter').invoke('text').then(parseInt).then((newCount) => { cy.get('@initialCount').then((initialCount) => { expect(newCount).to.eq(initialCount + 1); }); });});This demonstrates using both .then() for immediate processing (like parseInt) and .as() for storing a value (initialCount) to be used later in the test flow.
Further Reading: