Home > Software design >  How can I select specific sibling of an element in table?
How can I select specific sibling of an element in table?

Time:09-16

I am pointing to the middle table cell and I can able to get text of the next cell using the next() method but when I tried to use parent() I am getting full row text which is three cells. Below is the HTML code. Kindly help.

cy.get('[name="courses"] > tbody >tr >td:nth-child(2)').each((e1, index) => {
  const course = e1.text()
  
  if (course.includes('Python')) {
    cy.get('[name="courses"] > tbody >tr >td:nth-child(2)').eq(index).parent()
        .then((price) => {
      const courseprice = price.text()
      // expect(courseprice).to.be.equal('25')
      cy.log(courseprice)
    })
  }
})

enter image description here

enter image description here

enter image description here

CodePudding user response:

The reason the text is the entire text is that it combines the text of all child elements. To avoid this, we can take a few different routes:

First solution: we can just check if the parent contains the value:

cy.get('[name="courses"] > tbody >tr >td:nth-child(2)')
  .eq(index)
  .parent()
  .should('contain.text', 25);

Second solution: grab the third row TD directly

cy.get('[name="courses"] > tbody >tr >td:nth-child(3)') // nth-child is index-1
  .should('have.text', 25);

CodePudding user response:

After using parent, you can use within to go inside the parent tr and access each td elements like this:

cy.get('[name="courses"] > tbody >tr >td:nth-child(2)')
  .eq(index)
  .within(() => {
    cy.get('td').eq(0).should('have.text', 'Rahul Shetty')
    cy.get('td')
      .eq(1)
      .should(
        'have.text',
        'Master Selenium Automation is simple Python Language'
      )
    cy.get('td').eq(2).should('have.text', '25')
  })

CodePudding user response:

It would be easier to iterate over the rows and check the 2nd instead of iterating over the 2nd and then travers up and down the DOM to get the price and then use cypress-if

cy.get('[name="courses"] > tbody >tr')
  .should("have.length.greaterThan", 0)
  .each($row =>{
    cy.wrap($row)
      .contains("td", "Python", { timeout: 0 })
      .if("visible")
      .then(() => {
        cy.log("Price of Python course");
        cy.wrap($row).contains("td", "25").should("be.visible");
      })
      .else()
      .log("Instructor does NOT sell Python");
   }
})

Here is a minimal reproducible example.

CodePudding user response:

Another option, and my preferred way is to use find I would also recommend not using then or or other nested function like each if you don't need it. And even though you can use jquery selectors like nth-child(), using the eq() makes it a bit more readable (IMHO). Also nth-child index is not 0-based but 1-based, so nth-child(2) returns the 2nd column, not the 3rd.

for example, this will give you the 8th row and 3rd column

cy.get('[name="courses"] > tbody >tr')
  .eq(7)
  .find('td')
  .eq(2)

if I repeat anything more than twice in a test, I tend to write helper functions in the spec.

// define somewhere at the beginning of the file (or add to commands.js)
const getTableCell(r,c) => cy.get('[name="courses"] > tbody >tr')
  .eq(r)
  .find('td')
  .eq(c)

describe('           
  • Related