Reputation: 389
I have a table that has a status column, I want to check the status of the fist row (which is at last column) . the status goes from "in progress" to completed after some amount of time (max 5 min);
here is the DOM:
<tbody>
<tr>
<td>...</td>
<td> ... </td>
<td> in progress / complete </td> //status => want to check this cell.
</tr>
<tr>
<td>...</td>
<td> ... </td>
<td> ... </td> //status
</tr>
<tr>
<td>...</td>
<td> ... </td>
<td> ... </td> //status
</tr>
</tbody>
how to reach to the cell I want and use polling mechanism to see if the status completed?
thank you for your help
Upvotes: 1
Views: 3160
Reputation: 2555
It's unclear how the cell in your table is updated. Is there a request sent in intervals or only when first loading the page?
If its former, then it would be simple as such
// assuming only table on page and last cell of first row is always the cell you want
cy.get('tbody')
.should('be.visible') // check table is fully loading in case
.find('tr')
.first() // same as .eq(0), just more readable
.find('td')
.last() // same as .eq(3), jut more readable
.should('be.visible')
.and('match.text', /complete/i) // can update command timeout
If you are dealing with the latter, then you'll have to use recursion to check after each page reload. Recommend using cypress-recurse
import { recurse } from 'cypress-recurse'
recurse ({
() => {
return cy.get('tbody tr:nth-child(0) td:nth-child(3)') // eq to above
.should('be.visible')
},
($el) => expect($el).to.have.text('complete'),
{
// can alter configurations
timeout: 30_000,
delay: 3_000,
post: { cy.reload() }
}
)
Upvotes: 0
Reputation: 4405
I would first check the "in progress" status to ensure the sequence is correct.
cy.contains('tbody tr:eq(0)', 'in progress')
cy.contains('tbody tr:eq(0)', 'complete', {timeout:300000})
Upvotes: 2
Reputation: 10550
Cypress has built-in polling, no need to code a special routine.
This is all you need!
cy.contains('tbody tr:nth-of-type(1) td:nth-of-type(3)', 'complete', {timeout:300000})
No need for .find()
or .within()
, the selector 'tbody tr:nth-of-type(1) td:nth-of-type(3)'
takes care of searching the table hierarchy.
The cy.contains()
command asserts that the text "complete"
should be in that cell, and the timeout automatically polls for 5 minutes.
It will pass earlier if the status changes earlier.
Note using .within()
can give you "detached from DOM" error if the whole row is replaced upon status change.
Upvotes: 1
Reputation: 18626
You can also use within
to go inside the first tr
and wait for the desired amount of time for the text complete
to appear. Something like this:
For exact text match:
cy.get('tbody')
.find('tr')
.eq(0)
.within(() => {
//eq(0) gets the first tr
cy.get('td', {timeout: 300000}).eq(2).should('have.text', 'complete') //Exact text match
})
For Partial text match:
cy.get('tbody')
.find('tr')
.eq(0)
.within(() => {
//eq(0) gets the first tr
cy.get('td', {timeout: 300000}).eq(2).should('contain.text', 'complete') //partial text match
})
Upvotes: 1
Reputation: 32044
The pattern for selecting row and column in Cypress would be
cy.get('tbody tr').eq(0) // first row
.find('td').eq(2) // third col
.should('contain', 'complete') // criteria to check
This waits for the defaultCommandTimeout
setting which is 4000 ms. To extend to 5 minutes add a 300000 timeout.
cy.get('tbody tr').eq(0)
.find('td').eq(2, {timeout:300000})
.should('contain', 'complete') // on fail retry above up to 5 minutes
But you might get errors with this depending on what changes in the DOM after status is updated. If the row or the table are refreshed with a new copy, you might need to combine the steps into one selector.
cy.get('tbody tr:nth-child(1) td:nth-child(3)', {timeout:300000})
.should('contain', 'complete')
It's not always clear which steps in a command chain will be repeated when .should()
fails.
Upvotes: 3