Traversal
Examples of traversing DOM elements in Cypress, for a full reference of commands, go to docs.cypress.io
.children()
To get children of DOM elements, use the .children()
command.
<ol class="traversal-breadcrumb breadcrumb">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item"><a href="#">Library</a></li>
<li class="breadcrumb-item active">Data</li>
</ol>
cy.get('.traversal-breadcrumb')
.children('.active')
.should('contain', 'Data')
You can get the number of children and check it using have.length
assertions. Even hidden elements are counted.
<ol id="fruit-cart">
<li>Oranges</li>
<li>Grapes</li>
<li style="display:none">Apples (sold out)</li>
</ol>
// confirm the total number of children
cy.get('#fruit-cart').children().should('have.length', 3)
// confirm the number of visible children
cy.get('#fruit-cart')
// use the jQuery pseudo selector ":visible"
.children(':visible')
.should('have.length', 2)
// confirm the number of hidden children
cy.get('#fruit-cart')
// use the jQuery pseudo selector ":hidden"
.children(':hidden')
.should('have.length', 1)
// get the number of hidden children
// using "not visible" pseudo selectors
cy.get('#fruit-cart')
.children(':not(:visible)')
.should('have.length', 1)
.closest()
To get the closest ancestor DOM element, use the .closest()
command.
<ul class="list-group">
<li class="list-group-item">
<span class="badge">14</span>
Events
</li>
<li class="list-group-item">
<span class="badge traversal-badge">54</span>
Friends
</li>
</ul>
cy.get('.traversal-badge')
.closest('ul')
.should('have.class', 'list-group')
.eq()
To get a DOM element at a specific index, use the .eq()
command.
<ul class="traversal-list">
<li>tabby</li>
<li>siamese</li>
<li>persian</li>
<li>sphynx</li>
<li>burmese</li>
</ul>
cy.get('.traversal-list>li').eq(1).should('contain', 'siamese')
.filter()
To get DOM elements that match a specific selector, use the .filter()
command.
<ul class="traversal-nav nav nav-tabs">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Services</a>
</li>
</ul>
cy.get('.traversal-nav > li a')
.filter('.active')
.should('contain', 'About')
Elements with an attribute
Let's grab all row elements, but then keep only the elements with an attribute line
present:
<table id="filter-attribute">
<tbody>
<tr>
<td>No line</td>
</tr>
<tr>
<td>No line</td>
</tr>
<!-- attribute line has no value at all -->
<tr line>
<td>line</td>
</tr>
<tr line="up">
<td>line</td>
</tr>
<tr line="down">
<td>line</td>
</tr>
<tr>
<td>No line</td>
</tr>
</tbody>
</table>
cy.get('#filter-attribute tr')
// only interested in the elements
// that have the attribute "line"
.filter('[line]')
.should('have.length', 3)
Visible elements
You can use .filter
to find visible elements using jQuery selector :visible
<ul class="visible-items">
<li>first</li>
<li style="display:none">second</li>
<li style="display:none">third</li>
<li>fourth</li>
</ul>
cy.get('.visible-items li')
.should('have.length', 4) // all LI items
// from all found elements, find only the visible ones
.filter(':visible')
.should('have.length', 2) // only 2 visible LI items
Tip: you can make the test more robust against flake by merging the two commands cy.get
+ .filter
into a single one following the advice given in the Cypress Retry-ability guide.
cy.log('**single :visible selector query**')
// use a single CSS + :visible jQuery selector
cy.get('.visible-items li:visible')
// only 2 visible LI items
.should('have.length', 2)
Using a callback function
You can filter elements using a predicate callback function.
Let's find all list items with the text "cat" or class "pet".
<ul id="animals">
<li class="pet">Puppy</li>
<li>Small cat</li>
<li>Large cat</li>
<li>Pet tarantula</li>
<li class="pet">Hamster</li>
</ul>
cy.get('#animals li')
// ensure we have all items
.should('have.length', 5)
// find the items we are interested in
.filter((k, el) => {
// k is the 0-based index
// el is the DOM element
return (
el.classList.contains('pet') ||
el.innerText.includes('cat')
)
})
.should('have.length', 4)
Watch the video Use cy.filter For Complex Element Filtering.
Find more filtering examples in the recipes Computed style and Filter elements. Learn how to find input elements by their current value in the recipe Input value.
Skip an element with certain text
Let's say we want to grab the list of job options from the list below. Notice that one of the entries has the descriptive text and should be skipped.
<ul id="jobs">
<li>(Pick your current job)</li>
<li>Teacher</li>
<li>Nurse</li>
<li>Driver</li>
</ul>
We can skip the non-job list item in several ways.
// 1. skip using the cy.filter(callback)
cy.get('#jobs li')
.filter((k, el) => !el.innerText.includes('Pick'))
.should('have.length', 3)
// 2. skip using the cy.filter(callback) using the index
cy.get('#jobs li')
// filter out the very first element
.filter((k) => k > 0)
.should('have.length', 3)
// 3. filter using the text and jQuery
// :not and :contains selectors
cy.get('#jobs li')
.filter(':not(:contains("Pick"))')
.should('have.length', 3)
.find()
To get descendant DOM elements of the selector, use the .find()
command.
<ul class="pagination traversal-pagination">
<li class="page-item">
<a class="page-link" href="#">
<span>«</span>
</a>
</li>
<li class="page-item">
<a class="page-link" href="#">1</a>
</li>
<li class="page-item">
<a class="page-link" href="#">2</a>
</li>
<li class="page-item">
<a class="page-link" href="#">3</a>
</li>
<li class="page-item">
<a class="page-link" href="#">4</a>
</li>
<li class="page-item">
<a class="page-link" href="#">5</a>
</li>
<li class="page-item">
<a class="page-link" href="#">
<span>»</span>
</a>
</li>
</ul>
// 5 individual links plus "prev" and "next" links
cy.get('.traversal-pagination')
.find('li.page-item')
.find('a')
.should('have.length', 7)
Finds all elements
The .find()
command is a child command. For every element yielded by the parent command, .find
finds the elements matching the selectors.
<ul id="a-list">
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
cy.get('ul#a-list').find('li').should('have.length', 3)
Now imagine we grab the <LI>
elements and try to find elements in each one.
<ul id="anchors">
<li><a>link A</a>, <a>link B</a></li>
<li><a>link C</a>, <a>link D</a></li>
<li><a>link E</a>, <a>link F</a></li>
</ul>
cy.get('ul#anchors li')
.should('have.length', 3)
// inside each LI element, find the A elements
.find('a')
.should('have.length', 6)
Find all links
If we want to find every child element with href
attribute:
<ul id="links">
<li><a href="a">link A</a>, <a>link B</a></li>
<li><a>link C</a>, <a href="d">link D</a></li>
<li><a href="e">link E</a>, <a href="f">link F</a></li>
</ul>
Notice how only some of the <A>
elements have href
attribute
cy.get('ul#links li')
.should('have.length', 3)
// inside each LI element, find the elements with href attribute
.find('[href]')
.should('have.length', 4)
Find links without href attribute
<ul id="incomplete-links">
<li><a href="a">link A</a>, <a>link B</a></li>
<li><a>link C</a>, <a href="d">link D</a></li>
<li><a href="e">link E</a>, <a href="f">link F</a></li>
</ul>
Let's find LI
elements, then inside each find A
elements without href
attribute. We can use the jQuery selector :not
to search for elements without an attribute.
cy.get('ul#incomplete-links li')
.should('have.length', 3)
.find('a:not([href])')
// only two links are missing "href" attribute
.should('have.length', 2)
.first()
To get the first DOM element within elements, use the .first()
command.
<table class="table traversal-table">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Jane</td>
<td>Lane</td>
</tr>
<tr>
<td>2</td>
<td>John</td>
<td>Doe</td>
</tr>
</tbody>
</table>
cy.get('.traversal-table td').first().should('contain', '1')
:first selector
You can also use :first
CSS selector to merge the cy.get
and .first
commands into a single one for better retry-ability
<table class="table traversal-table">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Jane</td>
<td>Lane</td>
</tr>
<tr>
<td>2</td>
<td>John</td>
<td>Doe</td>
</tr>
</tbody>
</table>
// get the first table cell using the :first CSS selector
cy.get('.traversal-table td:first').should('have.text', '1')
// get the first row
cy.get('.traversal-table tbody tr:first').contains('td', 'Lane')
.last()
To get the last DOM element within elements, use the .last()
command.
<div class="traversal-buttons">
<a class="btn btn-default" href="#" role="button">Link</a>
<button class="btn btn-default" type="submit">Button</button>
<input class="btn btn-default" type="button" value="Input" />
<input class="btn btn-default" type="submit" value="Submit" />
</div>
cy.get('.traversal-buttons .btn')
.last()
.should('contain', 'Submit')
// you can also use the CSS selector :last to avoid
// using a separate .last() command
cy.get('.traversal-buttons .btn:last').should(
'contain',
'Submit',
)
.next()
To get the next sibling DOM element within elements, use the .next()
command.
<ul class="traversal-ul">
<li>apples</li>
<li class="second">oranges</li>
<li>bananas</li>
</ul>
cy.get('.traversal-ul')
.contains('apples')
.next()
.should('have.class', 'second')
.and('contain', 'oranges')
See also Sibling element recipe.
.next() with selector
Given the previous element (or several), we can find the next element matching the given selector.
<ul id="next-selector">
<li>apples</li>
<li>oranges</li>
<li>bananas</li>
<li class="selected">pineapples</li>
</ul>
// currently does not work due to bug 19724
cy.get('#next-selector li')
.first()
.next('.selected')
.should('have.text', 'pineapples')
Workaround while #19724 is open
// currently does not work due to bug 19724
cy.get('#next-selector li')
.first()
.nextAll()
.filter('.selected')
.should('have.text', 'pineapples')
See the video How To Report A Cypress Bug.
.nextAll()
To get all of the next sibling DOM elements within elements, use the .nextAll()
command.
<ul class="traversal-next-all">
<li>apples</li>
<li class="second">oranges</li>
<li>bananas</li>
<li>pineapples</li>
<li>grapes</li>
</ul>
cy.get('.traversal-next-all')
.contains('oranges')
.nextAll()
.should('have.length', 3)
.nextUntil()
To get all of the next sibling DOM elements within elements until another element, use the .nextUntil()
command.
<ul class="healthy-foods">
<li id="fruits" class="header">Fruits</li>
<li>apples</li>
<li>oranges</li>
<li>bananas</li>
<li id="veggies" class="header">Vegetables</li>
<li>cucumbers</li>
<li>carrots</li>
<li>corn</li>
<li id="nuts" class="header">Nuts</li>
<li>walnuts</li>
<li>cashews</li>
<li>almonds</li>
</ul>
<style>
.header {
font-weight: bolder;
}
</style>
cy.get('#veggies')
.nextUntil('#nuts')
.should('have.length', 3)
.and(($veggies) => {
expect($veggies[0]).to.have.text('cucumbers')
expect($veggies[1]).to.have.text('carrots')
expect($veggies[2]).to.have.text('corn')
})
.not()
To remove DOM element(s) from the set of elements, use the .not()
command.
<div class="traversal-disabled">
<button
type="button"
class="btn btn-default"
disabled="disabled"
>
Disabled
</button>
<button type="button" class="btn btn-default">Button</button>
</div>
cy.get('.traversal-disabled .btn')
.not('[disabled]')
.should('not.contain', 'Disabled')
Find all incomplete items
Another example, showing the .not
command vs jQuery :not(...)
selector. Let's say we have several TODO items, and some of them are already completed.
<style>
.todo.completed {
text-decoration: line-through;
color: gray;
}
</style>
<ul id="todo-items">
<li class="todo completed">Code apps</li>
<li class="todo">Write tests</li>
<li class="todo completed">Get paid</li>
</ul>
cy.get('#todo-items').within(() => {
// there are two completed items
cy.get('.todo.completed').should('have.length', 2)
// but how do we find the incomplete items?
// 1. select all elements with class "todo"
// 2. remove all elements with class "completed"
cy.get('.todo').not('.completed').should('have.length', 1)
// ALTERNATIVE: a slightly more robust way that does not split the query
// commands; we can use the jQuery ":not" selector
cy.get('.todo:not(.completed)').should('have.length', 1)
})
.parent()
To get parent DOM element of elements, use the .parent()
command.
<p>
Morbi leo risus, porta ac consectetur ac,
<mark class="traversal-mark">highlight</mark> vestibulum at
eros.
</p>
cy.get('.traversal-mark')
.parent()
.should('contain', 'Morbi leo risus')
.parents()
To get parent DOM elements of elements, use the .parents()
command.
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<footer>
Someone famous in
<cite class="traversal-cite">Source Title</cite>
</footer>
</blockquote>
cy.get('.traversal-cite').parents().should('match', 'blockquote')
.parentsUntil()
To get parents DOM element of elements until other element, use the .parentsUntil()
command.
<ul class="nav clothes-nav">
<li>
<a href="#">Clothes</a>
<ul class="menu">
<li>
<a href="/shirts">Shirts</a>
</li>
<li class="active">
<a href="/pants">Pants</a>
</li>
</ul>
</li>
</ul>
cy.get('.clothes-nav')
.find('.active')
.parentsUntil('.clothes-nav')
.should('have.length', 2)
.prev()
To get the previous sibling DOM element within elements, use the .prev()
command.
<ul class="birds list-group">
<li class="list-group-item">Cockatiels</li>
<li class="list-group-item">Lorikeets</li>
<li class="list-group-item active">Cockatoos</li>
<li class="list-group-item">Conures</li>
<li class="list-group-item">Eclectus</li>
</ul>
cy.get('.birds')
.find('.active')
.prev()
.should('contain', 'Lorikeets')
.prevAll()
To get all previous sibling DOM elements within elements, use the .prevAll()
command.
<ul class="fruits-list">
<li>apples</li>
<li>oranges</li>
<li class="third">bananas</li>
<li>pineapples</li>
<li>grapes</li>
</ul>
cy.get('.fruits-list')
.find('.third')
.prevAll()
.should('have.length', 2)
.prevUntil()
To get all previous sibling DOM elements within elements until other element, use the .prevUntil()
command.
<ul class="foods-list">
<li id="fruits" class="header">Fruits</li>
<li>apples</li>
<li>oranges</li>
<li>bananas</li>
<li id="veggies" class="header">Vegetables</li>
<li>cucumbers</li>
<li>carrots</li>
<li>corn</li>
<li id="nuts" class="header">Nuts</li>
<li>walnuts</li>
<li>cashews</li>
<li>almonds</li>
</ul>
cy.get('.foods-list')
.find('#nuts')
.prevUntil('#veggies')
.should('have.length', 3)
.siblings()
To get all sibling DOM elements of elements, use the .siblings()
command.
<ul class="nav nav-pills traversal-pills">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Messages</a></li>
</ul>
cy.get('.traversal-pills .active')
.siblings()
.should('have.length', 2)