khmarbaise
khmarbaise

Reputation: 97537

Select elements in HTML via cypress.get()

I'm using cypress to write some tests against an html site..

The following selects me correctly a single tr elements from a table on my HTML site. The site contents looks like this:

<tr data-recordid="theId">
  <td...><div ..>Text 1</div></td>
  <td...><div ..>Text 2</div></td>
  <td...><div ..>Text 3</div></td>
</tr>

The following test script snippet selects me correctly the single <tr..> part.

cy.get('tr[data-recordid="theId"]').contains('Text')

Now I want to select the text within the <div>..</div> tags..The first thing I have tried to chain a single call for the first <div>..</div> tag like this:

cy.get('tr[data-recordid="theId"]').get('div').contains('Text')

which does not work as I expected. The get() calls a chained jQuery calls (Based on the Docs of cypress). So it looks like I misunderstand how things work in JQuery.

What I'm expecting is how I can check all div elements like this (Not working):

cy.get('tr[data-recordid="theId"]')..SomeHowMagic
  .get('td[alt="xyz"]".get('div').contains('Text 1')
  .get('td...').get('div').contains('Text 2')
  .get('td...').get('div').contains('Text 3')

Any idea how to get forward a step? Missing any information just make a comment.

Upvotes: 2

Views: 10961

Answers (2)

Brian Mann
Brian Mann

Reputation: 211

Let's clarify a few things:

1) If you are just wanting to ASSERT that the div's contain the given text then this is the best possible and most precise way to do this:

cy.get('tr[data-recordid="theId"]').should(($tr) => {
  const $divs = $tr.find('div') // find all the divs

  expect($divs.eq(0)).to.contain('Text 1')
  expect($divs.eq(1)).to.contain('Text 2')
  expect($divs.eq(2)).to.contain('Text 2')
})

I can't tell if things need to be this specific. If you only want to ensure that the $tr contains text you could simplify it down to be:

cy.get('tr[data-recordid="theId"]').should(($tr) => {
  expect($tr).to.contain('Text 1')
  expect($tr).to.contain('Text 2')
  expect($tr).to.contain('Text 2')
})

Why do it this way?

  • Using a .should() function will not change the subject. Your $tr will continue to be the subject going forward.
  • Cypress will wait until all of the assertions in the .should() callback pass, and continually retry until they do. That guarantees you the state of multiple elements is correct before proceeding.

2) However if you just care that Cypress finds the text and you don't mind the subject being changed you could do this:

cy.get('tr[data-recordid="theId"]').within(() => {
  cy.contains('Text 1') // changes the subject to the <div>
  cy.contains('Text 2') // changes the subject to the <div>
  cy.contains('Text 3') // changes the subject to the <div>
})

This is different than the first example because instead of an explicit assertion you are simply changing the subject to whatever element the text is found in. Cypress's default assertion on cy.contains() is to retry so ultimately the behavior is the same, except you are additionally changing the subject.

If even this is too complicated you could also just do this:

cy.get('tr[data-recordid="theId"] div').contains('Text 1')
cy.get('tr[data-recordid="theId"] div').contains('Text 2')
cy.get('tr[data-recordid="theId"] div').contains('Text 3')

Your original question was also using chained cy.get() which does not drill into subjects. For that to happen use .find()

cy.get('a').get('span') // each cy.get() queries from the root
cy.get('a').find('span') // the .find() queries from the <a>

One final note: you suggested solution does not work. cy.get() does not accept a callback function, and if you look at your Command Log you will not see those 3 cy.contains from ever being invoked. In other words, they are not running. That's why its passing.

Upvotes: 10

khmarbaise
khmarbaise

Reputation: 97537

So after more experimenting I found a solution:

cy.get('tr[data-recordid="TheId"]>td> div', function() {
  cy.contains('Text 1').end()
  cy.contains('Text 2').end()
  cy.contains('Text 3').end()
})

If someone else has a better solution please post it here.

Upvotes: 0

Related Questions