In Cypress when to use Custom Command vs Task?
A command (most methods on the global
cy object) is a function that enqueues (pushes) an action to a queue of currently-executing commands. The queue executes serially and asynchronously (that's why return value of a command is an object having a
.then method --- but despite that and the fact it behaves like promise, it's not a promise). Until a previous command is finished, the next command doesn't execute.
Commands are defined and executed directly in the browser.
A custom command is a regular command, but defined by you as opposed to the default commands that Cypress supplies out of the box. Custom commands are useful for automating a workflow you repeat in your tests over and over (e.g. by grouping several default
cy commands together).
Commands are used to interact with your web app under test (AUT) --- most notably with the DOM (e.g. via
cy.get(selector) to query the DOM), and to make assertions.
// INCORRECT USAGE let value; cy.get('.myInput').invoke('val').then(val => value = val); cy.get('.mySecondInput').type(value); // ✗ value is undefined here
Nor can you use async/await:
// INCORRECT USAGE let value; // ✗ doesn't work on Cypress commands const value = await cy.get('.myInput').invoke('val'); cy.get('.mySecondInput').type(value);
A task is a function defined and executed on the Cypress backend process (Node.js), not in the browser.
To execute a task (which you previously defined in your
cypress/plugins/index.js file), you need to first enqueue it as a regular command in your test via
cy.task(taskName, data). Cypress then (when the command takes its turn to execute) sends a message to the backend process where the task is executed.
Data your task returns is serialized (via
JSON.stringify or something similar) and sent back to the browser where it's passed to a callback you potentially chained to your
cy.task() command using
Tasks are mainly used to communicate with your own server backend, to e.g. seed the database; or for I/O such as reading/writing to a file (although cypress supplies commands for these such as
There are no default tasks --- every task you execute you first need to define yourself.
Another important point is that the messages that are sent between processes (the Cypress browser process, and the Cypress node process) are sent via an IPC channel, and must be serializable. That means that the data you pass to
cy.task(taskName, data) are stringified, as well as is the response returned from the task itself. Thus, sending e.g. an object containing a method will not work (that is, the method won't be transferred at all).
Great answers but in order to sum up, here are two main differences that help you choose whether you need a Cypress command or a task :
- If you need to run a promise or interact with your backend, go with a task.
- If you are interacting with the DOM and making assertions, go with a command.
Taken from this article