Cypress wrap(): Handling Objects, Elements, and Promises

Cypress’s cy.wrap() command is a powerful tool for integrating non-Cypress values into your test command chain.

Understanding cy.wrap()

The cy.wrap() command yields the object passed into it. If the object is a promise, it yields the resolved value.

Syntax

cy.wrap(subject)
cy.wrap(subject, options)

Arguments

  • subject: The object to be yielded
  • options:
  • log (Boolean): Display command in Command log (default: true)
  • timeout (Number): Time to wait before timing out (default: defaultCommandTimeout)

Key Use Cases

1. Working with Objects

const getName = () => {
  return 'Jane Lane'
}

cy.wrap({ name: getName }).invoke('name').should('eq', 'Jane Lane')

2. Handling DOM Elements

Basic Element Wrapping

cy.get('form').within(($form) => {
  cy.wrap($form).should('have.class', 'form-container')
})

Conditional Wrapping

cy.get('button').then(($button) => {
  if ($button.someMethod() === 'something') {
    cy.wrap($button).click()
  }
})

3. Managing Promises

Simple Promise Example

const myPromise = new Promise((resolve) => {
  setTimeout(() => {
    resolve({
      type: 'success',
      message: 'It worked!'
    })
  }, 2500)
})

it('should wait for promises', () => {
  cy.wrap(myPromise).its('message').should('eq', 'It worked!')
})

Real-world Authentication Example

import { userService } from '../../src/_services/user.service'

it('authenticates with wrapped promise', () => {
  const username = Cypress.env('username')
  const password = Cypress.env('password')

  cy.wrap(userService.login(username, password))
    .should('be.an', 'object')
    .and('have.keys', ['firstName', 'lastName', 'username', 'id', 'token'])

  cy.visit('/')
  cy.contains('Hi Test!').should('be.visible')
})

Advanced Patterns

1. Working with API Responses

Direct Function Wrap

function fetchDataFromApi() {
  return fetch('https://www.bstackdemo.com/api/products')
    .then((response) => response.json())
}

it("Wraps API function", () => {  
  cy.wrap(fetchDataFromApi()).its("products").then((data) => {
    cy.wrap(data).its(0).should("have.property", "title", "iPhone 12")
  })
})

Intercept and Wrap

it("Advanced API wrapping", () => {
  cy.intercept("api/products").as("productList")
  cy.visit("https://www.bstackdemo.com/")

  cy.wait("@productList").then((responseData) => {
    cy.wrap(responseData.response.body)
      .its("products")
      .its(0)
      .should("have.property", "title", "iPhone 12")
  })
})

2. Proper Async Handling

Important Note: cy.wrap() doesn’t synchronize async function calls automatically. For proper sequencing:

// ❌ Problematic approach
cy.wrap(foo()) // Executes immediately
cy.get('button').click()
cy.wrap(bar()) // Might execute before click completes

// ✅ Correct approach
cy.wrap(foo())
cy.get('button')
  .click()
  .then(() => {
    cy.wrap(bar()) // Executes after click completes
  })

When to Use cy.wrap()

  1. To integrate jQuery elements or custom DOM queries into Cypress chains
  2. When working with promises from application code
  3. To assert against complex objects while maintaining command chaining
  4. When you need to conditionally execute Cypress commands on non-Cypress objects

Best Practices

  1. Always wrap promises returned by application code
  2. Use .then() for proper command sequencing
  3. Combine with .its() for clean property assertions
  4. Leverage aliases (as()) for complex objects you’ll reuse


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *