Explore's query history and query inspector both render through
TabbedContainer, whose close IconButton carries no test id — the only
handle is its tooltip, which becomes a translated aria-label. Two of the
three close labels are localized, so the control is unaddressable in a
non-English Grafana.
Adds components.TabbedContainer.closeButton and wires it onto the icon
button, which covers both panels at once. Also gives the query inspector's
TabbedContainer a testId so its container can scope the lookup, matching
the existing pages.Explore.QueryHistory.container.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* rename feature toggle to be in sync with open feature requirements
* feat: register grafana.dashboardGlobalVariables alongside legacy flag
Keep globalDashboardVariables registered so this is an add + consumer
switch, not a delete/rename in toggles_gen.json. Legacy removal is a
follow-up after rollout.
Co-authored-by: Cursor <cursoragent@cursor.com>
* test: cover variables API flag-off path via authorizer
Assert list/create return 403 with the feature-gate deny reason when
grafana.dashboardGlobalVariables is disabled, since storage is always
registered and enablement is enforced only in the authorizer.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Inherit parent subScope through regular folders so clicking a dashboard
nested under a ChildScope → Group still sets nav_scope_path in the URL.
Co-authored-by: Cursor <cursoragent@cursor.com>
* I18n: Add translations for the Alerting Watchers nav entry
Adds title and subtitle strings for the Watchers item added to the Alerting
section. Independent of the backend change: the nav reducers fall back to the
backend-supplied text when a nav ID has no translation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* I18n: Add tests for the nav item translation helpers
navBarItem-translations.ts had no test file, so adding cases to it lowered the
squad's coverage. Cover the new Watchers entries plus the unknown/undefined
fallbacks.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Chore: widen CODEOWNERS pattern for navBarItem-translations
The exact-path entry left the new test file unowned. Use a prefix glob, matching
the neighbouring entries in this section.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Dashboards: Make DashboardLayoutManager generic over its serialize return type
* return AnyDashboardLayout manager in getLayout
* trip comments
* Widen LayoutParent to match DashboardScene.getLayout and return NotebookLayoutManager in cloneLayout, duplicate
* Frontend: inject orgId into all SPA navigations via LocationService
Append ?orgId=<N> to every SPA navigation at the history layer in
LocationService (push/replace), gated on multi-org, so URLs stay
shareable across orgs. Wires the orgId getter at startup in app.ts and
covers the behaviour in LocationService tests.
Fixes#105040
Signed-off-by: QuentinBisson <quentin@giantswarm.io>
* refactor: fix test
Signed-off-by: QuentinBisson <quentin@giantswarm.io>
* prune suppressions
Signed-off-by: QuentinBisson <quentin@giantswarm.io>
* Frontend: keep current path for query/hash-only orgId navigations
appendOrgId resolved query-only ('?tab=x') and hash-only ('#h') strings
against a dummy base and always returned url.pathname, forcing relative
navigations to '/'. Omit pathname for those so the router keeps the
current path, and cover both cases in tests.
Signed-off-by: QuentinBisson <quentin@giantswarm.io>
* Frontend: register orgId getter before post-login redirect
---------
Signed-off-by: QuentinBisson <quentin@giantswarm.io>
Co-authored-by: Laura Benz <laura.benz@grafana.com>
Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
Co-authored-by: joshhunt <josh.hunt@grafana.com>
* docs(skills): add panel-testing-strategy skill
Add a Claude skill capturing how the DataViz squad wants unit and E2E tests
written for Grafana visualization panels and DataViz-owned code, distilled from
the April–July 2026 test-coverage effort, its PR review discussions, and the
DataViz + DataPro frontend testing strategy manifesto.
The skill encodes:
- the (inverted) testing diamond and how to pick the right layer
- assert-real-behavior conventions (no bare toBeDefined / not.toThrow)
- honest test descriptions that match their assertions
- verifying tests actually reach the target branch
- the repo's data-frame and panel-props builders, with common gotchas
- the canvas draw-call snapshot harness for chart panels
- E2E: selectors-first, an a11y check for every panel, and interaction snapshots
- no-AI-slop authoring guidance (AI speeds up a test you already intend)
- SDLC-phase expectations for when to add which tests
- 10 anti-flake rules, each mapped to a real stabilization PR
Wire it (and the existing add-e2e-selectors skill) into AGENTS.md under a new
"Project skills" pointer, and un-ignore the skill directory in .gitignore to
match the add-e2e-selectors convention.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Update .claude/skills/panel-testing-strategy/SKILL.md
Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>
* Update .claude/skills/panel-testing-strategy/SKILL.md
Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>
* Update .claude/skills/panel-testing-strategy/SKILL.md
Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>
* Update SKILL.md
* Update .claude/skills/panel-testing-strategy/SKILL.md
Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>
* Update .claude/skills/panel-testing-strategy/SKILL.md
Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>
* docs(skills): trim panel-testing-strategy rules checklist and exemplars
Make the rules checklist pure pointers into the sections above instead of
restating every rule, and drop the two exemplar bullets already cited inline
(panel-props builder in Step 1, canvas harness in Step 4). Removes duplicated
maintenance surface so a rule change no longer has to be edited in two places.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): tighten panel-testing-strategy description
Trim the frontmatter description from ~184 to ~124 tokens by dropping the
redundant "Encodes ..." summary sentence (that content is in the body) and
thinning the panel/component enumerations, while keeping every distinctive
trigger phrase. The description is loaded into every session's skill listing,
so this is an always-on saving regardless of whether the skill is invoked.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): correct canvas harness example and waitFor idiom
The Step 4 import example named createGrafanaUiMeasureTextJestMock but
attributed it to TimeSeriesPanel.canvasTestUtils.tsx, which actually imports
applyDefaultUPlotAxisMeasureTextMock. They are two different helpers: the
harness file imports applyDefaultUPlotAxisMeasureTextMock / installCanvasPath2DShim /
removeCanvasTransforms, while each *.canvas.test.tsx mocks
@grafana/ui/src/utils/measureText via createGrafanaUiMeasureTextJestMock in a
jest.mock factory. Show both halves so the example matches the exemplar.
Also fix the renderer-ready wait: waitFor(() => uPlotInstance?.status === 1)
never retries because a falsy return does not throw. Use
waitFor(() => expect(uPlotInstance?.status).toBe(1)), consistent with
anti-flake rule #4.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* build: make the .claude skill un-ignore actually take effect
!.claude/skills/panel-testing-strategy could not re-include files because its
parent .claude/ was excluded as a directory and git never descends into an
excluded dir, so new files in the skill dir still required a force-add. Ignore
directory contents with /* and re-include each parent step by step so the two
tracked skill dirs work without -f, while the rest of .claude/ stays ignored.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): prefer jest.mocked over as jest.MockedFunction casts
Add Step 3 guidance to type mocked functions/modules with jest.mocked(fn)
rather than `fn as jest.MockedFunction<typeof fn>`. jest.mocked is the
type-safe repo convention (256 test files use it vs 52 using the cast) and
avoids a common review nit, so agent-generated tests should follow it. Also
note it in the rules-checklist Step 3 pointer.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(codeowners): assign panel-testing-strategy skill to dataviz-squad
The .claude/skills/panel-testing-strategy/ dir had no CODEOWNERS entry (no
global * owner exists), so it had no owner and review routing. Assign it to
@grafana/dataviz-squad, who maintain the skill's conventions.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): scope skill pointers to directory-level AGENTS.md
Move the panel-testing-strategy and add-e2e-selectors pointers out of the
root AGENTS.md, where they cost tokens on every agent session repo-wide, and
into directory-scoped AGENTS.md files that only load when working in the
relevant frontend trees:
- public/app/plugins/panel/
- public/app/features/
- packages/grafana-ui/
The pointers only advertise the skills and nudge their use in-tree; each
skill's own trigger description (already in every session's skills manifest)
decides when it actually applies, so the AGENTS.md files avoid any ownership
lookup and do not duplicate the CODEOWNERS mapping.
This follows the directory-scoped context recommendation for large codebases
and avoids adding frontend-specific guidance to the repo-wide default, keeping
context lean for backend work and for contributors without a large LLM budget.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(skills): satisfy codeowners + prettier for un-ignored skill files
The .gitignore fix in this branch makes .claude/skills/add-e2e-selectors/
genuinely tracked for the first time, which exposed two CI checks that had
never seen the file:
- codeowners-validator flagged add-e2e-selectors/SKILL.md and the new
public/app/features/AGENTS.md as not-owned. Assign the e2e-selectors skill
to @grafana/grafana-frontend-platform (owns the e2e-selectors package) and
the features agent guide to @grafana/dataviz-squad.
- prettier flagged emphasis style in add-e2e-selectors/SKILL.md; normalize
*text* to _text_.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): add rule against circular test expectations
Extend Principle 2 of panel-testing-strategy: expected values must be
frozen literals, never derived from the code under test, a collaborator
it calls internally, or a copy of the production formula (comparing a
value to itself asserts nothing). Promote mutate-then-confirm-red from a
Verify step to a first-class habit.
Prompted by review feedback on geomap test coverage (#129607).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): require regression tests to fail on main
A test accompanying a bug fix must fail in the absence of the fix and
pass in its presence — otherwise it pins nothing and won't catch the
regression coming back. Spell out the check (revert the fix → red,
restore → green) and reference it from the SDLC checklist item.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): drop squad reference from skill pointers
An agent reading the AGENTS.md pointer has no way to know who the
"DataViz squad" is, so phrase the panel-testing-strategy pointer by what
it does — how panel/visualization tests should be written — instead of
who wants them. Applies to the three directory-level AGENTS.md files.
Addresses review feedback from @joshhunt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): phrase skill by what it does, not who owns it
Drop the "DataViz squad" framing from the skill description and intro so
an agent decides relevance by the work (writing/reviewing viz tests),
not by knowing who the squad is. Keeps the coverage-gate fact, reworded
to reference the codeowner paths rather than the team.
The one remaining slug is the literal argument to
`test:coverage:by-codeowner`, left as-is so the command still runs.
Addresses review feedback from @joshhunt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): drop the run-tests-by-codeowner recommendation
Remove the `test:coverage:by-codeowner` Verify step and its checklist
entry — the codeowner coverage gate runs in CI and isn't something an
agent needs to run locally.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): prettier-format add-e2e-selectors SKILL.md
Un-ignoring .claude/skills brings its files under the repo prettier:check.
main's copy of the add-e2e-selectors skill predates that gate and wasn't
formatted, so the branch-merged-with-main lint failed. Run Prettier on it
(emphasis markers + list-item indentation only).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(skills): prefer deletion over inflation
Add a Step 2 rule that deleting a redundant assertion (e.g. a toBeDefined()
prelude before a concrete check) or a duplicate test is a preferred fix over
inflating a weak assertion into a contrived value check.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Update .claude/skills/panel-testing-strategy/SKILL.md
Co-authored-by: Jesse David Peterson <jesdavpet@users.noreply.github.com>
* Update .claude/skills/panel-testing-strategy/SKILL.md
Co-authored-by: Jesse David Peterson <jesdavpet@users.noreply.github.com>
* Update .claude/skills/panel-testing-strategy/SKILL.md
Co-authored-by: Jesse David Peterson <jesdavpet@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>
Co-authored-by: Jesse David Peterson <jesdavpet@users.noreply.github.com>