KayakinKoder
KayakinKoder

Reputation: 3451

How to wait for an element to be visible?

Is it possible to wait until an element is visible?

cy.get('[data-test=submitIsVisible]').should('be.visible');

This should error if the submit button is not visible. I want to wait until the submit button is visible.

The primary use case is visual testing, i.e. taking a screenshot of the page.

Upvotes: 53

Views: 178279

Answers (4)

Manuel Abascal
Manuel Abascal

Reputation: 6312

You can wait for the element to be visible like so:

// Give this element 10 seconds to appear
cy.get('[data-test=submitIsVisible]', { timeout: 10000 }).should('be.visible');

According to Cypress's Documentation:

DOM based commands will automatically retry and wait for their corresponding elements to exist before failing.

Cypress offers you many robust ways to query the DOM, all wrapped with retry-and-timeout logic.

Another way to wait for an element’s presence in the DOM is through timeouts. Cypress commands have a default timeout of 4 seconds, however, most Cypress commands have customizable timeout options. Timeouts can be configured globally or on a per-command basis. Check the customizable timeout options list here.

In some cases, your DOM element will not be actionable. Cypress gives you a powerful {force:true} option you can pass to most action commands.

Caveat:

As Anthony Cregan pointed out, the .should('be.visible') assertion checks whether an element is visible on the page, not necessarily in the viewport. This means that this assertion will return true even if the element is not within the visible area of the screen when the test is run.

Further recommended readings:

Upvotes: 114

GjoDim
GjoDim

Reputation: 17

Try element.should('have.length.greaterThan', 0).and('be.visible')

Upvotes: -2

Lola Ichingbola
Lola Ichingbola

Reputation: 4966

Updated for Cypress v12

If you want to see exactly how Cypress waits for something to become visible, follow this example.

Using this code, you can check out how the delay and the timeout can affect the passing or failing of the .should('be.visible') assertion.

Steps

  1. Add a simple page to a VSCode project containing Cypress v12.1.0 Call it index.html

    <html>
      <body>
        <h2>API fetched data</h2>
        <span>will become visible here</span>
      </body>
      <script>
        fetch('https://jsonplaceholder.typicode.com/posts/1')
          .then(response => response.json())
          .then(data => document.querySelector('span').innerText = data.title )
      </script>
    </html>
    
  2. Right-click index.html and choose "Open with Live Server" to activate the page.

  3. Add this test to see how Cypress waits for the API data

    describe('test the waiting of API data', () => {
    
      const timings = [
        { delay: 0, timeout: 4000 },     // default, passes
        { delay: 2000, timeout: 4000 },  // passes 
        { delay: 4000, timeout: 4000 },  // flaky
        { delay: 5000, timeout: 4000 },  // fails
        { delay: 5000, timeout: 10000 },  // passes
      ]
    
      timings.forEach(timing => {
    
        const {delay, timeout} = timing;
    
        it(`delayed API by ${delay} ms, command timout is ${timeout} ms`, () => {
    
          cy.intercept('https://jsonplaceholder.typicode.com/posts/1', (req) => {
            req.continue((res) => res.setDelay(delay))
          })
    
          cy.visit('http://127.0.0.1:5500/index.html')
    
          cy.contains('sunt aut facere', {timeout})
            .should('be.visible')
        })
      })
    })
    

Result

enter image description here

This shows that the longer the delay in receiving the data, the bigger the timeout needed on the visibility assertion.

Upvotes: 113

Sudheer Singh
Sudheer Singh

Reputation: 654

you can also do it by passing below script into your cypress.config.js files

e2e: {
    defaultCommandTimeout: 25000,
}

pass defaultCommandTimeout as per your requirement.

Upvotes: 3

Related Questions