Cypress: How to ensure all react components are loaded before cy.screenshot()

Created on 3 Oct 2019  路  4Comments  路  Source: cypress-io/cypress

Current behavior:

When trying to get screenshots of pages, even after waiting for all xhr requests and checking elements exist, cy.screenshot() will capture the page in an intermediate loading state where some things haven't rendered yet.

I do not want to use cy.wait(1000) as it is hacky and has caused my problems further down the test chain, such as random timeouts on screenshots.

Desired behavior:

Is there any way to check a component has rendered and is visible before taking the screenshot?

Steps to reproduce: (app code and test code)

Here is an example where it works when I add a wait but not without:

cy.fixture(QA_FIXTURE).as('fixture');
  cy.server();
  cy.route('POST', '/v1.0/blobs/sign-url/').as('signUrl');

  cy.selectLatestActivity('/activity/');

  cy.get('@fixture').then(fixture => {
    if (fixture.BUILD_PREFIX === 'blah') {
      cy.log(fixture.BUILD_PREFIX);
      cy.wait('@signUrl').then(xhrs => {
        cy.wrap(xhrs.status).should('eq', 200);
      });
    }
  });
  cy.wait(2000);
  cy.screenshot();
  cy.get('[data-cy="close_btn"]').click();

the signurl fucntion is the last request to occur, and even if use something like:

cy.get('[data-cy="close_btn"]').then(() => {cy.screenshot();});

To ensure the button is there after the request, it will still be a race to whether the component has rendered and the screenshot saved.

Versions

3.4.1

question

Most helpful comment

Did you ever try something like

cy.get('some-lazy-element').should('be.visible');
cy.screenshot();

or

cy.get('some-lazy-element').contains('stuff from xhr response that should be rendered')
cy.screenshot();

?
cy.get() alone doesn't care for the visibility of an element.

All 4 comments

Did you ever try something like

cy.get('some-lazy-element').should('be.visible');
cy.screenshot();

or

cy.get('some-lazy-element').contains('stuff from xhr response that should be rendered')
cy.screenshot();

?
cy.get() alone doesn't care for the visibility of an element.

@lleewwiiss We've struggled with this issue ourselves in our tests for our Dashboard. We discussed possibly exposing an event from within our application - so firing an event in the application when it is ready for screenshot, then listening for that to know when to screenshot.

But we are primarily waiting for XHR requests to finish and for elements to exist before screenshotting now. @tgriesser did y'all implement something specific for this in the end?

@webnexusmobile's solution is similar to what I've had to implement in some of the slower areas of our application. We'll do things like:

cy.get('element we know loads "late"').should('not.be.empty'); or
cy.get('element that will get focus when loading is done').should('have.focus')

In the rare case where that's still not _quite_ enough time (for transitions to finish firing or something like that) you could always increase the timeout of those checks instead of using .wait(). That way you can increase how long Cypress will wait for the thing to appear or exist without forcing it to wait the full amount of time.

cy.get('#dialogClose').should('have.focus', { timeout: 5000 });

Issues in our GitHub repo are reserved for potential bugs or feature requests. This issue will be closed since it appears to be neither a bug nor a feature request.

We recommend questions relating to how to use Cypress be asked in our community chat. Also try searching our existing GitHub issues, reading through our documentation, or searching Stack Overflow for relevant answers.

Was this page helpful?
0 / 5 - 0 ratings