In Cypress how to count a selection of items and get the length?
Solution 1
Found a solution, This works to check a count of items:
cy.get('.datatable').find('tr').should('have.length', 4)
This does not work with the Cypress.$()
method of notation.
Reference: https://docs.cypress.io/guides/references/assertions.html#Length
Solution 2
You can also get the length of a selection of items through its property, for example:
cy.get('.datatable').find('tr').its('length').should('eq', 4)
cy.get('.datatable').find('tr').its('length').should('be.gte', 4)
In addition to should('have.length', 4)
I tested with Cypress version 3.1.0 and 3.2.0.
Solution 3
if you want more flexible and have a dynamic result use this.
cy.get('.listings-grid')
.find('.listing')
.then(listing => {
const listingCount = Cypress.$(listing).length;
expect(listing).to.have.length(listingCount);
});
Solution 4
One option is to use "have.length" ...
cy.get('.datatable tr').should('have.length', 4)
...another option is to use should
cy.get('.datatable tr').should(($tr) => {
expect($tr).to.have.length(4)
})
...or then (synchronous queries)
cy.get('.datatable').then(($table) => {
// synchronously query to find length of elements
expect($table.find('td').length).to.equal(4)
})
Solution 5
From the cypress API docs .should() section, using an arrow function:
cy.get('.datatable').find('tr').should(($listOfElements) => {
expect($listOfElements).to.have.length(4)
// any other assertions, for example the below one
// expect($listOfElements).to.have.any.keys('key1', 'key2')
})
This approach will allow you to use Chai BDD notation and assert more than one thing on your list of elements.
Katharine Osborne
Currently a Python/React developer. Formerly a teacher, and back in the 90s, a perl coder.
Updated on May 07, 2022Comments
-
Katharine Osborne about 2 years
I'm starting to learn Cypress. I have a 4 row table (with a class of datatable). I can verify the number of rows this way:
cy.get('.datatable').find('tr').each(function(row, i){ expect(i).to.be.lessThan(4) })
This is fine, but it seems awkward, since I just want to count the length and don't really need to access the stuff in the rows, and I assume it's faster to do one thing than do 4 things.
If I log the selection (not sure what else to call it):
cy.log(cy.get('.datatable').find('tr'))
it comes out as
[object Object]
and I'm not quite sure how to deconstruct that, which suggests to me that I'm thinking about this all wrong.If I try:
expect(cy.get('.datatable').find('tr')).to.have.lengthOf(4)
I get
AssertionError: expected { Object (chainerId, firstCall) } to have a property 'length'
If I try:
expect(Cypress.$('.datatable > tr')).to.have.lengthOf(4)
I get
AssertionError: expected { Object (length, prevObject, ...) } to have a length of 4 but got 0
so at least it has a length here?If I log that method of selection I get
Object{4}
. I'm not sure where to go from here. It seems like this would be a very common thing to deal with.-
Katharine Osborne over 5 yearsMy client uses only Chrome (it's not a public facing app). We have moved away from Cypress as we are converting the app to Angular and are now using Karma and Jasmine (which are inbuilt with the framework). I found Cypress quite easy to work with but I didn't choose it (nor did I choose Angular); however I would have to say that the extensive documentation for Cypress is probably very attractive. When testing is not your ken and more of a chore, having extensive docs with good examples helps you get up and running quicker.
-
alexrogers over 5 yearsThanks, so much for your feedback Katharine
-
-
lauri108 almost 6 yearsThat's one way. See below for an alternative approach.
-
Admin over 5 yearsOther assertions can be chained with
.and()
see should.html#Multiple-Assertions. Less noise IMO. -
Steve Staple about 5 yearstried these & get an error: TypeError: $table.find(...).its is not a function
-
Yuci about 5 years@SteveStaple I tried again with the current latest version of Cypress, v3.2.0, it still works. See my updated answer with a screenshot.
-
Mobiletainment about 5 yearsFor flexibility reasons I prefer this solution over the
.should('have.length', length)
expectation, because.its('length')
provides greater flexibility on your assertions, e.g. greater than or less than. -
png almost 5 yearsThis is a good way to test length, but you can't return the length this way. To return you need to use the Promise chain
.then(elm => elm.length)
-
NPC over 4 yearsLooks like .should('have.length', 4) checks for “at least 4”. The other solution, using .its('length').should('eq', 4), checks for exact equality.
-
James Cameron about 4 yearsThie first one is the best solution if you have dynamic content - otherwise .get will work immediately and return the wrong amount of find, which is waited on even though the real number changed. This solution will wait on the correct number.
-
Matan Bobi almost 4 yearsJust an FYI, you can also use greater than or less than with
should
like this:should('have.length.gte', length)
-
Sasha Bond over 3 yearsthis gets filled listingCount internally only, cannot return it outside of .then()... .its('length') also returns chaining object, not an integer
-
Sasha Bond over 3 yearsthe question was "how to count a selection of items and get the length?" and NOT "how to check" - the goal is to return count outside of the chaining....
-
Muhammad bin Yusrat about 3 yearsThis test is going to be flaky because only the last then will be retried throughout the timeout.
-
DCCoder almost 3 yearsGenerally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others.
-
sao over 2 years@SashaBond why not make a variable higher in scope, then modify it in your .then(). that should fix the scope issue.
-
Dizzy Al over 2 yearsPlease don't post answers already given.
-
Sinister Beard almost 2 yearsThis doesn't answer the question.