Custom command that calls another custom command won’t get its value in Cypress

I have an object and I need to modify some of its attributes. For this I’m using custom commands and the first one modifies a couple of them when the second modifies only one but I execute the second custom command from the first one. When I execute my test, the attribute modified by the second command is null. How can I do this?

Here’s a sample of how my code looks:

Cypress.Commands.add("firstCommand", (varA, objectB) => {
  let aBody = {};
  aBody.a = varA;
  cy.modifiesOtherAttr(aBody, objectB);
})

Cypress.Commands.add("modifiesOtherAttr", (aBody, objectB) => {
  aBody.b = objectB.attrb;
})

Then my test only calls the first command

describe("a suite name", () => {
  it("my test name", () => {
    cy.firstCommand(variable, object);
})
})

Answer

Ideally you want to be specific about the return value from each custom command.

However, Cypress will pick up the last command inside the custom command and return it’s subject. But within firstCommand the last command is modifiesOtherAttr which does not have a return value or any cy command, so Cypress returns undefined which is then what firstCommand returns.

Since you create a new object aBody, it should be explicitly returned.

Cypress.Commands.add("firstCommand", (varA, objectB) => {
  let aBody = {};
  aBody.a = varA;
  cy.modifiesOtherAttr(aBody, objectB)
  cy.wrap(aBody)                         // this is the return value
});

Cypress.Commands.add("modifiesOtherAttr", (aBody, objectB) => {
  aBody.b = objectB.attrb  // "side effect" happens here, nothing returned
});

OR

Cypress.Commands.add("firstCommand", (varA, objectB) => {
  let aBody = {};
  aBody.a = varA;
  cy.modifiesOtherAttr(aBody, objectB)  // this is the return value
});

Cypress.Commands.add("modifiesOtherAttr", (aBody, objectB) => {
  aBody.b = objectB.attrb  
  cy.wrap(aBody)                         // this is the return value
});

Explicit is better

Cypress.Commands.add("firstCommand", (varA, objectB) => {
  let aBody = {};
  aBody.a = varA;
  cy.modifiesOtherAttr(aBody, objectB)  
  return cy.wrap(aBody)                         // this is the return value
});

Cypress.Commands.add("modifiesOtherAttr", (aBody, objectB) => {
  aBody.b = objectB.attrb  
  return cy.wrap(aBody)                         // this is the return value
});