Replace The cy.then Command

How to replace the confusing cy.then command with the less confusing cy.later command.

Many people complain that the Cypress cy.then command is confusing. It looks like a Promise, yet it is not.

  • you cannot replace it with async / await syntax sugar
  • it behaves differently from the Promise.then, for example if the callback returns undefined value, then the original subject value is passed to the next command or assertion

To avoid the confusion, you can disallow using the cy.then command completely.

1
2
3
4
5
6
7
8
9
// if anyone tries to use cy.then in the spec code or in a plugin
// we will get an error
Cypress.Commands.overwrite('then', function (then, subject, cb) {
throw new Error('Using cy.then command is disallowed')
})
cy.wrap('Hello')
.then(cy.log)
.then((x) => x + x)
.should('equal', 'HelloHello')

Banning the cy.then command

We still want the functionality of the cy.then command, but under the less confusing name. We do need the original cy.then command functionality. Thus we will grab the reference to the function so we can call it from our command. We can find the reference by inspecting the Cypress.Commands object.

All command functions are stored in Cypress.Commands._commands object

Let's add a custom command cy.later that calls the banned cy.then command function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// find and save the reference to the original cy.then command
// by inspecting the internals of the Cypress.Commands object
const thenCommand = Cypress.Commands._commands.then.fn

// if anyone tries to use cy.then in the spec code or in a plugin
// we will get an error
Cypress.Commands.overwrite('then', function (then, subject, cb) {
throw new Error('Using cy.then command is disallowed')
})

Cypress.Commands.add(
'later',
{ prevSubject: true },
(subject, cb) => {
// cy.later behaves just like cy.then
// which we implement by calling the original cy.then command
return thenCommand(subject, cb)
},
)

cy.wrap('Hello')
.later(cy.log)
.later((x) => x + x)
.should('equal', 'HelloHello')

The new command is working as expected, but hopefully does not lead the users down the wrong path.

The new custom command cy.later is working as expected

I hope this helps.

🎁 You can find the above code in a recipe at glebbahmutov.com/cypress-examples.