closest
Get the first DOM element that matches the selector (whether it be itself or one of its ancestors).
.closest() tests the element itself first, then travels up the DOM tree
through its ancestors.
The querying behavior of this command matches how
.closest() works in jQuery, except that
Cypress continues past shadow DOM boundaries. See
Shadow DOM boundaries and .closest().
Syntax​
.closest(selector)
.closest(selector, options)
Usage​
Correct Usage
cy.get('td').closest('.filled') // Yield closest el with class 'filled'
Incorrect Usage
cy.closest('.active') // Errors, cannot be chained off 'cy'
cy.clock().closest() // Errors, 'clock' does not yield DOM elements
Arguments​
selector (String selector)
A selector the element itself or one of its ancestors must match.
options (Object)
Pass in an options object to change the default behavior of .closest().
| Option | Default | Description |
|---|---|---|
log | true | Displays the command in the Command log |
timeout | defaultCommandTimeout | Time to wait for .closest() to resolve before timing out |
Yields ​
.closest()yields the new DOM element(s) it found. When the subject holds more than one element, it yields the closest match for each one, with duplicates removed..closest()is a query, and it is safe to chain further commands.
Examples​
Selector​
Find the closest ancestor of p.error with class banner​
<div class="banner">
<div class="content">
<p class="error">Payment failed</p>
</div>
</div>
// yields <div class="banner">…</div>
cy.get('p.error').closest('.banner')
Yield the subject itself when it matches​
<ul class="nav">
<li class="active">Home</li>
</ul>
// yields <li class="active">Home</li>, since the subject
// matches the selector before any ancestor is tested
cy.get('li.active').closest('li')
Act on one card in a repeated list​
Find something unique inside a repeated component, climb to the component with
.closest(), then query inside it.
<div data-cy="product-card">
<h3>Trail Runner</h3>
<button>Add to cart</button>
</div>
<div data-cy="product-card">
<h3>Road Racer</h3>
<button>Add to cart</button>
</div>
// clicks the "Add to cart" button in the Road Racer card only
cy.contains('h3', 'Road Racer')
.closest('[data-cy="product-card"]')
.find('button')
.click()
Assert on a form field's wrapper​
Validation state often lives on a wrapper element rather than on the input.
<div class="form-group has-error">
<label for="email">Email</label>
<input id="email" type="email" />
</div>
cy.get('#email').closest('.form-group').should('have.class', 'has-error')
Compare .closest() with .parents()​
.closest() stops at the first match. .parents()
collects every matching ancestor.
<section class="panel outer">
<section class="panel inner">
<button>Save</button>
</section>
</section>
// yields <section class="panel inner">
cy.get('button').closest('.panel')
// yields <section class="panel inner"> and <section class="panel outer">
cy.get('button').parents('.panel')
Assert that an element is not inside a container​
When no ancestor matches, .closest() yields an empty result, so
.should('not.exist') passes.
// passes when the checkout button is not inside a modal
cy.get('[data-cy="checkout"]').closest('.modal').should('not.exist')
Notes​
Shadow DOM boundaries and .closest()​
When the subject is inside a shadow root, .closest() crosses the shadow
boundary. If nothing inside the shadow root matches, it continues from the
shadow host, testing the host itself and then the host's ancestors, until it
finds a match or reaches the document. This happens whether or not
includeShadowDom is enabled. The
option controls whether queries like .find() reach
into a shadow root, not whether .closest() climbs back out of one.
<form id="checkout">
<payment-panel>
<template shadowrootmode="open">
<button>Pay now</button>
</template>
</payment-panel>
</form>
// .find() needs includeShadowDom to reach the button;
// .closest() crosses back out of the shadow root on its own
// yields <form id="checkout">
cy.get('payment-panel')
.find('button', { includeShadowDom: true })
.closest('form')
Rules​
Requirements ​
.closest()requires being chained off a command that yields DOM element(s) or a document.
Assertions ​
.closest()will automatically retry until the element(s) exist in the DOM..closest()will automatically retry until all chained assertions have passed.
Timeouts ​
.closest()can time out waiting for the element(s) to exist in the DOM..closest()can time out waiting for assertions you've added to pass.
Command Log​
Find the closest element of li.active with the class 'nav'
cy.get('li.active').closest('.nav')
The commands above will display in the Command Log as:

When clicking on the closest command within the command log, the console
outputs the following:

History​
| Version | Changes |
|---|---|
| 12.0.0 | .closest() is now a query. Overwrite it with Cypress.Commands.overwriteQuery() rather than Cypress.Commands.overwrite(). |