Cypress: Wait for unpredictable component to render from an exclusive set?

谁说我不能喝 提交于 2020-12-15 05:41:47

问题


For thorough testing, my service (UI+Backend) migrates through multiple deployment environments: ex DEV, STAGE, DEMO, and PROD. As this service migrates these test environments, its UI waits for asynchronous updates from its Backend, which as a test stressor it can be unpredictably slow; thereby, speeding it up is not an option nor is mocking the response.

UI test involves waiting for an asynchronous update response to determine which React components will exclusively be presented. These React components will be section/div with unpredictable content/text, so Cypress contains is not an option.

The typical solution for handling slow asynchronous updates is using fixed delays with Cypress wait: a bunch of milliseconds, tenths of a second, or even seconds. However, the longer are fixed delays leads your test to be more brittle.

Here is an example of my brittle Cypress test code:

cy.get('div.main')
  .then( ($divMain) => {
    cy.wait(5000) // wait 5 seconds

    const boolStateA = $divMain.find('section.A').length > 0;
    const boolStateB = $divMain.find('section.B').length > 0;

    if (boolStateA( {
      // Do ...
    } else if ( boolStateB ) {
      // Do something else ...
    }
  })

However.. after waiting for 5 seconds, it is not absolutely certain, that either one of the components actually rendered. If neither or both rendered, then that is an unexpected state.

So how can I wait for either of these components to render using neither cy.wait() nor cy.contains?

Thank you


回答1:


The recommendation from cypress is to make your testing deterministic. Meaning, figure out how to ensure your product is always in a known state when your tests run. This is typically done with mocks, routes or massaging the backend to provide (or perhaps get) a pre-determined state.

An inline timeout could be a bit better than cy.wait() but that doesn't resolve your unknown state problem.

cy.get('.mobile-nav', { timeout: 10000 })
  .should('be.visible')
  .and('contain', 'Home')

Alternatively, you could update your app to include a hidden done state that your tests wait for.

Example:

<div data-cy="SectionLoaded">SectionA</div> 

In this manner, the test only needs to wait for one thing and it's always going to be there. Your test can have a condition that gets the .text() of this element and then acts on it. That might look something like this provided you wanted to click on one of them.

cy.get('[data-cy=SectionLoaded]', { timeout: 10000 }).then(($loadedSection) => {
  cy.get(`[data-cy=${$loadedSection.text()}]`).click() 

More on this from cypress.io including additional best practices and workarounds:

  • https://docs.cypress.io/guides/core-concepts/conditional-testing.html#Element-existence
  • https://docs.cypress.io/guides/core-concepts/conditional-testing.html#Dynamic-text
  • https://docs.cypress.io/guides/core-concepts/retry-ability.html#Increase-time-to-retry



回答2:


@GrayDwarf: Thank you for your response

I did use Cypress contains

    cy.get('div[data-cy="sales_listing_section"]')
        .contains(
            'h1.header-title[data-cy="sale_items_header"]',
            'Items for Sale',
            {timeout: 10000}
        )
        .then(() => {

As well as module npm cypress-wait-until

    cy.get('div.main-content')
        .then(($sectionBody) => {

            // @ts-ignore
            cy.waitUntil(() => {
                return ($sectionBody.find('div[data-cy="sales_listing_section"]').length > 0)
            }, {
                errorMsg: `ERROR: Sales section has not loaded.`,
                timeout: 10000, // waits up to 10000 ms, default to 5000
                interval: 500, // performs the check every 500 ms, default to 200
                verbose: true,
                customCheckMessage: `CHECK: If Sales section has loaded`
            })
                .then(() => {
                    cy.log('Sales section', 'Loading finished');
                })
        })


来源:https://stackoverflow.com/questions/64421563/cypress-wait-for-unpredictable-component-to-render-from-an-exclusive-set

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!