问题
What is the difference between a Custom Command and a Task? I am trying to understand how they should each be used.
Custom Command documentation: https://docs.cypress.io/api/cypress-api/custom-commands.html
Task documentation: https://docs.cypress.io/api/commands/task.html
回答1:
A command (most methods on cy object) is function that enqueues (pushes) an "action" to a queue of currently-executing commands, and executed serially and asynchronously (that's why return value of a command has .then method --- that being said, they are not promises, even though they kinda behave like that). Until a previous command isn't finished, the next command doesn't execute.
Commands are defined, and executed directly in the browser (but they can send message outside the browser, which is what cy.task is for, see below).
A custom command is nothing more than a regular command, just defined by user, 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. grouping several default cy commands together).
Commands are used to interact with your web app under test (AUT) --- mainly with the DOM, e.g. via cy.get(selector) to query the DOM; and to make assertions.
It's also important to realize that while commands are being executed serially, they are enqueued immediately, and any expressions you pass to them are evaluated then and there. This isn't a Cypress-specific behavior, but a JavaScript-specific behavior. This is why you can't do things like these (I've seen these errors pop up often):
let value;
cy.get('.myInput').invoke('val').then(val => value = val);
cy.get('.mySecondInput').type(value); // value is undefined here
A task is a function defined and executed on Cypress backend process (node), 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 (via an IPC channel --- explained below), where the task is executed.
If your task returns data, that data 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() call using .then(callback).
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.
As far as I know, there are no default tasks --- every task you execute you first need to define yourself.
Another important point is (as partly mentioned above), that the messages that are sent between processes (the Cypress browser process, and the Cypress node process) are sent via an inter-process-communication (IPC), 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).
来源:https://stackoverflow.com/questions/58680757/in-cypress-when-to-use-custom-command-vs-task