-
Notifications
You must be signed in to change notification settings - Fork 8.6k
[Scout][a11y] adding axe-core validation
#243953
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
7c9d88d
[Scout][a11y] adding axi-core validation
alexwizp 5827980
move tests
alexwizp c5cb35d
cleanup
alexwizp a005d43
cleanup
alexwizp d7ca82d
Changes from node scripts/lint_ts_projects --fix
kibanamachine d4e3d06
Changes from security: 3rd-party dependencies
kibanamachine 9c3f22f
update renovate + fix license_checker issue
alexwizp 3b309e8
Changes from node scripts/capture_oas_snapshot --include-path /api/…
kibanamachine 62cd34a
Merge branch 'main' into nov-24
alexwizp db38bcc
push some updates
alexwizp 4c1d959
Merge remote-tracking branch 'origin/main' into nov-24
alexwizp 959ce7c
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine 4c2f747
cleanup
alexwizp a61b9e6
add include option
alexwizp 8df570f
Merge remote-tracking branch 'origin/main' into nov-24
alexwizp 5c2c5a9
add test
alexwizp 9a6601d
Merge branch 'main' into nov-24
alexwizp 9a6ba55
Merge branch 'main' into nov-24
alexwizp 57916b8
Update index.ts
alexwizp 2273228
Merge branch 'main' into nov-24
alexwizp 550d758
cleanup
alexwizp 0b6a16a
Update src/platform/packages/shared/kbn-scout/src/playwright/utils/ax…
alexwizp 6ebed7b
Fix formatting of JSDoc comment in checkA11y method
alexwizp c47490d
Merge branch 'main' into nov-24
alexwizp a9933df
replace KibanaUrl -> page.url()
alexwizp 7bae0b1
add new require_include_in_check_a11y rule
alexwizp 38ec1b5
add a comment
alexwizp d93618a
Merge branch 'main' into nov-24
alexwizp File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
src/platform/packages/shared/kbn-scout/src/playwright/utils/axe.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the "Elastic License | ||
| * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
| * Public License v 1"; you may not use this file except in compliance with, at | ||
| * your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
| * License v3.0 only", or the "Server Side Public License, v 1". | ||
| */ | ||
|
|
||
| import type { Page } from '@playwright/test'; | ||
| import type { Result } from 'axe-core'; | ||
| import AxeBuilder from '@axe-core/playwright'; | ||
| import { AXE_OPTIONS, AXE_IMPACT_LEVELS } from '@kbn/axe-config'; | ||
|
|
||
| import type { KibanaUrl } from '../../..'; | ||
|
|
||
| export interface RunA11yScanOptions { | ||
| /** Optional CSS selectors to include in analysis */ | ||
| include?: string[]; | ||
| /** Optional CSS selectors to exclude from analysis */ | ||
| exclude?: string[]; | ||
| /** Timeout in ms for the scan (defaults 10000) */ | ||
| timeoutMs?: number; | ||
| } | ||
|
|
||
| const runA11yScan = async ( | ||
| page: Page, | ||
| { include = [], exclude = [], timeoutMs = 10000 }: RunA11yScanOptions = {} | ||
| ) => { | ||
| const builder = new AxeBuilder({ page }); | ||
| builder.options(AXE_OPTIONS); | ||
|
|
||
| if (include) { | ||
| for (const selector of include) { | ||
| builder.include(selector); | ||
| } | ||
| } | ||
|
|
||
| if (exclude) { | ||
| for (const selector of exclude) { | ||
| builder.exclude(selector); | ||
| } | ||
|
alexwizp marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| const analysisPromise = builder.analyze(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @alexwizp could you add a comment above the function to explain the logic behind it and the edge case when Promise might be rejected (and how it should be interpreted) |
||
| let timeoutId: ReturnType<typeof setTimeout> | undefined; | ||
|
|
||
| const result = await Promise.race([ | ||
| analysisPromise, | ||
| new Promise<never>((_, reject) => { | ||
| timeoutId = setTimeout( | ||
| () => reject(new Error(`Axe accessibility scan timed out after ${timeoutMs}ms`)), | ||
| timeoutMs | ||
| ); | ||
| }), | ||
| ]); | ||
|
|
||
| if (timeoutId) { | ||
| clearTimeout(timeoutId); | ||
| } | ||
|
|
||
| let violations: Result[] = result.violations; | ||
|
|
||
| if (AXE_IMPACT_LEVELS?.length) { | ||
| violations = violations.filter((v) => v.impact && AXE_IMPACT_LEVELS.includes(v.impact)); | ||
| } | ||
|
|
||
| return { violations }; | ||
| }; | ||
|
|
||
| export const checkA11y = async (page: Page, kbnUrl?: KibanaUrl, options?: RunA11yScanOptions) => { | ||
| const { violations } = await runA11yScan(page, options); | ||
|
|
||
| const formatA11yViolation = (v: Result): string => { | ||
| const nodesSection = v.nodes | ||
| .map((n, idx) => { | ||
| const selectors = n.target.join(', '); | ||
| const failure = n.failureSummary?.trim() || 'No failure summary provided'; | ||
| return ` ${idx + 1}. Selectors: ${selectors}\n Failure: ${failure}`; | ||
| }) | ||
| .join('\n'); | ||
|
|
||
| return [ | ||
| `\nAccessibility violation detected!\n`, | ||
| ` Rule: ${v.id}. Impact: (${v.impact ?? 'impact unknown'})`, | ||
| ` Description: ${v.description}`, | ||
| ` Help: ${v.help}. See more: ${v.helpUrl}`, | ||
| ` Page: ${kbnUrl}`, | ||
| ` Nodes:\n${nodesSection}`, | ||
| ] | ||
| .join('\n') | ||
| .trim(); | ||
| }; | ||
|
|
||
| return { | ||
| violations: violations.map((v) => formatA11yViolation(v)), | ||
| }; | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
src/platform/packages/shared/kbn-scout/test/scout/ui/tests/axe.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the "Elastic License | ||
| * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
| * Public License v 1"; you may not use this file except in compliance with, at | ||
| * your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
| * License v3.0 only", or the "Server Side Public License, v 1". | ||
| */ | ||
|
|
||
| import { test, expect } from '../../../../src/playwright'; | ||
|
|
||
| test.describe('runA11yScan', { tag: ['@svlSecurity', '@ess'] }, () => { | ||
| test('returns violations array (empty for basic accessible markup)', async ({ page }) => { | ||
| await page.setContent(` | ||
| <html lang="en"> | ||
| <head> | ||
| <title>AXE Core check for basic accessible markup</title> | ||
| </head> | ||
| <main> | ||
| <h1>AXE Core check for basic accessible markup</h1> | ||
| <button aria-label="Close dialog">X</button> | ||
| <form> | ||
| <label for="email">Email</label> | ||
| <input id="email" type="email" /> | ||
| </form> | ||
| </main> | ||
| </html> | ||
| `); | ||
|
|
||
| const { violations } = await page.checkA11y(); | ||
|
|
||
| expect(Array.isArray(violations)).toBe(true); | ||
|
|
||
| // Basic page should have no serious/critical violations | ||
| expect(violations).toHaveLength(0); | ||
| }); | ||
|
|
||
| test('returns violations related to the CSS "include" selector only', async ({ page }) => { | ||
| await page.setContent(` | ||
| <main> | ||
| <h1>AXE Core check for basic accessible markup</h1> | ||
| <form> | ||
| <label>Email</label> | ||
| <input id="email" type="email" /> | ||
| </form> | ||
| </main> | ||
| `); | ||
|
|
||
| const { violations } = await page.checkA11y({ include: ['form'] }); | ||
|
|
||
| expect(violations).toHaveLength(1); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,5 +35,6 @@ | |
| "@kbn/core-http-common", | ||
| "@kbn/streams-schema", | ||
| "@kbn/streamlang", | ||
| "@kbn/axe-config" | ||
| ] | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.