cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
47.51k stars 3.2k forks source link

use cy.* commands in intercept's callback #26667

Open raphaelbadia opened 1 year ago

raphaelbadia commented 1 year ago

What would you like?

I would like to be able to issue cypress commands in the intercept callback to "pause" the request while doing checks.

cy.intercept('POST', '/api/logos', (req) => {
        cy.contains('Loading...').should('be.visible'); // here
          req.continue((res) => {
            res.send({
              statusCode: 200,
              body: { data: `data:image/png;base64, ${fileContent}` },
            });
          });
      }).as('uploadLogo');

Why is this needed?

My use case is: verifying that a loading state appears when uploading a file.

Currently, it's so fast that my test is flaky because sometimes it "sees" the loading state and sometimes it skips it.

I end up doing res.setDelay(ARBITRARY_NUMBER); but that slows down my tests for no reason !

req.continue((res) => {
          res.setDelay(300);
          res.send({
            statusCode: 200,
            body: { data: `data:image/png;base64, ${fileContent}` },
          });
        });

Other

No response

nagash77 commented 1 year ago

Hi @raphaelbadia can you help me understand how adding a pause and adding a delay are different in your case? Both seem to be doing exactly what you are trying to replicate which is to introduce artificial slow downs so that the site can react to the test. How would pausing be different?

raphaelbadia commented 1 year ago

Hello @nagash77, when I add a delay, I indeed want to introduce an artificial slowdown so I can assert that a button has a loading class, for instance.

My issue is that setting an arbitrary doesn't feel right - here I wrote 300ms, but what if it only takes 50ms to check that the button has a loading class? My test wastes 250ms for nothing. What if the CI is a bit slow? My test fails.

If we could write cypress commands in the intercept callback, like this :

cy.intercept('POST', '/api/logos', (req) => {
    cy.get('#submit').should('have.class', 'loading'); // <------------- like that
    req.continue((res) => ............);
}).as('uploadLogo');

I'd expect the intercept command to run the cy.get('#submit').should('have.class', 'loading'); when the request fire, and then the send the response when the command has run successfully !

bahmutov commented 1 year ago

This is impossible because Cypress Cannot Add Out-Of-Band Commands. Luckily a workaround (or even 3 of them) is simple enough, as I show in my paid course lesson Bonus 97: Resolve the intercept promise