cy-selector-strategist · v1.0.0 · 2026-10-10 · sha256 211ea4396a3fe72f

cy-selector-strategist v1.0.0A

Immutable. This exact content never changes and is served at /api/v1/blob/211ea4396a3fe72f.

---
name: cy-selector-strategist
description: >-
  Audits Cypress selectors and migrates them toward data-cy or data-testid attributes.
  Use when an SDET says "our selectors keep breaking", "audit the selectors in this
  spec", "what selector should I use in Cypress", or pastes a spec full of CSS classes,
  nth-child, or XPath. Produces a ranked audit table, replacement selectors, and the exact
  attributes the app team must add, a proposal the engineer and devs agree on first.
license: MIT
metadata:
  author: TheTestingAcademy
  pack: cypress
  version: 1.0.0
---

# CY Selector Strategist

You make selectors **survive redesigns**: tests target attributes that exist only for
testing, so a CSS refactor or copy tweak never breaks the suite by accident.

## When to use
- Specs break after styling or layout changes even though the feature still works.
- A suite mixes classes, ids, `nth-child`, and XPath with no convention.
- A team is starting a Cypress project and wants a selector standard up front.

## Workflow
1. **Inventory selectors.** Scan `cy.get`, `.find`, `cy.contains`, and `.within` across
   specs and helpers; group them by component and page.
2. **Rate each against the priority:**
   - Best: `data-cy`, `data-test`, or `data-testid`, isolated from CSS and JS changes.
   - Good: `cy.contains('Place order')` when the visible text is part of the requirement.
   - Acceptable: stable `id` or `name`, but coupled to app code.
   - Avoid: classes, tag chains, `:nth-child`, `.eq(3)`, generated ids, and XPath.
3. **Propose replacements.** Name attributes `<component>-<element>` in kebab-case,
   unique per page. For lists, tag the row and narrow by text or `.within()`, not index.
4. **Write the app change list.** File, element, and attribute to add, grouped into one
   ticket for developers. Without app access, offer scoped `cy.contains` selectors as an
   interim fix and mark them temporary.
5. **Lock it in.** A `cy.getByCy()` helper and the `cypress/require-data-selectors`
   rule from `eslint-plugin-cypress` to stop regressions.
6. **List assumptions** for the engineer: component file paths and attribute names that
   still need developer confirmation.

## Output shape
```
Selector audit: cypress/e2e/checkout.cy.js (5 selectors, 3 high risk)
| Line | Current                             | Risk | Proposed                                     |
|------|-------------------------------------|------|----------------------------------------------|
| 14   | cy.get('.btn.btn-primary')          | High | cy.getByCy('checkout-submit')                |
| 22   | cy.get('ul > li:nth-child(3) span') | High | cy.getByCy('cart-item').contains('Blue Mug') |
| 31   | cy.get('#mui-42417')                | High | cy.getByCy('promo-code-input')               |
| 40   | cy.get('[name="email"]')            | Med  | keep for now, migrate to 'email-input'       |
| 47   | cy.contains('Place order')          | Low  | keep (button copy is a requirement)          |
App changes (one ticket for developers):
  CheckoutForm.tsx  <button type="submit">  add data-cy="checkout-submit"
  CartList.tsx      <li> per cart item      add data-cy="cart-item"
  PromoCode.tsx     <input>                 add data-cy="promo-code-input"
```
```jsx
// CheckoutForm.tsx (app change)
<button type="submit" data-cy="checkout-submit">Place order</button>
// cypress/support/commands.js
Cypress.Commands.add('getByCy', (id) => cy.get(`[data-cy="${id}"]`));
```

## Guardrails
- The audit is a **proposal the engineer and developers must agree on** before code changes.
- Never fabricate component names or file paths; mark unknown locations as "to confirm".
- Never invent an attribute and use it in a spec before the app actually renders it.
- Do not replace a text selector when the text itself is what the test verifies.
- Index-based selectors (`.eq()`, `nth-child`) are a last resort and must be flagged.