From 1a2e61dab55adf6cff1979d16692ca8aa2ac715e Mon Sep 17 00:00:00 2001 From: Timur Olzhabayev Date: Wed, 29 Apr 2026 12:24:50 +0200 Subject: [PATCH 1/2] docs(plugin-e2e): document accessibility testing with Axe Adds a "Test for accessibility violations" section to the panel plugin testing guide covering the new scanForA11yViolations fixture and toHaveNoA11yViolations matcher introduced in #2462, and adds the accessibility capability to the e2e overview feature list. --- docusaurus/docs/e2e-test-a-plugin/index.md | 1 + .../e2e-test-a-plugin/test-a-panel-plugin.md | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/docusaurus/docs/e2e-test-a-plugin/index.md b/docusaurus/docs/e2e-test-a-plugin/index.md index 8b48ededbc..dc3397ac46 100644 --- a/docusaurus/docs/e2e-test-a-plugin/index.md +++ b/docusaurus/docs/e2e-test-a-plugin/index.md @@ -22,6 +22,7 @@ The `@grafana/plugin-e2e` tool offers a consistent way to interact with the Graf - **Predefined fixtures:** Offers a set of predefined fixtures that are tailored for Grafana plugin testing. - **Custom models:** Provides custom models that represent pages and components in Grafana, simplifying maintenance and creating reusable code to avoid repetition. - **Expect matchers:** Includes a range of expect matchers that are specialized for Grafana plugin assertions, helping you validate plugin behavior more effectively. +- **Accessibility testing:** Integrates with [Axe](https://www.deque.com/axe/) to run configurable accessibility scans inside your tests, with default rules aligned with Grafana's [WCAG 2.1 AA](https://www.w3.org/TR/WCAG21/) target. - **Integration with Playwright:** Seamlessly integrates with the Playwright testing framework, leveraging its powerful browser automation capabilities. ## End-to-end testing guides diff --git a/docusaurus/docs/e2e-test-a-plugin/test-a-panel-plugin.md b/docusaurus/docs/e2e-test-a-plugin/test-a-panel-plugin.md index 38a1e3d9de..c575d1390d 100644 --- a/docusaurus/docs/e2e-test-a-plugin/test-a-panel-plugin.md +++ b/docusaurus/docs/e2e-test-a-plugin/test-a-panel-plugin.md @@ -186,3 +186,60 @@ test('should display dropdown with two values when two frames are passed to the await expect(panelEditPage.getByTestIdOrAriaLabel(selectors.components.Select.option)).toHaveText(['a', 'b']); }); ``` + +## Test for accessibility violations + +`@grafana/plugin-e2e` ships with an [Axe](https://www.deque.com/axe/)-powered `scanForA11yViolations` fixture and a `toHaveNoA11yViolations` matcher so you can catch accessibility regressions in your panel as part of your end-to-end suite. By default the scan runs the WCAG 2.0 and 2.1 A and AA rule sets, which match Grafana's [WCAG 2.1 AA](https://www.w3.org/TR/WCAG21/) target. + +:::note +The accessibility scanning APIs are currently `@alpha` — the surface may change before becoming stable. Feedback is welcome on [GitHub](https://github.com/grafana/plugin-tools/issues). +::: + +The following test renders a panel from a provisioned dashboard and asserts that there are no accessibility violations on the page: + +```ts +test('panel has no accessibility violations', async ({ + gotoDashboardPage, + readProvisionedDashboard, + scanForA11yViolations, +}) => { + const dashboard = await readProvisionedDashboard({ fileName: 'my-panel-dashboard.json' }); + const dashboardPage = await gotoDashboardPage({ ...dashboard }); + await expect(dashboardPage.getPanelByTitle('My panel').locator).toBeVisible(); + + const report = await scanForA11yViolations(); + expect(report).toHaveNoA11yViolations(); +}); +``` + +When violations are found, `toHaveNoA11yViolations` prints each rule, its impact, and the affected DOM nodes, and the full Axe report is attached to the Playwright test result as a JSON artifact. + +### Scope a scan to your panel + +Pass `include` or `exclude` to limit the scan to a CSS selector (or array of selectors). This is useful when you only want to assert on your own panel and not the surrounding Grafana chrome: + +```ts +const report = await scanForA11yViolations({ + include: '[data-testid="data-testid panel content"]', +}); +expect(report).toHaveNoA11yViolations(); +``` + +You can also pass through any [axe-core run options](https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#options-parameter) — for example, to run a single rule: + +```ts +const report = await scanForA11yViolations({ + options: { runOnly: ['color-contrast'] }, +}); +``` + +### Tune the assertion + +`toHaveNoA11yViolations` accepts a `threshold` (the maximum number of violations to allow) and `ignoredRules` (axe rule IDs to skip when counting violations). This is helpful when adopting accessibility testing on an existing plugin and you want to track new regressions without fixing every pre-existing issue up front: + +```ts +expect(report).toHaveNoA11yViolations({ + threshold: 2, + ignoredRules: ['color-contrast'], +}); +``` From 0ebf9a1c420274c5320784a75d22f920526d5e34 Mon Sep 17 00:00:00 2001 From: Timur Olzhabayev Date: Wed, 29 Apr 2026 12:34:39 +0200 Subject: [PATCH 2/2] docs(plugin-e2e): address review feedback on a11y section - Note that @axe-core/playwright is an optional peer dep that must be installed - Switch the include example to a plugin-author-owned data-testid so the snippet is meaningful in a plugin dev guide and avoids exposing Grafana's internal selector convention - Tighten the @alpha note to present simple --- .../docs/e2e-test-a-plugin/test-a-panel-plugin.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docusaurus/docs/e2e-test-a-plugin/test-a-panel-plugin.md b/docusaurus/docs/e2e-test-a-plugin/test-a-panel-plugin.md index c575d1390d..0c75ff7683 100644 --- a/docusaurus/docs/e2e-test-a-plugin/test-a-panel-plugin.md +++ b/docusaurus/docs/e2e-test-a-plugin/test-a-panel-plugin.md @@ -191,8 +191,14 @@ test('should display dropdown with two values when two frames are passed to the `@grafana/plugin-e2e` ships with an [Axe](https://www.deque.com/axe/)-powered `scanForA11yViolations` fixture and a `toHaveNoA11yViolations` matcher so you can catch accessibility regressions in your panel as part of your end-to-end suite. By default the scan runs the WCAG 2.0 and 2.1 A and AA rule sets, which match Grafana's [WCAG 2.1 AA](https://www.w3.org/TR/WCAG21/) target. +`@axe-core/playwright` is an optional peer dependency, so install it alongside `@grafana/plugin-e2e` to use these APIs: + +```bash +npm install --save-dev @axe-core/playwright +``` + :::note -The accessibility scanning APIs are currently `@alpha` — the surface may change before becoming stable. Feedback is welcome on [GitHub](https://github.com/grafana/plugin-tools/issues). +The accessibility scanning APIs are `@alpha`. The surface may change before it becomes stable. Feedback is welcome on [GitHub](https://github.com/grafana/plugin-tools/issues). ::: The following test renders a panel from a provisioned dashboard and asserts that there are no accessibility violations on the page: @@ -216,11 +222,11 @@ When violations are found, `toHaveNoA11yViolations` prints each rule, its impact ### Scope a scan to your panel -Pass `include` or `exclude` to limit the scan to a CSS selector (or array of selectors). This is useful when you only want to assert on your own panel and not the surrounding Grafana chrome: +Pass `include` or `exclude` to limit the scan to a CSS selector (or array of selectors). This is useful when you only want to assert on the markup your plugin owns rather than the surrounding Grafana chrome. Add a `data-testid` to your panel's root element and target it from the test: ```ts const report = await scanForA11yViolations({ - include: '[data-testid="data-testid panel content"]', + include: '[data-testid="my-panel-root"]', }); expect(report).toHaveNoA11yViolations(); ```