In Cypress how to count a selection of items and get the length?

159,336

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)

enter image description here 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.

Share:
159,336
Katharine Osborne
Author by

Katharine Osborne

Currently a Python/React developer. Formerly a teacher, and back in the 90s, a perl coder.

Updated on May 07, 2022

Comments

  • Katharine Osborne
    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
      Katharine Osborne over 5 years
      My 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
      alexrogers over 5 years
      Thanks, so much for your feedback Katharine
  • lauri108
    lauri108 almost 6 years
    That's one way. See below for an alternative approach.
  • Admin
    Admin over 5 years
    Other assertions can be chained with .and() see should.html#Multiple-Assertions. Less noise IMO.
  • Steve Staple
    Steve Staple about 5 years
    tried these & get an error: TypeError: $table.find(...).its is not a function
  • Yuci
    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
    Mobiletainment about 5 years
    For 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
    png almost 5 years
    This 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
    NPC over 4 years
    Looks 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
    James Cameron about 4 years
    Thie 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
    Matan Bobi almost 4 years
    Just an FYI, you can also use greater than or less than with should like this: should('have.length.gte', length)
  • Sasha Bond
    Sasha Bond over 3 years
    this gets filled listingCount internally only, cannot return it outside of .then()... .its('length') also returns chaining object, not an integer
  • Sasha Bond
    Sasha Bond over 3 years
    the 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
    Muhammad bin Yusrat about 3 years
    This test is going to be flaky because only the last then will be retried throughout the timeout.
  • DCCoder
    DCCoder almost 3 years
    Generally, 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
    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
    Dizzy Al over 2 years
    Please don't post answers already given.
  • Sinister Beard
    Sinister Beard almost 2 years
    This doesn't answer the question.