find
Get the descendant DOM elements that match a selector.
.find() searches every level below the subject, as opposed to
.children(), which only looks one level down.
Syntax​
.find(selector)
.find(selector, options)
Usage​
Correct Usage
cy.get('.article').find('footer') // Yield 'footer' within '.article'
Incorrect Usage
cy.find('.progress') // Errors, cannot be chained off 'cy'
cy.clock().find('li') // Errors, 'clock' does not yield DOM elements
Arguments​
selector (String selector)
A selector used to match descendant DOM elements.
options (Object)
Pass in an options object to change the default behavior of .find().
| Option | Default | Description |
|---|---|---|
log | true | Displays the command in the Command log |
timeout | defaultCommandTimeout | Time to wait for .find() to resolve before timing out |
includeShadowDom | includeShadowDom config option value | Whether to also search inside the shadow roots of the subject and its descendants, including nested shadow roots. |
Yields ​
.find()yields the new DOM element(s) it found..find()is a query, and it is safe to chain further commands.
Examples​
Selector​
Find the li elements inside a parent with .find()​
<ul id="parent">
<li class="first"></li>
<li class="second"></li>
</ul>
// yields [<li class="first"></li>, <li class="second"></li>]
cy.get('#parent').find('li')
Find direct children with a leading > in .find()​
Start the selector with > to match only direct children of the subject. The
result is the same as .children('li').
<ul class="nav">
<li>Home</li>
<li>
Docs
<ul>
<li>API</li>
</ul>
</li>
</ul>
// yields [<li>Home</li>, <li>Docs<ul>…</ul></li>]
cy.get('.nav').find('> li')
// yields all 3 li elements, including the nested one
cy.get('.nav').find('li')
Assertions​
Assert on the number of elements .find() yields​
When .find() is chained off another query such as
cy.get(), Cypress reruns the whole chain until the
assertion passes, so the count stays current as the page updates.
cy.get('[data-cy=cart]').find('[data-cy=cart-item]').should('have.length', 3)
Assert that .find() no longer finds an element​
Chain .should('not.exist') to wait for an element, such as a loading spinner,
to leave the subject.
cy.get('[data-cy=results]').find('.spinner').should('not.exist')
Options​
Wait longer for slow content with timeout​
Pass timeout to give .find() more time than
defaultCommandTimeout to locate its
elements.
cy.get('[data-cy=report]').find('table', { timeout: 10000 })
Find elements inside a shadow root with includeShadowDom​
By default, .find() does not search inside shadow roots. Pass
includeShadowDom: true to search them, or set the
includeShadowDom configuration option
to search them in every query.
<checkout-panel>
#shadow-root
<button>Checkout</button>
</checkout-panel>
// yields [<button>Checkout</button>]
cy.get('checkout-panel').find('button', { includeShadowDom: true })
Notes​
.find() only searches below the subject​
.find() matches descendants of the subject, never the subject itself. An
element that matches the selector is left out of the result when it is the
subject. To search from the root of the page instead, use
cy.get(), and see
how cy.get() and .find() differ.
<div class="card">
<div class="card">Nested</div>
</div>
// yields [<div class="card">Nested</div>], not the outer .card
cy.get('.card').first().find('.card')
Subjects with multiple elements​
When the subject holds more than one element, .find() searches inside each
one and yields a single set, in document order, with any duplicates removed.
<ul>
<li><a href="/home">Home</a></li>
<li><a href="/docs">Docs</a></li>
</ul>
// yields [<a href="/home">Home</a>, <a href="/docs">Docs</a>]
cy.get('li').find('a')
.find() compared to .within()​
Chain .find() when you run one query inside an element.
.within() scopes every command in its callback to the
subject, which reads better when you run several commands against the same
region.
// Option 1: one query
cy.get('[data-cy=login-form]').find('[data-cy=submit]').click()
// Option 2: several commands in the same region
cy.get('[data-cy=login-form]').within(() => {
cy.get('[data-cy=password]').type('secret')
cy.get('[data-cy=submit]').click()
})
Reading a .find() timeout error​
When .find() times out without finding its elements, the error names the
selector and lists the queries that produced its subject. The chain shows
whether the problem is the .find() selector or an earlier query that yielded a
different element than you expected.
cy.get('[data-cy=cart]').find('.total')
Timed out retrying after 4000ms: Expected to find element: `.total`, but never found it. Queried from:
> cy.get([data-cy=cart])
Shadow DOM boundaries and .find()​
Without includeShadowDom, .find() stops at a shadow boundary: it searches
the markup written inside a shadow host, not the host's shadow root. Chained off
an element that is already inside a shadow root, it searches that shadow tree
normally, with or without the option. To search one shadow root only, traverse
into it with .shadow() first:
cy.get('checkout-panel').shadow().find('button')
Rules​
Requirements ​
.find()requires being chained off a command that yields DOM element(s) or a document.
Assertions ​
.find()will automatically retry until the element(s) exist in the DOM..find()will automatically retry until all chained assertions have passed.
Timeouts ​
.find()can time out waiting for the element(s) to exist in the DOM..find()can time out waiting for assertions you've added to pass.
Command Log​
Find the li elements within the nav
cy.get('.left-nav>.nav').find('>li')
The commands above display in the Command Log as:

Clicking the find command in the Command Log outputs the selector, the
element(s) it was applied to, the yielded elements, and the number of elements
found to the console:

History​
| Version | Changes |
|---|---|
| 12.6.0 | Overwrite .find() with Cypress.Commands.overwriteQuery() rather than Cypress.Commands.overwrite(). |
| 12.0.0 | .find() is now a query. |
| 5.2.0 | Added includeShadowDom option. |