frontend-testing-strat…
Write unit and E2E tests for Grafana frontend code (React/TypeScript, any package or feature area) to the conventions this repo expects. Use when adding,…
Add reliable @grafana/e2e-selectors to interactive elements and key containers in the Grafana frontend. Use when adding e2e selectors, data-testid attributes, or test selectors to React components, when a file or component lacks selectors for testing, or when asked to make
$ npx -y skills add grafana/grafana --skill add-e2e-selectors --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/add-e2e-selectorsContext preview
The summary Claude sees to decide when to auto-load this skill.
Add reliable @grafana/e2e-selectors to interactive elements and key containers in the Grafana frontend. Use when adding e2e selectors, data-testid attributes, or test selectors to React components, when a file or component lacks selectors for testing, or when asked to make
name: add-e2e-selectors description: Add reliable @grafana/e2e-selectors to interactive elements and key containers in the Grafana frontend. Use when adding e2e selectors, data-testid attributes, or test selectors to React components, when a file or component lacks selectors for testing, or when asked to make elements testable. Also use when given a Grafana Pathfinder interactive guide (a guide directory or content.json) to audit or fix — it extracts the guide's reftarget selectors, identifies weak ones, and fixes them at the source in Grafana's JSX. Defines versioned selectors in the e2e-selectors package and wires data-testid into JSX. Accepts a file path, a list of targets, a directory, a pathfinder guide, or the current/open file.
Find interactive elements and key containers in the Grafana frontend that lack a stable test selector, define a **versioned** selector in the `@grafana/e2e-selectors` package, and wire it into the JSX as `data-testid`. This encodes the package's layout (`pages` vs `components`), its semver versioning scheme, and its strict reuse / never-delete rules so selectors are added correctly and don't break plugin end-to-end tests.
Interpret the argument to decide scope:
under `grafana-pathfinder-app/src/bundled-interactives/`) → see "Pathfinder guide as target".
Interactive guides drive Grafana's UI through CSS selectors (`reftarget` fields), so a weak selector breaks a guide the same way it breaks a test. Process the guide, then fix the weak targets at the source:
1. Extract targets: `grep -o '"reftarget": *"[^"]*"' <guide>/content.json` 2. Skip navigation targets — blocks with `"action": "navigate"` or URL-shaped values (starting with `/` or `http`). 3. Classify the rest. **Strong** (leave alone): `data-testid`/`data-cy`-based selectors and `grafana:` / `{grafana:...}` tokens. **Weak** (fix): text matching (`:contains`, `:text`), `aria-label` / `placeholder` / `title` attributes, `href`, bare-id compounds, and positional selectors (`:nth-of-type`, `:nth-child`, `:nth-match`). 4. Locate the JSX in this repo rendering each weak target (search by id, testid fragment, button text, aria-label). Some targets are not fixable here — external npm packages (`@grafana/plugin-ui`, `@grafana/prometheus`), Monaco editor internals, instance data (dashboard titles, datasource names) — report those instead of forcing a change. 5. Run Steps 1–6 below for the located elements. Updating the guide itself is out of scope — include a weak-selector → new-selector mapping in your summary so the guide author can adopt them.
All new selectors added in this run use a single version key: the current `main` version with `-pre` and build tags stripped.
grep -m1 '"version"' package.json
`13.2.0-pre` → use `'13.2.0'`. On a release branch, read main's copy instead (`git show main:package.json | grep -m1 '"version"'` — the local `main` ref can be stale, so fetch first if in doubt). If you know the change will be backported, use the lowest release version instead. Never hardcode — always compute it.
Target these in the file:
`textarea`, `a`, links, toggles/switches, checkboxes, radios, menu items, tabs, and the grafana-ui components that render them (`Button`, `IconButton`, `Input`, `Select`, `Switch`, `Checkbox`, `Tab`, etc.).
Skip any element that already has a `data-testid` or an existing selector — don't duplicate.
**Exception — a static testid on a repeated item.** A hardcoded literal inside a `.map()` (every card rendering the same `data-testid="data-source-card"`) identifies nothing: consumers are forced into text matching or positional hacks to pick one item, so it's as weak as no selector at all. Migrate it:
1. Define a parameterized selector keyed by a stable per-item value. 2. Preserve the legacy literal as the `MIN_GRAFANA_VERSION` entry so version-resolved consumers keep working against older Grafana, keeping the signature compatible:
dataSourceCard: {
'13.2.0': (name: string) => `data-testid data source card ${name}`,
[MIN_GRAFANA_VERSION]: (_name: string) => 'data-source-card',
},3. Update every in-repo usage of the old literal (jest and Playwright — grep `public/` and `e2e-playwright/`), and note in your summary that external code hardcoding the literal will need the same one-line update.
Inside a `.map()` / list render, **do not** put a selector on each inner interactive element — that bloats the DOM and degrades render performance. Instead attach **one parameterized container selector to the repeated row/wrapper**, keyed by a unique value. Tests then scope their queries within the matched row.
Canonical example — `public/app/features/browse-dashboards/components/DashboardsTree.tsx`:
<div
key={key}
{...rowProps}
data-testid={selectors.pages.BrowseDashboards.table.row(
'title' in dashboardItem ? dashboardItem.title : dashboardItem.uid
)}
>
{row.cells.map((cell) => /* inner cells get NO individual selector */)}
</div>Before defining anything, search the package for an existing selector covering this UI:
grep -rn "<keyword>" packages/grafan
The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
Repo: grafana/grafana
Write unit and E2E tests for Grafana frontend code (React/TypeScript, any package or feature area) to the conventions this repo expects. Use when adding,…
Write unit and E2E tests for Grafana visualization panels and viz utilities to the conventions this repo expects. Use when adding, backfilling, or reviewing…