Q13 of 48 · Cypress
How do you select elements in Cypress and what's the recommended selector strategy?
Short answer
Short answer: Use `cy.get(selector)` for CSS, `cy.contains(text)` for text, `cy.find()` to scope inside another element. Cypress recommends `data-test`, `data-cy`, or `data-testid` attributes — they're stable under refactor. Avoid CSS class names and XPath; both are coupled to implementation.
Detail
cy.get accepts any CSS selector. The framework also exposes cy.contains (find by visible text) and chained .find / .parent / .children for DOM traversal.
The selector hierarchy Cypress recommends, from best to worst:
data-test/data-cy/data-testid— explicit testing attributes the team controls. Stable across CSS rewrites and class renames.cy.get('[data-test=submit]').role/aria-label— accessible names. Tests double as accessibility audits.cy.get('button[aria-label="Submit"]')— though Cypress lacks a built-ingetByRole(Playwright/Testing Library do).- Text content —
cy.contains('Submit'). Brittle if copy changes; use sparingly. - CSS classes / IDs / nested selectors —
cy.get('.btn-primary > span'). Couples tests to implementation. Avoid. - XPath — requires a plugin and almost never the right answer in a Cypress project.
The team agreement is "every interactive element gets a data-test attribute." It's a small dev-time cost for a big test-stability win.
cy.contains is convenient but matches anywhere in the DOM by default. Scope it: cy.contains('[data-test=cart]', 'Apples') looks for "Apples" inside the cart only.
// EXAMPLE
selectors.cy.ts
// ✅ Recommended — stable testing attribute
cy.get('[data-test=submit-order]').click();
// ✅ Acceptable — accessible name
cy.get('button[aria-label="Submit order"]').click();
// ⚠️ Use sparingly — copy changes break the test
cy.contains('Submit order').click();
// ⚠️ Scope cy.contains to avoid matching elsewhere
cy.contains('[data-test=cart-row]', 'Apples').should('be.visible');
// ❌ Avoid — coupled to CSS implementation
cy.get('.btn.btn-primary > span.icon').click();
// Chained DOM traversal
cy.get('[data-test=cart]')
.find('[data-test=cart-row]')
.should('have.length', 3);