then

Enables you to work with the subject yielded from the previous command.

Syntax

.then(callbackFn)
.then(options, callbackFn)

Usage

Correct Usage

cy.get('.nav').then(($nav) => {}) // Yields .nav as first arg
cy.location().then((loc) => {}) // Yields location object as first arg

Arguments

options (Object)

Pass in an options object to change the default behavior of .then().

OptionDefaultDescription
timeoutdefaultCommandTimeoutTime to wait for .then() to resolve before timing out

callbackFn (Function)

Pass a function that takes the previously yielded subject as its first argument.

Yields

Whatever is returned from the callback function becomes the new subject and will flow into the next command (with the exception of undefined or null). If the return value is a Promise or other "thenable" (anything with a .then() interface), Cypress will wait for it to resolve before continuing forward through the chain of commands.

If undefined or null are returned (or there is no return), the result of the last Cypress command in the callback function will be yielded as the new subject instead, and flow into the next command.

If undefined or null are returned (or there is no return) and the callback does not call any Cypress commands, the subject will not be modified and the previous subject will carry over to the next command.

.then() is a command, and will not be retried. It is unsafe to return DOM elements from the callback and then use further assertions, queries of commands on them.

Examples

DOM element

The button element is yielded

cy.get('button').then(($btn) => {
  const cls = $btn.attr('class')

  cy.wrap($btn).click().should('not.have.class', cls)
})

The number is yielded from previous command

cy.wrap(1)
  .then((num) => {
    cy.wrap(num).should('equal', 1) // true
  })
  .should('equal', 1) // true

Change subject

The el subject is changed with another command

cy.get('button')
  .then(($btn) => {
    const cls = $btn.attr('class')

    cy.wrap($btn).click().should('not.have.class', cls).find('i')
    // since there is no explicit return
    // the last Cypress command's yield is yielded
  })
  .should('have.class', 'spin') // assert on i element

The number subject is changed with another command

cy.wrap(1).then((num) => {
  cy.wrap(num)).should('equal', 1) // true
  cy.wrap(2)
}).should('equal', 2) // true

The number subject is changed by returning

cy.wrap(1)
  .then((num) => {
    cy.wrap(num).should('equal', 1) // true

    return 2
  })
  .should('equal', 2) // true

Returning undefined will not modify the yielded subject

cy.get('form')
  .then(($form) => {
    console.log('form is:', $form)
    // undefined is returned here, but $form will be
    // yielded to allow for continued chaining
  })
  .find('input')
  .then(($input) => {
    // we have our $input element here since
    // our form element was yielded and we called
    // .find('input') on it
  })

Raw HTMLElements are wrapped with jQuery

cy.get('div')
  .then(($div) => {
    return $div[0] // type => HTMLDivElement
  })
  .then(($div) => {
    $div // type => JQuery<HTMLDivElement>
  })

Promises

Cypress waits for Promises to resolve before continuing

Example using Q

cy.get('button')
  .click()
  .then(($button) => {
    const p = Q.defer()

    setTimeout(() => {
      p.resolve()
    }, 1000)

    return p.promise
  })

Example using bluebird

cy.get('button')
  .click()
  .then(($button) => {
    return Promise.delay(1000)
  })

Example using jQuery deferred's

cy.get('button')
  .click()
  .then(($button) => {
    const df = $.Deferred()

    setTimeout(() => {
      df.resolve()
    }, 1000)

    return df
  })

Notes

Differences

What's the difference between .then() and .should()/.and()?

Using .then() allows you to use the yielded subject in a callback function and should be used when you need to manipulate some values or do some actions.

When using a callback function with .should() or .and(), on the other hand, there is special logic to rerun the callback function until no assertions throw within it. You should be careful of side affects in a .should() or .and() callback function that you would not want performed multiple times.

Rules

Requirements

  • .then() requires being chained off a previous command.

Assertions

  • .then() will only run assertions you have chained once, and will not retry .

Timeouts

  • .then() can time out waiting for a promise you've returned to resolve.

Command Log

  • .then() does not log in the Command Log

History

VersionChanges
0.14.0Added timeout option
< 0.3.3.then() command added

See also