# Querying
Examples of querying for DOM elements in Cypress, for a full reference of commands, go to docs.cypress.io and read Selecting Elements: Best Practices Guide
# cy.get()
To query for the button, use the cy.get()
command.
<div id="querying-example">
<div class="well">
<button id="query-btn" class="query-btn btn btn-primary">
Button
</button>
</div>
</div>
// selects the button using ID
cy.get('#query-btn').should('contain', 'Button')
// selects the button using class
cy.get('.query-btn').should('contain', 'Button')
// Use CSS selectors just like jQuery
cy.get('#querying-example .well>button:first').should(
'contain',
'Button',
)
# Number of items
You can attach an assertion to confirm the number of elements.
<section>
<h4>Example</h4>
<h5>Querying elements</h5>
<p>This page has heading elements</p>
<h6>cy.get</h6>
</section>
Example
Querying elements
This page has heading elements
cy.get
// find all H4 + H5 + H6 elements
// and confirm the minimum number of elements
// using the "greater" assertion
cy.get('h4,h5,h6').should('have.length.gt', 1)
Tip: use the .should('have.length', N)
assertion to confirm the exact number of elements. For example, see Assertions page.
# jQuery selectors
cy.get
uses jQuery selectors, thus you can immediately use them to find elements by text (or without given text).
<table>
<tbody>
<tr>
<td>Same</td>
<td>Same</td>
<td>Different</td>
<td>Same</td>
</tr>
</tbody>
</table>
Same | Same | Different | Same |
// selects all table cells with text "Same"
cy.get('td:contains("Same")').should('have.length', 3)
// if the text does not have white spaces, no need to quote it
cy.get('td:contains(Same)').should('have.length', 3)
// you can find elements NOT having the given text
cy.get('td:not(:contains(Same))')
.should('have.length', 1)
.and('have.text', 'Different')
# Escaping special characters
If the element's selector has special characters like .
or :
escape the using \\
character
<div id="user:1234" class="admin.user">Joe</div>
cy.get('#user\\:1234').should('have.text', 'Joe')
cy.get('.admin\\.user')
// no need to escape the non-selector text
.should('have.id', 'user:1234')
# Using attribute selector
You can grab all elements that have an attribute present. For example, to find all <LI>
rows with an attribute "line" present:
<ul id="row-attributes">
<li>No line</li>
<li>No line</li>
<!-- attribute line has no value at all -->
<li line>line</li>
<li line="up">line</li>
<li line="down">line</li>
<li>No line</li>
</ul>
- No line
- No line
- line
- line
- line
- No line
cy.get('#row-attributes li[line]').should('have.length', 3)
You can grab elements with a given attribute. For example, let's make sure there is only a single <a>
element pointing at "index.html":
<a href="article1.html">Article 1</a>
<a href="article2.html">Article 2</a>
<a href="article3.html">Article 3</a>
<a href="index.html">index</a>
cy.get('a[href="index.html"]').should('have.length', 1)
# Attribute prefix
Let's get the element with ID starting with "local-example" prefix
<ul>
<li id="local-example-123">first</li>
<li id="remote-example-456">second</li>
</ul>
- first
- second
cy.get('[id^=local-example]').should('have.text', 'first')
# Attribute suffix
Let's get the element with ID ending with "example-AF9" string
<ul>
<li id="this-example-ZFX">first</li>
<li id="that-example-AF9">second</li>
</ul>
- first
- second
cy.get('[id$=example-AF9]').should('have.text', 'second')
# Combining attribute selectors
Let's get the element with ID that starts with "my-" prefix and ending with "-yours" suffix
<ul>
<li id="my-first-123">first</li>
<li id="my-second-yours">second</li>
</ul>
- first
- second
cy.get('[id^=my-][id$=-yours]').should('have.text', 'second')
# Using data attribute
To find elements by data attribute, query using the attribute selector.
<div data-test-id="test-example" class="example">
Div with <code>data-test-id</code>
</div>
data-test-id
cy.get('[data-test-id="test-example"]').should(
'have.class',
'example',
)
cy.get()
yields a jQuery object, you can get its attribute by invoking the .attr()
method.
// find the element, confirm its attribute
cy.get('[data-test-id="test-example"]')
.invoke('attr', 'data-test-id')
.should('equal', 'test-example')
// or you can get an element's CSS property
cy.get('[data-test-id="test-example"]')
.invoke('css', 'position')
.should('equal', 'static')
Alternatively, chain assertions directly to the cy.get()
call. See assertions documentation.
cy.get('[data-test-id="test-example"]')
.should('have.attr', 'data-test-id', 'test-example')
.and('have.css', 'position', 'static')
# cy.contains()
We can find elements by their content using cy.contains()
<div id="querying">
<ul class="query-list">
<li class="first">apples</li>
<li class="second">oranges</li>
<li class="third">bananas</li>
<li class="fourth">more apples</li>
</ul>
<div class="query-button">
<button class="btn btn-default">
<span>Save Form</span>
</button>
</div>
</div>
- apples
- oranges
- bananas
- more apples
cy.get('.query-list')
.contains('bananas')
.should('have.class', 'third')
// we can pass a regexp to `.contains()`
cy.get('.query-list').contains(/^b\w+/).should('have.class', 'third')
cy.get('.query-list').contains('apples').should('have.class', 'first')
// passing a selector to contains will
// yield the selector containing the text
cy.get('div#querying')
.contains('ul', 'oranges')
.should('have.class', 'query-list')
cy.get('.query-button')
.contains('Save Form')
.should('have.class', 'btn')
# .within
We can find elements within a specific DOM element .within()
<h6>Name input</h6>
<input
type="text"
id="inputName"
class="form-control"
placeholder="Name"
/>
<h6>Form</h6>
<form class="query-form">
<input
type="text"
id="inputEmail"
class="form-control"
placeholder="Email"
/>
<input
type="text"
id="inputPassword"
class="form-control"
placeholder="Password"
/>
</form>
Name input
Form
// validate placeholder attributes
cy.get('.query-form').within(() => {
cy.get('input:first').should('have.attr', 'placeholder', 'Email')
cy.get('input:last').should('have.attr', 'placeholder', 'Password')
})
# Yields the original element
The cy.within
yields the same DOM element it received as the parent.
<div id="within-yields">
The parent div
<div class="some-child">Child element</div>
</div>
cy.get('#within-yields')
.within(() => {
// we are trying to return something
// from the .within callback,
// but it won't have any effect
return cy
.contains('Child element')
.should('have.class', 'some-child')
})
.should('have.id', 'within-yields')
You can attempt to cy.wrap a different value - still the original parent element is going to be yielded.
<div id="wrap-inside-within">
The parent div
<div class="some-child">Child element</div>
</div>
cy.get('#wrap-inside-within')
.within(() => {
// returning cy.wrap(...) has no effect on the yielded value
// it will still be the original parent DOM element
return cy.wrap('a new value')
})
.should('have.id', 'wrap-inside-within')
# Temporarily escape .within
You can temporarily escape the .within
scope by using cy.root + cy.closest commands.
<section id="escape-example">
<h6>Name input</h6>
<input
type="text"
id="inputName"
class="form-control"
placeholder="Name"
/>
<h6>Form</h6>
<form class="the-form">
<input
type="text"
id="inputEmail"
class="form-control"
placeholder="Email"
/>
<input
type="text"
id="inputPassword"
class="form-control"
placeholder="Password"
/>
</form>
</section>
Name input
Form
cy.get('.the-form').within(() => {
// escape back find H6
cy.root().closest('#escape-example').contains('h6', 'Name input')
// escape and enter text into the input field
cy.root()
.closest('#escape-example')
.find('input#inputName')
.type('Batman')
})
Note: you need the cy.root()
command first because cy.closest
is a child command and cannot be used to start the new command chain.
# Number of elements
Using .within
followed by cy.get
is convenient for finding multiple matching elements inside another element. For example, let's confirm that the given picture element has at least 2 source
elements and 1 img
child element.
<picture>
<source srcset="logo-768.png 768w, logo-768-1.5x.png 1.5x" />
<source srcset="logo-480.png, logo-480-2x.png 2x" />
<img src="logo-320.png" alt="logo" />
</picture>

cy.get('picture').within(() => {
// at least 2 source elements
cy.get('source').should('have.length.gt', 1)
// single img element
cy.get('img').should('have.length', 1)
})
# Within works with multiple elements
The parent command can yield multiple elements.
<ul id="fruits">
<li id="item-apples"><a href="/apples">Apples</a></li>
<li id="item-oranges"><a href="/oranges">Oranges</a></li>
</ul>
cy.get('#fruits li').within(() => {
cy.root().should('have.length', 2) // there are 2 LI items
cy.contains('a', 'Apples').should('have.attr', 'href', '/apples')
cy.contains('a', 'Oranges').should('have.attr', 'href', '/oranges')
})
# cy.root()
We can find the root DOM element cy.root()
<ul class="query-ul">
<li>One</li>
<li>Two</li>
<li>Buckle my shoe</li>
</ul>
- One
- Two
- Buckle my shoe
// By default, root is the document
cy.root().should('match', 'html')
cy.get('.query-ul').within(() => {
// In this within, the root is now the ul DOM element
cy.root().should('have.class', 'query-ul')
})
# Best Practices: Selecting elements
Prefer dedicated data-cy
or data-test
attributes to CSS class names and element IDs. See detailed discussion at Best Practices: Selecting elements
<div id="best-practices">
<button
id="main"
class="btn btn-large"
name="submission"
role="button"
data-cy="submit"
>
Submit
</button>
</div>
cy.get('#best-practices').within(() => {
// Worst - too generic, no context
cy.get('button').click()
// Bad. Coupled to styling. Highly subject to change.
cy.get('.btn.btn-large').click()
// Average. Coupled to the `name` attribute which has HTML semantics.
cy.get('[name=submission]').click()
// Better. But still coupled to styling or JS event listeners.
cy.get('#main').click()
// Slightly better. Uses an ID but also ensures the element
// has an ARIA role attribute
cy.get('#main[role=button]').click()
// Much better. But still coupled to text content that may change.
cy.contains('Submit').click()
// Best. Insulated from all changes.
cy.get('[data-cy=submit]').click()
})
# cy.get vs .find
The cy.get command always starts its search from the document
element, or, if used inside .within
, from the cy.root element. The .find command starts the search from the current subject.
<div class="test-title">cy.get vs .find</div>
<section id="comparison">
<div class="feature">Both are querying commands</div>
</section>
cy.get('#comparison')
.get('div')
// finds the DIV .test-title outside the #parent
// and the DIV .feature inside
.should('have.class', 'test-title')
.and('have.class', 'feature')
cy.get('#comparison')
.find('div')
// the search is limited to the tree at #comparison element
.should('have.length', 1)
.and('have.class', 'feature')