Cypress - Locators
Cypress - Modern Locators and Selector Strategies
Section titled “Cypress - Modern Locators and Selector Strategies”Cypress primarily uses CSS selectors to identify elements on a web page, which is generally fast and reliable. While Cypress can be extended to support XPath using plugins like @cypress/xpath, CSS selectors are the recommended default. Modern best practices also emphasize using test-specific attributes like data-cy or data-testid for more resilient selectors.
Let’s explore common CSS selector patterns with an example HTML structure:
<html><body> <div id="main-content"> <h1 class="title primary-heading">Welcome</h1> <form data-cy="login-form"> <input type="email" name="email" placeholder="Enter your email" id="email-input" /> <input type="password" name="password" class="input-field password-field" /> <button type="submit" data-cy="submit-button">Login</button> </form> <div class="user-info"> <p>Not logged in</p> </div> </div></body></html>Common CSS Selector Strategies
Section titled “Common CSS Selector Strategies”- By ID:
cy.get('#email-input')(Selects the element withid="email-input"). Tag name is optional:input#email-input. - By Class:
cy.get('.password-field')(Selects elements withclass="password-field"). Tag name can be used:input.password-field. - By Attribute:
cy.get('[name="email"]')(Selects elements withname="email"). Tag name can be used:input[name='email']. - By Test-Specific Attribute (Best Practice):
cy.get('[data-cy="submit-button"]')(Selects the element withdata-cy="submit-button"). This is highly recommended as it decouples tests from CSS or JS changes. - By Tag Name:
cy.get('button')(Selects all<button>elements. Use with caution, be specific). - Parent-Child Traversal:
cy.get('form[data-cy="login-form"] input[name="email"]')(Selects the email input within the login form). Or using Cypress commands:cy.get('[data-cy="login-form"]').find('input[name="email"]'). - Chaining Traversals:
cy.get('#main-content').children('.user-info').find('p')(Finds the paragraph within.user-infowhich is a child of#main-content).
Using cy.contains()
Section titled “Using cy.contains()”cy.contains() is useful for selecting elements based on their text content. It can take a selector as an optional first argument to narrow down the search.
// Finds any element containing 'Welcome'cy.contains('Welcome');
// Finds a button containing 'Login'cy.contains('button', 'Login');
// Finds an element with data-cy='submit-button' that contains 'Login'cy.contains('[data-cy="submit-button"]', 'Login');Selector Playground
Section titled “Selector Playground”Cypress Test Runner includes a ‘Selector Playground’ feature. This interactive tool helps you determine unique selectors for elements by simply clicking on them in your application preview. It often provides the best cy.get() command with an appropriate selector.
To use it:
- Open the Cypress Test Runner.
- Run a test or open your application via
cy.visit(). - Click the ‘target’ icon (Open Selector Playground) in the Test Runner header.
- Hover over and click on elements in your application preview.
- Cypress will suggest a selector in the
cy.get()field. You can copy this directly into your test code.
While the Selector Playground is helpful, always review its suggestions and consider if a more robust selector (like a data-cy attribute) is more appropriate for long-term test stability.
Using XPath (If Necessary)
Section titled “Using XPath (If Necessary)”If CSS selectors are not sufficient for a particular case (e.g., finding elements based on complex relationships or text content not easily handled by cy.contains()), you can use XPath via the @cypress/xpath plugin.
-
Install the plugin:
npm install -D @cypress/xpathoryarn add -D @cypress/xpath. -
Add
require('@cypress/xpath')to yourcypress/support/e2e.jsfile (orcypress/support/commands.jsif you use that structure).
Then you can use cy.xpath('//your/xpath/expression') in your tests.
Example: cy.xpath('//button[contains(text(), "Submit")]')
Further Reading: