Cypress | check that search keywords match the value of any td of the displayed trs

Viewed 616

I'm testing a search functionality that filters the entered characters against users' Firstname, Lastname, role, or email.

I have a table with multiple tr and each tr has multiple td.

I want to assert that the returned rows contain a value in any td that matches the entered keyword.

I created the below helper function but cy.get('td').contains(searchKeyword); causes the browser to hang up. any idea what could be the solution here.

 assertCorrectFilterResults(searchKeyword: string) {
            this.elements.tableBody().find("tr").then(rows => {
                rows.toArray().forEach(row => {
                    cy.get('td').contains(searchKeyword);
                })
            });
        };

My helper was inspired from the solution mentioned here How to get the total number of Rows in a table | Cypress

Table Structure enter image description here

3 Answers

In case if you directly want to look into the td elements you can directly loop over them.

For exact Match with the searchKeyword

cy.get('tbody.MuiTableBody-root tr td').each(($ele) => {
  if($ele.text().trim() == searchKeyword){
    expect($ele.text().trim()).to.equal(searchKeyword)  //Assertion for exact text
  }
})

For partial match with the searchKeyword

cy.get('tbody.MuiTableBody-root tr td').each(($ele) => {
  if($ele.text().trim().includes(searchKeyword)){
    expect($ele.text().trim()).to.include(searchKeyword)  //Assertion for partial text
  }
})

Try wrapping each row.

This will test that all the rows contain the searchword.

assertCorrectFilterResults(searchKeyword: string) {
  cy.get('tbody').find("tr").then(rows => {
    rows.toArray().forEach(row => {

      cy.wrap(row).contains(searchKeyword);  // test that one of child <td> has searchKeyword 

    })
  });
};

You can assert that a parent element "contains" text that is inside a child element, so

<tr>
  <td></td>
  <td></td>
  <td>Find me!</td>
</tr>

asserting on <tr> with .contains(...) will check all the <td>.


Additional Note

When you do cy.get('td') inside the forEach, Cypress actually searches from the cy.root() element (by default it's the <body> element).

So another way to do it is to change the root element using .within()

assertCorrectFilterResults(searchKeyword: string) {
  cy.get('tbody').find("tr").then(rows => {
    rows.toArray().forEach(row => {

      cy.wrap(row).within(() => {
        cy.get('td').contains(searchKeyword);  // now get works only in this row
      })

    })
  });
};

Triggering a button in another <td> of the row:

cy.get('tbody.MuiTableBody-root tr')  // note - end this selector at tr
.each(($tr, rowIndex) => {            // row index is passed as 2nd param

  if ($tr.text().includes(searchKeyword)) {

    cy.wrap($tr).within(() => {
      cy.get('td').eq(3)  // for example 4th col has button
        .find('button')   
        .click()
    })
  }
})
Related