Lesson 10 / 25

Commands and Chaining

cy.visit, cy.get, cy.contains.

A queue, not promises

Cypress tests use Mocha-style describe and it. Calls such as cy.visit('/'), cy.get('[data-cy=email]'), cy.contains('button', 'Save'), .type() and .click() do not run immediately: they are enqueued and executed in order after the test function returns. Each command yields a subject to the next one in the chain. Because commands are not promises, you cannot await them or assign their result to a variable; use .then() to work with a yielded value, or aliases (.as('name')) to refer to it later. cy.get searches the whole document, while .find() and .within() scope to the current subject.

Commands that queue, assertions that retry

Cypress tests chain commands that run in order inside the browser, retrying queries until assertions pass.

Three ideas: commands and chaining, retry-ability and should, cy.intercept.
Figure 4.1 — The Cypress command queue, retries and intercepted requests.

A login flow

Chaining, scoping and reading a value with then.

// cypress/e2e/login.cy.ts
describe('login', () => {
  it('signs in and greets the user', () => {
    cy.visit('/login');
    cy.get('[data-cy=email]').type('asha@example.com');
    cy.get('[data-cy=password]').type('correct horse', { log: false });
    cy.contains('button', 'Sign in').click();

    cy.location('pathname').should('eq', '/dashboard');
    cy.get('nav').within(() => {
      cy.contains('Asha').should('be.visible');
    });

    cy.get('[data-cy=plan]').invoke('text').then((plan) => {
      expect(plan.trim()).to.match(/Free|Pro/);
    });
  });
});

Writing a to-do list for a helper

Your test function writes a list of instructions and hands it over; the helper then works through it step by step. Asking "what did step three return?" while you are still writing the list makes no sense.

Quick check: Why can you not write `const el = await cy.get('button')`?

  • Cypress commands are enqueued and are not promises
  • cy.get only works in component tests
  • TypeScript forbids await in tests
  • cy.get returns a plain string
Answer

Cypress commands are enqueued and are not promises — Use .then() or aliases to work with yielded values.