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?
-
One way would be to wait till the XHR request associated is executed by using
cy.route()
, something likecy.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')
ORcy.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
1 Answer
Reset to default 6You 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)
})