Home > OS >  Cypress - get inside get - test different containers at once
Cypress - get inside get - test different containers at once

Time:11-01

I have a page with orders. Each order can have one or more items. I need to check the quantity displayed against the quantity in the mocked data.

Here is the simplified structure:

.order {
  background: white;
  display: flex;
  flex-direction:column;
}
.order:nth-of-type(2n 2) {
  background:#ccc;
}
<div >

  <div >
    <div >
      <h3>
        Item name A
      </h3>
      <div classname="item-quantity">
        3
      </div>
    </div>
    <div >
      <h3>
        Item name B
      </h3>
      <div classname="item-quantity">
        1
      </div>
    </div>
    <div >
      <h3>
        Item name C
      </h3>
      <div classname="item-quantity">
        6
      </div>
    </div>

    <div >
      <div >
        <h3>
          Item name D
        </h3>
        <div classname="item-quantity">
          3
        </div>
      </div>
      <div >
        <h3>
          Item name E
        </h3>
        <div classname="item-quantity">
          9
        </div>
      </div>
    </div>
    
    
    <div >
      <div >
        <h3>
          Item name F
        </h3>
        <div classname="item-quantity">
          3
        </div>
      </div>
      <div >
        <h3>
          Item name G
        </h3>
        <div classname="item-quantity">
          4
        </div>
      </div>
    </div>

  </div>

</div>

Here is the simplified row-data:

"fulfillment": [
{
    "details": [
        {
            "quantity": 3,
            "item": {
                "itemName": "Item name A",
            }
        },
        {
            "quantity": 1,
            "item": {
                "itemName": "Item name B",
            }
        },
        {
            "quantity": 6,
            "item": {
                "itemName": "Item name C",
            }
        }
    ]
},
{
    "details": [
        {
            "quantity": 3,
            "item": {
                "itemName": "Item name D",
            }
        },
        {
            "quantity": 9,
            "item": {
                "itemName": "Item name E",
            }
        },
    ]
},
{
    "details": [
        {
            "quantity": 3,
            "item": {
                "itemName": "Item name F",
            }
        },
        {
            "quantity": 4,
            "item": {
                "itemName": "Item name G",
            }
        },
    ]
}
]

And here is the code I wrote:

it.only('Checks - right item quantity is shown', () => {
    cy.get('@getResponse').then(orders => { 
      const order = orders.response.body.filter(el => el.orderNumber === 'XYZ')[0]

      const singleFul = order.fulfillment.map(singleFulfillment => singleFulfillment.details)

        console.log('singleFul', singleFul)
        
      cy.get('.order').each(($singleFulfillment, index) => {
        const singleItem = singleFul[index].map(detail => detail.quantity)

        console.log('singleItemtop', singleItem)

        cy.get(
          '.order .ordered-item .item-quantity',
        ).each(($singleItemName, idx) => {
            console.log("idx", idx);
            console.log('singleItembottom', singleItem[idx])

          cy.wrap($singleItemName).should('contain', singleItem[idx])
        })
          
          
      })
    })
  })

The problem is that the way I did it, it successfully passes the tests for the first block (first order). The rest are failing.

Here is the result of those console.logs:

singleFul: [Array(3), Array(2), Array(2)]
singleItemtop (3) [3, 1, 6]
singleItemtop (2) [3, 9]
singleItemtop (2) [3, 4]
idx 0
singleItembottom 3
idx 1
singleItembottom 1
idx 2
singleItembottom 6
idx 3
singleItembottom undefined
idx 4
singleItembottom undefined
idx 5
singleItembottom undefined
idx 6
singleItembottom undefined

It looks like that the second (inner) cy.get is finding all the .item-quantity that are present in the page, thus the idx is going on and on.

I tried to use .within too, however it doesn't give an index to correctly match singleItem at the right index.

I hope someone can help me to fix this test to make it work.

Thank you in advance

CodePudding user response:

Can you approach it from the mocked data? Should be easier.

const data = {
  fulfillment: [
    ...
  ]
}

data.fulfillment.forEach(ff => {
  ff.details.forEach(detail => {
    const itemName = detail.item.itemName;
    cy.contains('h3', itemName)
      .next('.item-quantity')
      .invoke('text')
      .then(parseInt)
      .should('eq', detail.quantity)
  })
})

An alternative using Array.flatMap()

const flatData = data.fulfillment.flatMap(order => {
  return order.details.flatMap(orderItem => {
    return {
      name: orderItem.item.itemName, 
      quantity: orderItem.quantity
    }
  })
})
/*
 Yields
 [
   {name: 'Item name A', quantity: 3}
   {name: 'Item name B', quantity: 1}
   {name: 'Item name C', quantity: 6}
   {name: 'Item name D', quantity: 3}
   {name: 'Item name E', quantity: 9}
   {name: 'Item name F', quantity: 3}
   {name: 'Item name G', quantity: 4}
 ]
*/


cy.get('.ordered-item')
  .then($items => {
    return [...$items].map(item => {
      const $item = Cypress.$(item)
      const name = $item.find('h3').text().trim()
      const quantityText = $item.find('div[classname="item-quantity"]')
        .text().trim()
      const quantity = parseInt(quantityText)
      return {name, quantity}
    })
  })
  .should('deep.eq', flatData)

This is a better test because it checks there are no extra items on the page, and also check the order in the data is the same as the order on the page.

  • Related