then
Enables you to work with the subject yielded from the previous command.
info
Note: .then()
assumes you are already familiar with core concepts such as
closures.
info
Note: Prefer .should()
with callback over
.then()
for assertions as they are automatically rerun until no assertions
throw within it but be aware of differences.
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()
.
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.
Yields
.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
).
Additionally, the result of the last Cypress command in the callback function
will be yielded as the new subject and flow into the next command if there is no
return
.
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.
Examples
info
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 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](/guides/core-concepts/retry-ability).
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
Version | Changes |
---|---|
0.14.0 | Added timeout option |
< 0.3.3 | .then() command added |