invoke
Invoke a function on the previously yielded subject.
If you want to get a property that is not a function on the previously yielded
subject, use .its()
.
If you chain further methods off of .invoke()
, it will be called multiple
times. If the method is not idempotent, treat .invoke()
like a command, and
consider it unsafe to chain further methods. You can use
.end()
to make this extra clear in your test.
Syntax
.invoke(functionName)
.invoke(options, functionName)
.invoke(functionName, args...)
.invoke(options, functionName, args...)
Usage
Correct Usage
cy.get('.input').invoke('val').should('eq', 'foo') // Invoke the 'val' function
cy.get('.modal').invoke('show') // Invoke the jQuery 'show' function
cy.wrap({ animate: fn }).invoke('animate') // Invoke the 'animate' function
Incorrect Usage
cy.invoke('convert') // Errors, cannot be chained off 'cy'
cy.wrap({ name: 'Jane' }).invoke('name') // Errors, 'name' is not a function
cy.wrap({ animate: fn })
.invoke('animate')
.then(() => {}) // 'animate' will be called multiple times
Arguments
functionName (String, Number)
Name of function to be invoked.
options (Object)
Pass in an options object to change the default behavior of .invoke()
.
Option | Default | Description |
---|---|---|
log | true | Displays the command in the Command log |
timeout | defaultCommandTimeout | Time to wait for .invoke() to resolve before timing out |
args...
Additional arguments to be given to the function call. There is no limit to the number of arguments.
Yields
.invoke()
yields the return value of the method..invoke()
is a query, and it is safe to chain further methods.
Examples
Function
Assert on a function's return value
const fn = () => {
return 'bar'
}
cy.wrap({ foo: fn }).invoke('foo').should('eq', 'bar') // true
.invoke()
to test HTML content
Use
Properties that are functions are invoked
In the example below, we use .invoke()
to force a hidden div to be
'display: block'
so we can interact with its children elements.
cy.get('div.container')
.should('be.hidden') // element is hidden
.invoke('show') // call jquery method 'show' on the '.container'
.should('be.visible') // element is visible now
.find('input') // drill down into a child "input" element
.type('Cypress is great') // and type text
.invoke('show')
and .invoke('trigger')
Use
Function with Arguments
Send specific arguments to the function
const fn = (a, b, c) => {
return a + b + c
}
cy.wrap({ sum: fn })
.invoke('sum', 2, 4, 6)
.should('be.gt', 10) // true
.and('be.lt', 20) // true
cy.invoke('removeAttr', 'target')
to get around new tab
Use
Arguments are automatically forwarded to the function
cy.get('img').invoke('attr', 'src').should('include', 'myLogo')
Arrays
In the above examples, the subject was an object, but cy.invoke
also works on
arrays and allows using numerical index to pick a function to run.
const reverse = (s) => Cypress._.reverse(s)
const double = (n) => n * n
// picks function with index 1 and calls it with argument 4
cy.wrap([reverse, double]).invoke(1, 4).should('eq', 16)
Invoking an async function
In this example we have a little text input field and we invoke an async action
which will disable this input field. .invoke()
will then wait until the
Promise resolves and only then will continue executing to check if it really has
been disabled.
Our input field
<input type="text" name="text" data-cy="my-text-input" />
The Cypress test with cy.invoke()
awaiting the promise:
function disableElementAsync(element) {
return new Promise((resolve) => {
setTimeout(() => {
element.disabled = true
resolve()
}, 3000)
})
}
cy.get('[data-cy=my-text-input]').then((textElements) => {
cy.wrap({ disableElementAsync }).invoke(
'disableElementAsync',
textElements[0]
)
})
// log message appears after 3 seconds
cy.log('after invoke')
// assert UI
cy.get('[data-cy=my-text-input]').should('be.disabled')
For a full example where invoke is used to await async Vuex store actions, visit the recipe: Vue + Vuex + REST
jQuery method
If the parent command yields a jQuery element, we can invoke a jQuery method,
like attr
, text
, or val
. To confirm the element's id
attribute for
example:
<div id="code-snippet">The code example</div>
cy.contains('The code example')
.invoke('attr', 'id')
.should('equal', 'code-snippet')
Tip: Cypress has a built-in Chai-jQuery assertion to confirm the attribute. The above example can be written simply as:
cy.contains('The code example').should('have.attr', 'id', 'code-snippet')
Notes
Third Party Plugins
Using a Kendo DropDown
If you are using jQuery
then the jQuery
wrapped elements will automatically
have your 3rd party plugins available to be called.
cy.get('input')
.invoke('getKendoDropDownList')
.then((dropDownList) => {
// yields the return of $input.getKendoDropDownList()
return dropDownList.select('apples')
})
We can rewrite the previous example in a more terse way and add an assertion.
cy.get('input')
.invoke('getKendoDropDownList')
.invoke('select', 'apples')
.invoke('val')
.should('match', /apples/)
Retries
.invoke()
automatically retries invoking the specified method until the
returned value satisfies the attached assertions. The example below passes after
1 second.
let message = 'hello'
const english = {
greeting() {
return message
},
}
setTimeout(() => {
message = 'bye'
}, 1000)
// initially the english.greeting() returns "hello" failing the assertion.
// .invoke('greeting') tries again and again until after 1 second
// the returned message becomes "bye" and the assertion passes
cy.wrap(english).invoke('greeting').should('equal', 'bye')
Rules
Requirements
-
.invoke()
requires being chained off a previous command.
Assertions
-
.invoke()
will wait for thefunction
to exist on the subject before running. -
.invoke()
will wait for the promise to resolve if the invokedfunction
returns a promise. -
.invoke()
will automatically retry until all chained assertions have passed
Timeouts
-
.invoke()
can time out waiting for assertions you've added to pass. -
.invoke()
can time out waiting for a promise you've returned to resolve.
Command Log
Invoke jQuery show method on element
cy.get('.connectors-div')
.should('be.hidden')
.invoke('show')
.should('be.visible')
The commands above will display in the Command Log as:
When clicking on invoke
within the command log, the console outputs the
following:
History
Version | Changes |
---|---|
12.0.0 | .invoke() no longer supports promises or async functions |
3.8.0 | Added support for options argument |
3.7.0 | Added support for arguments of type Number for functionName |