https://cypress.io logo
Setup complex API data in before without promise h...
# i-need-help
b
Cypress 12.5.0 Our server may take a while for certain API calls. So we got flakiness often between tests as some processes hadn't completed. I tried out
cypress-promise
to allow for use of
async
await
actions to avoid promise hell. It works locally but fails in
beforeAll / before
in the pipeline How can I avoid promise hell? There are more complex calls that depend on the result of previous calls for the setup between tests.
g
Give me a complete repo with async hell and I guarantee I will show a solution where you will be like "wow, this is simple and elegant". Meanwhile, here is a bunch of examples of using cy.then with async functions https://glebbahmutov.com/cypress-examples/commands/connectors.html#then
b
Promise hell. Async is heaven. There are too many complex interactions building out the db with using .then. Is there a way to get cypress-promise to work in the
before
block in Electron / pipelines using headless Cypress?
So using this kind of suggestion works in Chrome but not Electron
Copy code
before(() => {
        cy.wrap(1000).then(async () => {
            await setupData();
        });
    });
g
I literally cannot help you if you don't provide details. What is your setupData?
b
The data here isn't literally the issue. It's specifically the lack of ability to use async functions in
before
and
beforeEach
. And this is to avoid metaphorical promise hell. The
setupData
function is just an async function. Each file has a series of steps to clean up the environment if data exists, and set up layers of more data. An allegorical example: We will quickly get into promise hell for something like
And now with what ideally should work with
async
await
^^^ and this sort of
asyncExampleSetup
fn fails in headless Cypress .. The
cy.callAPI
would be wrapped in `cypress-promise`'s
promisify
fn
g
Are you sure about this? I don't want to appear rude, but if
cy.callAPI
is your command, and it is something that makes the call, like using
cy.request
, then you are overcomplicating everything (in the first variant) 🙂
b
Yes cy.call has
cy.request
there (one of the top screenshots)
suggestions of simplifying that would work?
g
will do
l
Another option would be to create a
task
for your setup, then just run your API setup in Node.
b
Yeah was thinking that, but for 70+ different test files with different data setup… 😦
p
Maybe a recursion on the request is a simple and effective way, here's an example:
Copy code
js
let counter = 0;
let waitTime = 500;
const someFunction = () => {
cy.request(requestName).then((response) => {
        if (response.status !== 200 && counter < 10) {
          cy.wait(waitTime);
          someFunction();
          waitTime = waitTime + 500;
          counter++;
        } else {
          cy.request(anotherRequest).then((response) => {
              expect(response.status).to.eq(200);
          });
        }
      });
    };
It will wait some time, try the request again and see if the response body or status meets the expectations and then do what you want with the body before moving forward. In a complex microservice infrastructures It can help a lot
b
Thanks, but the amount of calls I have to do for complex data setup (with a rather dumb backend) is insane.
Async await
just works, and should work with Cypress
g
https://glebbahmutov.com/blog/setup-cypress-data/ To show anything else, I would need to use your public repo example