2

My test results in adding a row to the table. In afterEach hook I wanted to add a method to delete the newest row after the test ran so I wrote this piece of code:

deleteTheNewestRequest() {
    cy.get('table#return-request-list').find('tr').eq(1).then( firstRow => {
        cy.wrap(firstRow).find('td').eq(0).invoke('text').as('rowId')
        cy.wrap(firstRow).find('a[title="Delete"]').click()
        cy.get('button.btn-delete-return-request').click()
        cy.wrap(firstRow).find('td').first().should('not.have.text', this.rowId)
    })
}

With 'then' I'm saving a table element to later use to find and operate on the elements inside it. I wanted to first save the value of the newest row in the table that was added after the test ran successfully, then delete and as the last step make sure that the row with the ID that was deleted is actually gone from the table. The problem is that cypress test runner assertions marks it green because it sees that value of is not equal to 'undefined' and not, let's say 3794.

MaciejGy
  • 31
  • 2
  • For debugging Instead of this `cy.wrap(firstRow).find('td').eq(0).invoke('text').as('rowId')` can you write `cy.wrap(firstRow).find('td').eq(0).invoke('text').then((rowId) => {cy.log(rowId)})` and tell me what is getting printed. – Alapan Das Feb 10 '22 at 12:40
  • @AlapanDas Logging this value return actual value of the row, which is a four digit number – MaciejGy Feb 10 '22 at 13:25

4 Answers4

2

This looks like the culprit cy.get('table#return-request-list').find('tr').eq(1). You get the row you want to delete, you delete it, then you wrapping the delete row element even though it does not exist. So it will return undefined. You should instead get all rows initially.

function deleteTheNewestRequest(){
    // get all rows in table
    cy.get('table#return-request-list').find('tr').then( rows => {
        // get last row and store rowId
        cy.wrap(rows).last().find('td').first().invoke('text').as('deletedRowId')
        cy.wrap(rows).last().find('a[title="Delete"]').click()
        cy.get('button.btn-delete-return-request').click()
        // check new last row does not have same rowId
        cy.wrap(rows).last().find('td').first().should('not.have.text', this.rowId)
    })
}
jjhelguero
  • 2,281
  • 5
  • 13
  • Looks good, but you are checking the last row - shouldn't that be the first row since that one was deleted. In fact, for a thorough test it should check ***none*** of the rows have rowId. – Dizzy Al Feb 12 '22 at 09:22
  • I must have misread. I was assuming the last row was the row they were wanting to delete and then check the newly last row to not match the deleted rowId. – jjhelguero Feb 12 '22 at 15:07
  • For me the clue was the variable `firstRow`. – Dizzy Al Feb 12 '22 at 19:30
2

Breaking up the steps might work better.

deleteTheNewestRequest() {
  cy.get('table#return-request-list')
    .find('tr').eq(1)
    .as('firstRow')               // save row ref for delete 
    .find('td').eq(0)
    .invoke('text').as('rowId')   // save rowId text for check

  cy.get('@firstRow').find('a[title="Delete"]').click()
  cy.get('button.btn-delete-return-request').click()

  cy.get('@rowId').then(rowId => {
    cy.contains('tr', rowId).should('not.exist')  // "standard" non-existence check
  })
}

Ref Test if element does not exist

I would check if .find('tr').eq(1) is the first row, perhaps it should be .find('tr').eq(0)?

Fody
  • 23,754
  • 3
  • 20
  • 37
1

When you delete the row, it is removed from the DOM but the test still has a pointer to it (the firstRow variable), preventing the garbage collector from removing it from memory.

So cy.wrap(firstRow) is still pointing to the complete row, and it still has the same rowId.

You want to test what the user sees, that firstRow is no longer in the DOM.

//cy.wrap(firstRow).find('td').first().should('not.have.text', this.rowId)  // not this
cy.wrap(firstRow).should(firstRow => {  
  expect(Cypress.dom.isAttached(firstRow)).to.eq(false)
})

Or test that no rows in the DOM have the rowId

cy.get('@rowId').then(rowId => {
  cy.contains('tr', rowId).should('not.exist')  
})
Seeker
  • 356
  • 1
  • 11
0

You can do something like this:

deleteTheNewestRequest() {
    cy.get('table#return-request-list').find('tr').eq(1).then(firstRow => {
        cy.wrap(firstRow).find('td').eq(0).invoke('text').as('rowId')
        cy.wrap(firstRow).find('a[title="Delete"]').click()
        cy.get('button.btn-delete-return-request').click()
        cy.get('@rowId').then((rowId) => {
            cy.wrap(firstRow).find('td').first().should('not.have.text', rowId)
        })
    })
}
Alapan Das
  • 17,144
  • 3
  • 29
  • 52
  • I tried this and know Cypress sees this ID value that it takes right after the test, but it seems like it would check for it too early since assertion fails. When I check the same page on my browser I see that it was deleted but when the test is ran it fails because this row is still there. Regarding cy.get('@rowId'), I see that it would equal cy.get(1234) since rowId keeps a number and I wonder how it does not fail since get should not accept text values of the element. – MaciejGy Feb 10 '22 at 16:04