How do you use Cypress filter to apply multiple text-based conditions on elements?

Hello people!!

I’m working on a Cypress test where I need to select a very specific HTML element from a set of similar structures. I need to select the .row element based on multiple conditions regarding its nested text content.

Here’s the HTML I’m working with:

<div class="row">
  <span class="code">001</span>
  <span class="ref">002</span>
  <label>Some Label</label>
</div>
<div class="row">
  <span class="code">002</span>
  <span class="ref">002</span>
  <label>Another label</label>
</div>
<div class="row">
  <span class="code">002</span>
  <span class="ref">001</span>
  <label>Something</label>
</div>

I’m aiming to select the .row element where the .code is 002 AND the .ref is 001. I tried using:

cy.get('.row').filter(`span.code:contains("002")span.ref:contains("001")`)

However, this Cypress selector doesn’t seem to work as expected, even when I try it with a single condition.

Could someone provide guidance on the correct approach for combining these types of conditions to select the desired element? Any insights into what I might be missing would be greatly appreciated.

Hi @heenakhan.khatri!

Your challenge with applying multiple conditions using Cypress filter() is a very common one. I definitely ran into a similar issue a few weeks ago!

Turns out, filter() in Cypress works on the raw DOM elements already selected by cy.get(). So, it won’t directly handle those nested selectors you’ve written in the way you might expect. What worked reliably for me was filtering with a .filter() callback, like this:

cy.get('.row').filter((index, el) => {
  return (
    Cypress.$(el).find('.code').text().trim() === '002' &&
    Cypress.$(el).find('.ref').text().trim() === '001'
  );
});

This approach allows you to check the text content of the children manually using Cypress’s bundled jQuery within the callback. It works very reliably when Cypress filter needs to evaluate multiple nested conditions.

Hope this helps you accurately target those complex elements!

Hello fellow test automation engineers! Adding another powerful technique to the discussion about selecting elements with complex nested conditions in Cypress.

@heenakhan.khatri you are not alone in this, even I like many others had this exact issue when testing a complex UI! The key thing to know about Cypress filter is that it doesn’t always behave like a pure CSS selector when passed a string for complex conditions. You often need a function for that advanced logic. What worked for me was filtering with a .each() callback and then applying assertions inside:

cy.get('.row').each(($row) => {
  const code = $row.find('.code').text().trim();
  const ref = $row.find('.ref').text().trim();

  if (code === '002' && ref === '001') {
    cy.wrap($row).should('contain.text', 'Something');
  }
});

It’s a bit more verbose, yes, but it provides you with granular control and better readability when Cypress can’t directly apply a string-based filter for your exact condition. This helps especially when Cypress filter doesn’t support your specific conditional out of the box.

Hope this robust approach helps you target those tricky elements reliably!

Been through this before! The reason your Cypress filter attempt doesn’t work is because it expects a jQuery-style selector or a callback, and that CSS-style chaining inside .filter() doesn’t actually work like you’d expect.

For multiple conditions, I recommend using a callback filter and explicitly checking each value:"

cy.get('.row').filter((_i, row) => {
  const $row = Cypress.$(row);
  return $row.find('.code').text() === '002' && $row.find('.ref').text() === '001';
});

This approach has always worked well for me when I need Cypress filter to do more complex checks across siblings or children inside a parent element