Contains text in a list

Let's take a list and check if it contains a given text. We can write this test in several ways. Watch the video Find Text Item Without Flake Using cy.contains Commandopen in new window to see the explanation behind this recipe.

<ul id="list">
  <li>one</li>
  <li>two</li>
  <li>three</li>
  <li>four</li>
  <li>five</li>
</ul>
// uncomment the threshold to see the full array
// chai.config.truncateThreshold = 300
cy.get('#list')
  .find('li')
  .then((items) => {
    const list = Array.from(items, (item) => item.innerText)
    expect(list).to.include('three')
  })

What if the list is dynamic? The added items will NOT be seen by the .then command unfortunately, since Cypress retries the last command only, see the retry-ability guideopen in new window.

<ul id="list">
  <li>one</li>
  <li>two</li>
</ul>
<script>
  setTimeout(function () {
    const list = document.getElementById('list')
    list.innerHTML += `
      <li>three</li>
      <li>four</li>
      <li>five</li>
    `
  }, 1000)
</script>
// 🔥 WILL NOT WORK
// the ".then(cb)" will never retry checking the page
// and won't see the added items
cy.get('#list')
  .find('li')
  .then((items) => {
    const list = Array.from(items, (item) => item.innerText)
    expect(list).to.include('three')
  })
// ✅ a single cy.contains command retries searching the entire page
// until the list item "three" is added and the test passes
cy.contains('#list li', 'three')

What if you want to check multiple items?

const items = ['three', 'four', 'one']
items.forEach((item) => {
  cy.contains('#list li', item)
})