admin管理员组

文章数量:1325135

I'm trying to iterate through table rows and get each row which includes a specific value, but it doesn't work for me. I'm using .each() to iterate the rows and .within() on each $el, inside that, I use cy.get('td').eq(1).contains('hello') but I the get assertion error:

Timed out retrying: Expected to find content: 'hello' within the element: <td> but never did.

when I console.log cy.get('td').eq(1) it yields the desired cell in each row and the test passes, so I don't understand why chaining .contains() doesn't work...

it('get element in table', () => {
  cy.visit('http://localhost:3000/');
  cy.get('tbody tr').each(($el) => {
    cy.wrap($el).within(() => {
      cy.get('td').eq(1).contains('hello') // contains() doesn't work
    })
  })
});
<table>
  <thead>
    <tr>
      <th>Month</th>
      <th>Savings</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>hello</td>
      <td>$80</td>
    </tr>
     <tr>
      <td>$10</td>
      <td>hello</td>
    </tr>
  </tbody>
</table>

I'm trying to iterate through table rows and get each row which includes a specific value, but it doesn't work for me. I'm using .each() to iterate the rows and .within() on each $el, inside that, I use cy.get('td').eq(1).contains('hello') but I the get assertion error:

Timed out retrying: Expected to find content: 'hello' within the element: <td> but never did.

when I console.log cy.get('td').eq(1) it yields the desired cell in each row and the test passes, so I don't understand why chaining .contains() doesn't work...

it('get element in table', () => {
  cy.visit('http://localhost:3000/');
  cy.get('tbody tr').each(($el) => {
    cy.wrap($el).within(() => {
      cy.get('td').eq(1).contains('hello') // contains() doesn't work
    })
  })
});
<table>
  <thead>
    <tr>
      <th>Month</th>
      <th>Savings</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>January</td>
      <td>$100</td>
    </tr>
    <tr>
      <td>February</td>
      <td>hello</td>
      <td>$80</td>
    </tr>
     <tr>
      <td>$10</td>
      <td>hello</td>
    </tr>
  </tbody>
</table>

Share Improve this question asked Apr 22, 2020 at 10:37 juvejuve 631 gold badge1 silver badge3 bronze badges 1
  • 1 It's not .contains() that fails, the first row does not contain 'hello' in the second cell - so the test fails and never checks subsequent rows. – user8745435 Commented Apr 22, 2020 at 20:43
Add a ment  | 

3 Answers 3

Reset to default 3

should('have.text', text) should work

cy.get('td').eq(1).should('have.text', 'hello')

If there's whitespace around text, use contain.text

cy.get('td').eq(1).should('contain.text', 'hello')

This works for me:

      cy.get("table")
        .find("tbody")
        //Iterate through the rows
        .each(($row, $index) => {
          cy.wrap($row).within(() => {
            cy.get("td")
              .eq(1) // Second column
              .invoke("text")
              .then((text) => {
                if (text.includes("the-text-i-want")) {
                  cy.get("td")
                    .eq(1)
                    .contains("the-text-i-want");
                } else {
                  cy.log("Skipping");
                }
              });
          });
        });

The simple answer is: don't :)

To be more specific use html attribute selection instead. The convention is to have an attribute named data-cy. Furthermore, I discovered it convenient to have a data-cy-identifier for when selecting specific rows. Since I'm not sure what you're trying with your code, I'll use a similar example that can hopefully get you going:

<table data-cy="expences">
    <tr>
        <td data-cy="month">January</td>
        <td data-cy="price">$100</td>
    </tr>

    <tr data-cy="discounted">
        <td data-cy="month">Feburary</td>
        <td data-cy="price">$80</td>
    </tr>

    <tr data-cy="discounted">
        <td data-cy="month">March</td>
        <td data-cy="price">$10</td>
    </tr>
</table>

You can of course do all sorts of binations of this, but now you can do more specific and useful selections, such as:

cy.get('[data-cy="expenses"]').find('[data-cy="discounted"]').find('[data-cy="price"]').should(...)

And similar. This is flexible, because it reflects the structure of your data, and not the presentation, so you can change this to a list or whatever later. It avoids selecting of volatile things, so it's also more robust. It also uses a hierarchy rather than overly specific selectors.

The idea of adding things like data-cy-identifier allows you to do selections by ID (you can propagate it using javascript, angular, vue or whatever you use) and then checking things like the contents of a row with logically related items.

Hope it can get you going. Also I can remend reading: https://docs.cypress.io/guides/references/best-practices.html

本文标签: javascriptCypress iterate table rows get specific element in cellsStack Overflow