Skip to content

cy.get(), cy.find(), and cy.contains()

cy.get(), .find(), and cy.contains() are the three commands you will reach for constantly when locating elements. This lesson clarifies exactly how each one searches and when to prefer one over another.

Three Related but Different Commands

cy.get(selector) searches the entire document for elements matching a CSS selector and always starts a fresh search, regardless of any previous subject.

.find(selector) searches only within the current subject's descendants, it must be chained after another command that already yielded a subject. cy.contains(text) finds an element containing the given text content, optionally scoped by a preceding selector.

cy.get('[data-cy="product-card"]')
  .find('[data-cy="price"]')
  .should('contain', '$');

cy.contains('[data-cy="product-card"]', 'Wireless Mouse')
  .find('[data-cy="add-to-cart"]')
  .click();

The second example scopes contains() to product cards, finding the one containing specific text, then clicking its add-to-cart button.

Syntax for Each Command

cy.get(selector)
cy.get(selector, options)

.find(selector)

cy.contains(text)
cy.contains(selector, text)
  • cy.get() always searches the whole page; it cannot be scoped to a previous subject.
  • .find() must follow another command and searches only its descendants.
  • cy.contains(text) searches the whole page for an element containing that exact substring.
  • cy.contains(selector, text) narrows the search to elements matching the selector first.

get / find / contains Cheat Sheet

A quick side-by-side reference for the three most common location commands.

Command Scope Matches By
cy.get('.card') Whole document CSS selector
cy.get('.list').find('li') Descendants of .list CSS selector
cy.contains('Save') Whole document Visible text content
cy.contains('button', 'Save') Whole document, filtered by tag Text within matching tag
cy.get('.card').contains('Save') Descendants of .card Visible text content

How cy.contains() Matches Text

cy.contains() looks for the deepest element in the DOM tree that contains the given text as a substring, matching case-insensitively by default, and ignoring extra whitespace differences.

If multiple elements contain the same text, cy.contains() returns the first one found in document order, so combining it with a scoping selector or a preceding .find()/parent chain often produces more predictable results.

// Ambiguous if "Save" appears in multiple places
cy.contains('Save').click();

// More precise: scope to a specific container first
cy.get('[data-cy="edit-form"]').contains('button', 'Save').click();

Choosing the Right Command

Use cy.get() when you have (or can add) a dedicated, unique selector. Use .find() when you already have a scoped subject and need to drill into it. Use cy.contains() when text content, not structure, is the most natural way to identify an element, such as a specific row in a table or a named button among several similar ones.

  • Prefer cy.get('[data-cy=...]') whenever a stable attribute is available.
  • Reach for .find() to stay scoped within an already-located container.
  • Reach for cy.contains() when identifying by visible text is clearer than any selector would be.

Common Mistakes

  • Expecting cy.get() to search only within a previously yielded subject, it always searches the whole document.
  • Using unscoped cy.contains() on a page where the same text appears in multiple, unrelated places.
  • Chaining .find() without a preceding command that actually yields a subject to search within.
  • Relying on exact text matches with cy.contains() for content that is likely to change wording later (like marketing copy).

Key Takeaways

  • cy.get() always searches the entire document by CSS selector.
  • .find() searches only within the current subject's descendants.
  • cy.contains() matches by visible text and can optionally be scoped by a tag or selector.
  • Choosing the right command reduces ambiguity and makes selectors easier to reason about.

Pro Tip

When using cy.contains(), scope it with a selector (cy.contains('button', 'Save')) whenever there is any chance the same text appears elsewhere on the page, it costs almost nothing and prevents a whole category of "wrong element" flakiness.