Improve this doc

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

Note: .then() assumes you are already familiar with core concepts such as closures.


.then(options, callbackFn)


Correct Usage

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


options (Object)

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

Option Default Description
timeout defaultCommandTimeout Time to wait for .then() to resolve before timing out

callbackFn (Function)

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


.then() is modeled identically to the way Promises work in JavaScript. Whatever is returned from the callback function becomes the new subject and will flow into the next command (with the exception of undefined).

When undefined is returned by the callback function, the subject will not be modified and will instead carry over to the next command.

Just like Promises, you can return any compatible “thenable” (anything that has a .then() interface) and Cypress will wait for that to resolve before continuing forward through the chain of commands.


We have several more examples in our Core Concepts Guide which go into the various ways you can use .then() to store, compare, and debug values.

DOM element

The element input is yielded

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

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

Change subject

The subject is changed by returning

cy.wrap(null).then(() => {
  return { id: 123 }
.then((obj) => {
  // subject is now the obj {id: 123}
  expect( // true

Returning null or undefined will not modify the yielded subject

.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


Cypress waits for Promises to resolve before continuing

Example using Q

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

  setTimeout(() => {
  }, 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(() => {
  }, 1000)

  return df



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

Using .then() simply 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.



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


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


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

Command Log

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

See also