Yield value
Sometimes you might get an error that your test is "mixing up async and sync code". This happens when inside a Cypress chain of commands callback you have a Cypress command and a separate return X statement. Cypress is unsure if you want to yield the value X or the result of the last command.
Let's say you want to find the last name of the person in the DIV below.
<div id="person">Joe Smith</div>
The following code block will cause an error "mixing up async and sync code"
cy.get('#person')
.invoke('text')
.then((text) => {
// INCORRECT: mixing a Cypress command
// and a return value
cy.log('text', text)
return text.split(' ')[1]
})
.should('equal', 'Smith')

Cypress is unsure which value do you want to yield to the assertion .should('equal', 'Smith') - the result of the Cypress command cy.log? Or the result returned using the return ... statement?
Printing using cy.log can unexpectedly cause an error, because you do not assume it yields a value. But it is a Cypress command, just like cy.wrap. In the test below (which also causes the same error as above), do you expect to yield "Anna" or "Smith"?
cy.get('#person')
.invoke('text')
.then((text) => {
// INCORRECT: mixing a Cypress command
// and a return value
cy.wrap('Anna')
return text.split(' ')[1]
})
.should('equal', 'Smith')
Solutions
- Move the return statement into its own
.thencallback
cy.get('#person')
.invoke('text')
.then((text) => {
cy.wrap('Anna').then(() => {
return text.split(' ')[1]
})
})
.should('equal', 'Smith')
- Wrap the value to return using the cy.wrap command
cy.get('#person')
.invoke('text')
.then((text) => {
cy.log('text', text)
cy.wrap(text.split(' ')[1])
})
.should('equal', 'Smith')
- Print the text using a separate
.thencallback. If the.thencallback returnsundefined, then its original value is yielded to the next command by Cypress.
cy.get('#person')
.invoke('text')
.should('be.a', 'string')
.then((text) => {
return text.split(' ')[1]
})
.should('equal', 'Smith')
Tip: you can perform data manipulation steps using cy.invoke and cy.its commands
cy.get('#person')
.invoke('text')
.should('be.a', 'string')
.invoke('split', ' ')
.its(1)
.should('equal', 'Smith')
To see the same explanation, you can watch the video Fix The Cypress Error "You are mixing async and sync code"