Skip to main content
Cypress App

get

Get one or more DOM elements by selector or alias.

info

The querying behavior of this command is similar to how $(...) works in jQuery.

Syntax​

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

Usage​

Correct Usage

cy.get('.list > li') // Yield the <li>'s in .list

Arguments​

selector (String selector)

A selector used to filter matching DOM elements.

alias (String)

An alias as defined using the .as() command and referenced with the @ character and the name of the alias.

You can use cy.get() for aliases of DOM elements, primitives, objects, intercepts, spies, and stubs.

By default, an alias re-runs the queries leading up to it each time you request it, so an aliased DOM element reflects the current state of the page. An alias created with { type: 'static' } yields the value captured when the alias was created. See .as() for details.

options (Object)

Pass in an options object to change the default behavior of cy.get().

OptionDefaultDescription
logtrueDisplays the command in the Command log
timeoutdefaultCommandTimeoutTime, in milliseconds, to wait for cy.get() to resolve before timing out. Must be a number.
withinSubjectthe .within() subject, otherwise the documentElement to search within. Pass null to search from the document.
includeShadowDomincludeShadowDom config option valueWhether to traverse shadow DOM boundaries and include elements within the shadow DOM in the yielded results.

Yields ​

  • cy.get() yields the DOM element(s) it found, or the results of the alias lookup.
  • For an intercept alias, cy.get() yields the most recent interception, or null if no request has matched yet.
  • cy.get() is a query, and it is safe to chain further commands.

Examples​

Selector​

Get the input element​

cy.get('input').should('be.disabled')

Find the first li descendant within a ul​

cy.get('ul li:first').should('have.class', 'active')

Find the first li in every ul​

:first is a jQuery extension that yields only the first matching element on the whole page. To get the first li in each list, use the CSS :first-child selector instead.

<ul class="fruits">
<li>Apple</li>
<li>Banana</li>
</ul>
<ul class="vegetables">
<li>Carrot</li>
<li>Pea</li>
</ul>
cy.get('ul li:first').should('have.length', 1) // Apple only
cy.get('ul li:first-child').should('have.length', 2) // Apple and Carrot

Find the dropdown-menu and click it​

cy.get('.dropdown-menu').click()

Find 5 elements with the given data attribute​

Dedicated data-* attributes such as data-cy keep selectors stable when your styles or text change. See best practices for selecting elements.

cy.get('[data-cy=todo-item]').should('have.length', 5)

Find the first or nth element with .first() and .eq()​

Chaining .first() or .eq() onto cy.get() reads more clearly than a :first or :eq() selector.

cy.get('[data-cy=todo-item]').first().should('contain', 'Buy milk')
cy.get('[data-cy=todo-item]').eq(1).should('contain', 'Walk dog')

Find elements matching any of several selectors​

Separate selectors with commas to yield every element that matches any of them.

cy.get('input, textarea, select').should('have.length', 3)
cy.get('a[href*="questions"]').click()

Find the element with id that starts with "local-"​

cy.get('[id^=local-]')

Find the element with id that ends with "-remote"​

cy.get('[id$=-remote]')

Find the element with id that starts with "local-" and ends with "-remote"​

cy.get('[id^=local-][id$=-remote]')

Find the element with id that has characters used in CSS like ".", ":"​

cy.get('#id\\.\\.\\.1234') // escape the character with \\

Find an element by an ID built at runtime​

When the ID comes from a variable, escape it with CSS.escape() instead of adding backslashes by hand.

const userId = 'user:42'

cy.get(`#${CSS.escape(userId)}`).should('have.text', 'Jane')

cy.get() in the .within() command​

Since cy.get() is chained off of cy, it always looks for the selector within the entire document. The only exception is when used inside a .within() command.

cy.get('form').within(() => {
cy.get('input').type('Pamela') // Only yield inputs within form
cy.get('textarea').type('is a developer') // Only yield textareas within form
})

Get vs Find​

The cy.get command always starts its search from the cy.root element. In most cases, it is the document element, unless used inside the .within() command. The .find command starts its 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 #comparison
// 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
// so it finds div.feature only
.should('have.length', 1)
.and('have.class', 'feature')

Waiting for elements​

Wait for a list to finish loading​

cy.get() retries until the assertion chained to it passes, so it waits for all three items to appear.

cy.get('[data-cy=todo-item]').should('have.length', 3)

An assertion inside .then() runs only once. cy.get() waits only until at least one item exists, so this fails if the list is still filling in:

// Runs once: fails if the list is still loading
cy.get('[data-cy=todo-item]').then(($items) => {
expect($items).to.have.length(3)
})

Assert an element doesn't exist​

cy.get() retries a negative assertion too, until the element is gone.

cy.get('[data-cy=loading-spinner]').should('not.exist')

Options​

Wait longer for a slow element with timeout​

cy.get('[data-cy=search-results]', { timeout: 10000 }).should('be.visible')

Find elements inside shadow DOM with includeShadowDom​

cy.get('.shadow-button', { includeShadowDom: true }).click()

To search shadow DOM in every query, set the includeShadowDom configuration option instead.

Hide a query from the Command Log with log​

The get row is hidden, but the assertion still appears in the Command Log.

cy.get('[data-cy=toast]', { log: false }).should('be.visible')

Alias​

For a detailed explanation of aliasing, read more about aliasing here.

Get the aliased 'todos' elements​

cy.get('ul#todos').as('todos')

//...hack hack hack...

//later retrieve the todos
cy.get('@todos')

Get the aliased 'submitBtn' element​

beforeEach(() => {
cy.get('button[type=submit]').as('submitBtn')
})

it('disables on click', () => {
cy.get('@submitBtn').click()
cy.get('@submitBtn').should('be.disabled')
})

Get the aliased 'users' fixture​

beforeEach(() => {
cy.fixture('users.json').as('users')
})

it('shows the first user in the header', () => {
// access the array of users
cy.get('@users').then((users) => {
// get the first user
const user = users[0]

cy.get('header').contains(user.name)
})
})

Re-run an alias or capture a static value​

By default, an alias re-runs its queries each time you request it. Pass { type: 'static' } to .as() to keep the value from the moment you created the alias.

cy.get('[data-cy=total]').invoke('text').as('liveTotal')
cy.get('[data-cy=total]').invoke('text').as('startTotal', { type: 'static' })

cy.get('[data-cy=add-item]').click()

cy.get('@liveTotal').should('eq', '$5.00') // re-runs the queries
cy.get('@startTotal').should('eq', '$0.00') // value captured earlier

In the Command Log, the static alias is labeled (static) where it's created:

Command Log showing the liveTotal alias without a label and the startTotal alias labeled static, then each alias retrieved with cy.get and asserted to equal $5.00 and $0.00

Assert an aliased element no longer exists​

Because the alias re-runs its query, you can assert that the element is gone.

cy.get('[data-cy=toast]').as('toast')
cy.get('[data-cy=dismiss]').click()
cy.get('@toast').should('not.exist')

Get an aliased spy or stub​

cy.window().then((win) => {
cy.spy(win.console, 'error').as('consoleError')
})

cy.get('[data-cy=save]').click()
cy.get('@consoleError').should('not.have.been.called')

Get all aliased intercepts​

When using cy.intercept() with an alias, you can retrieve all intercepted requests for that alias by appending .all to the alias name. This returns an array of interception objects.

cy.intercept('GET', '/users').as('getUsers')

// trigger multiple requests
cy.visit('/users')
cy.visit('/users')

// yields an array of all interceptions for this alias
cy.get('@getUsers.all').then((interceptions) => {
expect(interceptions).to.have.length(2)
})

You can also retrieve a specific intercept by its 1-based numeric index. Without any suffix, cy.get('@alias') returns the most recent intercepted request.

cy.intercept('GET', '/users').as('getUsers')

cy.visit('/users')
cy.visit('/users')

// yields the first intercepted request
cy.get('@getUsers.1').its('response.statusCode').should('eq', 200)

// yields the second intercepted request
cy.get('@getUsers.2').its('response.statusCode').should('eq', 200)
caution

Index 0 is not valid — indices start at 1. These suffixes are not supported by cy.wait(). Use cy.get('@alias.all') instead of cy.wait('@alias.all').

TypeScript​

Type the yielded element or an aliased value​

Pass a type argument to type what cy.get() yields. For a selector, it's the element type. For an alias, it's the type of the aliased value.

cy.get<HTMLInputElement>('[data-cy=email]').then(($input) => {
// $input is typed as JQuery<HTMLInputElement>
expect($input[0].value).to.eq('[email protected]')
})

cy.wrap({ name: 'Jane' }).as('user')
cy.get<{ name: string }>('@user').its('name').should('eq', 'Jane')

Notes​

What a cy.get() timeout error looks like​

When no element matches before the timeout, cy.get() fails with an error like this one. The time in the message is the command's timeout: defaultCommandTimeout, or the timeout option when you pass one.

Timed out retrying after 4000ms: Expected to find element: `[data-cy=todo-item]`, but never found it.

cy.get() doesn't search inside iframes​

cy.get() searches the document of the application under test and doesn't descend into <iframe> elements. To query inside a same-origin iframe, see How do I test elements inside an iframe?.

Rules​

Requirements ​

  • cy.get() is chained off of cy. When chained off another command, it ignores that command's subject.

Assertions ​

Timeouts ​

  • cy.get() can time out waiting for the element(s) to exist in the DOM.
  • cy.get() can time out waiting for assertions you've added to pass.

Command Log​

Get an input and assert on the value

cy.get('input[name="firstName"]').should('have.value', 'Homer')

The commands above will display in the Command Log as:

Command Log showing a get command for the firstName input followed by a passing assertion that its value is Homer

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

DevTools console output for the get command, listing its selector, the yielded input element, and an element count of 1

History​

VersionChanges
15.17.0@-prefixed aliases are typed as Chainable<S> instead of Chainable<JQuery<HTMLElement>>
12.0.0Aliases re-run the queries leading up to them by default
5.2.0Added includeShadowDom option

See also​