admin管理员组

文章数量:1024131

I want to wait until the second of two elements to appear before performing an action on it. Currently, I have this:

    cy.get('[data-test="insert-item"]').click();
    cy.get('[data-test="textarea"]').eq(1).type('Hello').type('{enter}');

This currently fails. I'm assuming this is because Cypress is going to collect all the occurrences of textarea, then try to select the second one before it has actually rendered on the page (because of the async request that creates it). If I add cy.wait(2000); in between these two lines it passes.

Is there any way to do this without using cy.wait(2000), so that it specifically waits until the second item has appeared?

I want to wait until the second of two elements to appear before performing an action on it. Currently, I have this:

    cy.get('[data-test="insert-item"]').click();
    cy.get('[data-test="textarea"]').eq(1).type('Hello').type('{enter}');

This currently fails. I'm assuming this is because Cypress is going to collect all the occurrences of textarea, then try to select the second one before it has actually rendered on the page (because of the async request that creates it). If I add cy.wait(2000); in between these two lines it passes.

Is there any way to do this without using cy.wait(2000), so that it specifically waits until the second item has appeared?

Share Improve this question edited Nov 26, 2020 at 9:19 Anatoly 22.9k3 gold badges32 silver badges46 bronze badges asked Nov 21, 2020 at 12:59 JoeTideeJoeTidee 26.2k29 gold badges113 silver badges163 bronze badges 4
  • One way would be to wait till the XHR request associated is executed by using cy.route(), something like cy.server() cy.route('**/posts/**').as('getSomething') cy.wait('@getSomething'). You can find more info on the same here - docs.cypress.io/api/mands/route.html#Syntax – Alapan Das Commented Nov 21, 2020 at 15:24
  • Thanks for the suggestion, but this is just waiting for the XHR response, not the appearance of the second element. – JoeTidee Commented Nov 21, 2020 at 15:41
  • May be you can try either one of them for the appearance of the second element and see if it works - cy.get('[data-test="textarea"]').eq(1).should('be.visible') OR cy.get('[data-test="textarea"]').eq(1).should('exist'). – Alapan Das Commented Nov 21, 2020 at 15:46
  • 1 Thats not going to work either, as Cypress would have already assessed the number of textarea before the second one has appeared. Is there a way to wait a certain amount of time for the condition to be true? – JoeTidee Commented Nov 21, 2020 at 21:26
Add a ment  | 

1 Answer 1

Reset to default 6

You can move the eq() into the selector with :nth(1), which will cause the indexing to be part of the cy.get() retry mechanism

cy.get('[data-test="textarea"]:nth(1)')
  .type('Hello').type('{enter}')

Or you can assert the length of the elements selected before indexing the list.

cy.get('[data-test="textarea"]')
  .should('have.length', 2)
  .eq(1)
  .type('Hello').type('{enter}')

Demo

/// <reference types="@cypress/fiddle" />

const waitForAdd = {
  html: `
    <div id="parent">
      <textarea data-test="textarea">1</textarea>
      <button data-test="insert-item" onclick = "myFunction()"></button>
    </div>
    <script>
      const myFunction = () => {
        setTimeout(() => {
          const parent = document.querySelector('div#parent');
          let ta = document.createElement("textarea");
          ta.setAttribute('data-test', 'textarea');
          parent.appendChild(ta);
        }, 500)
      }
    </script>
  `,
  test: `
    cy.get('[data-test="insert-item"]').click();
    cy.get('[data-test="textarea"]:nth(1)')
      .type('Hello').type('{enter}')
    cy.get('[data-test="textarea"]:nth(1)')
      .invoke('val')
      .should('eq', 'Hello\\n')

    cy.get('[data-test="insert-item"]').click();
    cy.get('[data-test="textarea"]')
      .should('have.length', 3)
      .eq(2)
      .type('Hello again').type('{enter}')
    cy.get('[data-test="textarea"]')
      .eq(2)
      .invoke('val')
      .should('eq', 'Hello again\\n')
`
}
it('tests hello', () => {
  cy.runExample(waitForAdd)
})

I want to wait until the second of two elements to appear before performing an action on it. Currently, I have this:

    cy.get('[data-test="insert-item"]').click();
    cy.get('[data-test="textarea"]').eq(1).type('Hello').type('{enter}');

This currently fails. I'm assuming this is because Cypress is going to collect all the occurrences of textarea, then try to select the second one before it has actually rendered on the page (because of the async request that creates it). If I add cy.wait(2000); in between these two lines it passes.

Is there any way to do this without using cy.wait(2000), so that it specifically waits until the second item has appeared?

I want to wait until the second of two elements to appear before performing an action on it. Currently, I have this:

    cy.get('[data-test="insert-item"]').click();
    cy.get('[data-test="textarea"]').eq(1).type('Hello').type('{enter}');

This currently fails. I'm assuming this is because Cypress is going to collect all the occurrences of textarea, then try to select the second one before it has actually rendered on the page (because of the async request that creates it). If I add cy.wait(2000); in between these two lines it passes.

Is there any way to do this without using cy.wait(2000), so that it specifically waits until the second item has appeared?

Share Improve this question edited Nov 26, 2020 at 9:19 Anatoly 22.9k3 gold badges32 silver badges46 bronze badges asked Nov 21, 2020 at 12:59 JoeTideeJoeTidee 26.2k29 gold badges113 silver badges163 bronze badges 4
  • One way would be to wait till the XHR request associated is executed by using cy.route(), something like cy.server() cy.route('**/posts/**').as('getSomething') cy.wait('@getSomething'). You can find more info on the same here - docs.cypress.io/api/mands/route.html#Syntax – Alapan Das Commented Nov 21, 2020 at 15:24
  • Thanks for the suggestion, but this is just waiting for the XHR response, not the appearance of the second element. – JoeTidee Commented Nov 21, 2020 at 15:41
  • May be you can try either one of them for the appearance of the second element and see if it works - cy.get('[data-test="textarea"]').eq(1).should('be.visible') OR cy.get('[data-test="textarea"]').eq(1).should('exist'). – Alapan Das Commented Nov 21, 2020 at 15:46
  • 1 Thats not going to work either, as Cypress would have already assessed the number of textarea before the second one has appeared. Is there a way to wait a certain amount of time for the condition to be true? – JoeTidee Commented Nov 21, 2020 at 21:26
Add a ment  | 

1 Answer 1

Reset to default 6

You can move the eq() into the selector with :nth(1), which will cause the indexing to be part of the cy.get() retry mechanism

cy.get('[data-test="textarea"]:nth(1)')
  .type('Hello').type('{enter}')

Or you can assert the length of the elements selected before indexing the list.

cy.get('[data-test="textarea"]')
  .should('have.length', 2)
  .eq(1)
  .type('Hello').type('{enter}')

Demo

/// <reference types="@cypress/fiddle" />

const waitForAdd = {
  html: `
    <div id="parent">
      <textarea data-test="textarea">1</textarea>
      <button data-test="insert-item" onclick = "myFunction()"></button>
    </div>
    <script>
      const myFunction = () => {
        setTimeout(() => {
          const parent = document.querySelector('div#parent');
          let ta = document.createElement("textarea");
          ta.setAttribute('data-test', 'textarea');
          parent.appendChild(ta);
        }, 500)
      }
    </script>
  `,
  test: `
    cy.get('[data-test="insert-item"]').click();
    cy.get('[data-test="textarea"]:nth(1)')
      .type('Hello').type('{enter}')
    cy.get('[data-test="textarea"]:nth(1)')
      .invoke('val')
      .should('eq', 'Hello\\n')

    cy.get('[data-test="insert-item"]').click();
    cy.get('[data-test="textarea"]')
      .should('have.length', 3)
      .eq(2)
      .type('Hello again').type('{enter}')
    cy.get('[data-test="textarea"]')
      .eq(2)
      .invoke('val')
      .should('eq', 'Hello again\\n')
`
}
it('tests hello', () => {
  cy.runExample(waitForAdd)
})

本文标签: javascriptCypresshow to wait for second of two elements to appearStack Overflow