6

I've read that in Cypress I should not use await and that it is not needed because you can remove nesting through chaining. Here I have a cy.fixure nested in cy.origin nested in cy.session, is there a way to flatten this?

  cy.session([], () => {
    cy.visit("")
    cy.origin("https://my-address.com", () => {
      cy.fixture("user").then((user) => {
        cy.get("#username").type(user.username)
        cy.get("#password").type(user.password)
      })

      cy.get("button[type='submit']").click()
      cy.url().should("equal", "/login-success")
    })
  })

Edit
This is not a question regarding regular javascript, it's Cypress specific and normal async / await won't work here.

Cara Gee
  • 129
  • 6
Baki
  • 564
  • 2
  • 10
  • 22
  • Does this answer your question? [How do I access previous promise results in a .then() chain?](https://stackoverflow.com/questions/28250680/how-do-i-access-previous-promise-results-in-a-then-chain) – Liam May 16 '23 at 10:44
  • [You should be using async await in modern JS](https://stackoverflow.com/a/28250697/542251) – Liam May 16 '23 at 10:45
  • 1
    Cypress does not use real promises, it uses a promise-like syntax so regular JS answers won't like ansyc / await won't cut it. – Baki May 16 '23 at 10:47
  • @Liam es6-promise tag is misleading. – Baki May 16 '23 at 10:48
  • [Well use this option then](https://stackoverflow.com/a/28250693/542251) – Liam May 16 '23 at 10:58
  • 2
    Just because there is a `.then()` method, does not mean it's a promise. You can add a `.then` property to any object, but you can't `await` it. – Muffy Cound May 17 '23 at 09:33

1 Answers1

6

Not really (any way to flatten). As you said, async/await does not work with Cypress commands since they aren't promises.

Well, you can put promises in place and await them, but it's clumsy and actually more code.

But cy.session() and cy.origin() are funky commands that only work because of the callback - or more accurately require the callback to function.

cy.session() only fires it's callback on the first call, there-after it caches the session data and returns them on the 2nd call instead of re-calling the callback.

cy.origin() uses the callback to make an isolated sandbox for code running against the other (specified) origin, and it's not even a callback in the Javascript sense, since it cannot use closure to variables in the outside scope.

Which links in to the fixture() part. Normally you can import or require a fixture

const user = require('cypress/fixtures/user.json')

but with cy.origin that doesn't help you since the fixture in imported in the outer scope and cannot be seen inside the cy.origin sandbox.


For a promise-creating plugin see cypress-promise, but it won't work with session and origin for reasons stated.

import promisify from 'cypress-promise'
 
it('should run tests with async/await', async () => {
  const foo = await promisify(cy.wrap('foo'))
  const bar = await promisify(cy.wrap('bar'))
 
  expect(foo).to.equal('foo')
  expect(bar).to.equal('bar')
})
Cara Gee
  • 129
  • 6
  • Thanks for the thorough I guess I can mark this as best answer since the answer is "you cannot flatten it" – Baki May 16 '23 at 13:35