Cypress Examples

website·Indexed 43 days ago

https://example.cypress.io

A collection of practical examples demonstrating Cypress commands and API usage, including querying with cy.get(), network requests via cy.request() and cy.intercept(), assertions using .should(), and managing storage, cookies, and viewports.

Tokens
10.3K
Snippets
86
Records
86
Agent score
68%

What's inside Cypress

  1. Use explicit TDD assertions with assert

    Use assert to make TDD-style assertions about a specific subject.
    const person = {
      name: 'Joe',
      age: 20,
    }
    assert.isObject(person, 'value is object')
  2. Use explicit BDD assertions with expect

    Use expect to make BDD-style assertions about a specific subject. Unlike .should(), expect is an explicit assertion and does not automatically retry.
    expect(true).to.be.true
    const o = { foo: 'bar' }
    expect(o).to.equal(o)
    expect(o).to.deep.equal({ foo: 'bar' })
    // Match text using regular expression
    expect('FooBar').to.match(/bar$/i)
  3. Perform implicit assertions with .should()

    Use the .should() command to make assertions about the current subject in a Cypress chain. This command is used to verify the state or behavior of an element, such as its class, text content, HTML, or visibility.
    cy.get('.assertion-table')
      .find('tbody tr:last').should('have.class', 'success')
      .find('td')
      .first()
      // Check text content
      .should('have.text', 'Column content')
      .should('contain', 'Column content')
      .should('have.html', 'Column content')
      // Check if element matches a selector
      .should('match', 'td')
      // Match text content against a regular expression
      .invoke('text')
      .should('match', /column content/i)
    
    // Alternative: use cy.contains for regex text matching
    cy.get('.assertion-table')
      .find('tbody tr:last')
      .contains('td', /column content/i)
      .should('be.visible')
  4. Best practices for selecting elements

    To ensure tests are resilient to styling and structural changes, prefer dedicated test attributes (like data-cy or data-test) over CSS classes, IDs, or text content. Avoid generic selectors (like button) or those coupled to styling (like .btn-large).
    // ❌ Worst: Too generic
    cy.get('button').click()
    
    // ❌ Bad: Coupled to styling
    cy.get('.btn.btn-large').click()
    
    // ⚠️ Average: Coupled to HTML semantics
    cy.get('[name=submission]').click()
    
    // ⚠️ Better: Coupled to ID/Styling
    cy.get('#main').click()
    
    // ⚠️ Much better: Coupled to text (may change)
    cy.contains('Submit').click()
    
    // ✅ Best: Insulated from changes
    cy.get('[data-cy=submit]').click()
  5. Monitor function calls using cy.spy()

    Use cy.spy() to wrap an existing method to track its calls without changing its behavior. cy.spy() retries until the assertions that follow it pass, making it useful for asynchronous operations.
    const obj = {
      foo () {},
    }
    
    // Wrap method and create an alias
    const spy = cy.spy(obj, 'foo').as('foo')
    
    setTimeout(() => {
      obj.foo()
    }, 500)
    
    // Assertion will retry until the spy has been called twice
    cy.get('@foo').should('have.been.calledTwice')
  6. Handle subjects and values using cy.then()

    Use the .then() command to invoke a callback function with the current subject.

    Behavioral rules for yielding values:

    1. If the callback returns a value, that value is yielded to the next command.
    2. If the callback returns undefined, the original subject passed into .then() is yielded to the next command.
    3. If the callback contains Cypress commands, the value yielded by the last Cypress command in the block is passed to the next callback.
    // Example 1: Basic usage and returning a value
    cy.wrap(1)
      .then((num) => {
        expect(num).to.equal(1)
        return 2
      })
      .then((num) => {
        expect(num).to.equal(2)
      })
    
    // Example 2: Returning undefined yields the original value
    cy.wrap(1)
      .then((num) => {
        expect(num).to.equal(1)
        // nothing returned
      })
      .then((num) => {
        expect(num).to.equal(1)
      })
    
    // Example 3: Last Cypress command in block determines the yielded value
    cy.wrap(1)
      .then((num) => {
        expect(num).to.equal(1)
        cy.wrap(2) // This value is yielded
      })
      .then((num) => {
        expect(num).to.equal(2)
      })
  7. Control and manipulate browser time with cy.clock() and cy.tick()

    Use cy.clock() to freeze the browser's clock at a specific time (recommended to use UTC to ensure consistency across timezones). Use cy.tick() to move the clock forward by a specified number of milliseconds.
    // Set clock to a specific UTC date
    const now = new Date(Date.UTC(2017, 2, 14)).getTime()
    cy.clock(now)
    
    cy.visit('/your-page')
    cy.get('#clock-div').click()
    cy.get('#clock-div').should('have.text', '1489449600')
    
    // Move time forward by 10 seconds
    cy.tick(10000)
    
    cy.get('#clock-div').click()
    cy.get('#clock-div').should('have.text', '1489449610')
  8. Create complex assertions using .should() with a callback

    When built-in assertions are insufficient, pass a callback function to .should(). Cypress will retry the entire callback function until all explicit assertions inside it pass or the command times out. This is particularly useful for:

    1. Performing multiple assertions on a single subject.
    2. Retrying logic that involves data transformation (e.g., parsing text to a number).
    3. Comparing values between two different elements by saving a value in a variable and asserting it within the callback.
    // Example 1: Complex checks on multiple elements
    cy.get('.assertions-p').find('p')
      .should(($p) => {
        let texts = $p.map((i, el) => Cypress.$(el).text()).get()
        expect(texts).to.have.length(3)
        expect(texts, 'has expected text in each paragraph').to.deep.eq([
          'Some text from first p',
          'More text from second p',
          'And even more text from third p',
        ])
      })
    
    // Example 2: Retrying until a value is parsed correctly
    cy.get('#random-number')
      .should(($div) => {
        const n = parseFloat($div.text())
        expect(n).to.be.gte(1).and.be.lte(10)
      })
    
    // Example 3: Comparing two elements
    let text
    cy.get('.two-elements').find('.first').then(($first) => {
      text = $first.text().toLowerCase().replace(/\s/g, '')
    })
    cy.get('.two-elements').find('.second').should(($div) => {
      const secondText = $div.text().toLowerCase().replace(/\s/g, '')
      expect(secondText, 'second text').to.equal(text)
    })
    
  9. Load JSON fixtures using cy.fixture() vs require

    JSON fixtures can be loaded using the asynchronous cy.fixture() command (which can be aliased to the test context this) or synchronously using the JavaScript require() function via the built-in bundler.
    // Synchronous load using require
    const requiredExample = require('../../fixtures/example')
    
    beforeEach(() => {
      // Asynchronous load and alias to test context
      cy.fixture('example.json').as('example')
    })
    
    it('compare fixture and require', function () {
      // Access aliased fixture via 'this'
      expect(this.example).to.deep.equal(requiredExample)
    
      // Or use cy.wrap
      cy.wrap(this.example).should('deep.equal', requiredExample)
    })
    
  10. Replace function behavior using cy.stub()

    Use cy.stub() to replace a function with a stub. This allows you to control the return value, throw errors, or track calls. You can use .callThrough() to allow non-matched calls to execute the original method.
    const greeter = {
      greet (name) {
        return `Hello, ${name}!`
      },
    }
    
    cy.stub(greeter, 'greet')
      .callThrough() // Original method is called if no matchers apply
      .withArgs(Cypress.sinon.match.string).returns('Hi')
      .withArgs(Cypress.sinon.match.number).throws(new Error('Invalid name'))
    
    expect(greeter.greet('World')).to.equal('Hi')
    expect(() => greeter.greet(42)).to.throw('Invalid name')
  11. Chain and share data between cy.request() calls

    You can pass response data to subsequent requests using .then() or save data to the shared test context using .as().

    Important: When using .as() to save an alias, you must use the function () { ... } callback syntax instead of arrow functions to access the shared context via this.

    cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
      .its('body.0')
      .as('user') // saves the object in the test context
      .then(function () {
        // Use function() syntax to access 'this.user'
        cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
          userId: this.user.id,
          title: 'Cypress Test Runner',
          body: 'Fast, easy and reliable testing for anything that runs in a browser.',
        })
        .its('body').as('post')
      })
      .then(function () {
        expect(this.post).property('userId').to.equal(this.user.id)
      })
  12. Alias DOM elements and network routes using .as()

    Use the .as() command to assign a name (alias) to a DOM element or a network intercept. This avoids repeating long selector chains and allows you to reference the element or request later in the test by prefixing the alias name with @.
    // 1. Aliasing a DOM element to avoid repeating a complex selector
    cy.get('.as-table')
      .find('tbody>tr').first()
      .find('td').first()
      .find('button').as('firstBtn')
    
    // Reference the alias using '@'
    cy.get('@firstBtn').click()
    cy.get('@firstBtn').should('have.class', 'btn-success')
    
    // 2. Aliasing a network route to wait for a response
    cy.intercept('GET', '**/comments/*').as('getComment')
    
    // Trigger the action that causes the network request
    cy.get('.network-btn').click()
    
    // Wait for the aliased route and assert on the response
    cy.wait('@getComment').its('response.statusCode').should('eq', 200)