Repository navigation
harmonia template: axe-core checks the generated pages against WCAG 2.1 AA, red on serious/critical (#7645) - #7686
Merged
delchev merged 1 commit intoOct 5, 2026
Conversation
….1 AA, red on serious/critical (eclipse-dirigible#7645) The Harmonia templates carry ARIA where the component library put it, but nothing checked it: no axe-core, pa11y or Lighthouse anywhere, so every generated page was one template edit away from a regression no one saw. AccessibilityHarmoniaIT generates and publishes an intent application and scans its manage list, manage form, document page, read-only preview and Inbox with axe-core (Deque's Selenium binding, on the Chrome the Selenide ITs already drive), WCAG 2.1 A/AA rules, in both colour schemes. Every page's result and a count per impact go to target/failsafe-reports/axe/, which the IT jobs upload; a serious or critical violation fails it. It also asserts what axe cannot see: the status step indicator announces the active step, and the line dialog returns focus to the button that opened it. HarmoniaAccessibilityMarkupIT guards the rules on markup no intent application renders: a sortable header sorts through a button, every step trigger binds aria-current. Template fixes the first report and the issue's list surfaced: - the column-resize grip (a focusable role=separator) announced aria-valuenow only once focused - required from the start (critical); - the document's "your step" strip put muted text on its primary tint (4.32:1) - now foreground; - the perspective list sorted on a click on the <th> - a real button now, with aria-sort; - both status step indicators (document page, BPM task form) bind aria-current="step"; Harmonia marks the active step visually only. Reviewed, no change: inputs carry bound labels (the label rule finds nothing), Harmonia's dialog traps and returns focus itself, and the 194 role="presentation" are all on decorative svg icons, none on table markup. Not enforced: contrast against Harmonia 3.1.2's own --primary (white on it 3.67:1 light / 4.43:1 dark, it as dark-mode link text 4.26:1 - one token cannot pass both) - a node-level exemption, so every other contrast failure still fails the test; it is fixed in codbex/harmonia. The Playwright app-test runner (npm/test, published in @aerokit/sdk) gets the same check as an a11y flow with @axe-core/playwright (optional peer): report-only by default, APPTEST_A11Y=strict to fail. Verified: AccessibilityHarmoniaIT and HarmoniaAccessibilityMarkupIT green, red with the form labels' for= binding removed ([critical] label on #f_Name, #f_Email, #f_Vip); HarmoniaContractIT, HarmoniaListColumnsIT, HarmoniaHierarchyTreeTableIT, I18nKeyCoverageIT, HarmoniaTaskFormLayoutIT, ShellRuntimeVintageIT, IntentEmissionCoverageIT green; formatter:validate with the cache wiped. The npm a11y flow was syntax-checked, not run. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
| myFlow(manifest, entity, opts); | ||
| multilingualFlow(manifest, entity, opts); | ||
| shellFlow(manifest, entity, opts); | ||
| a11yFlow(manifest, entity, opts); |
| return false; | ||
| } | ||
| for (int channel = 1; channel < 7; channel += 2) { | ||
| int a = Integer.parseInt(hex.substring(channel, channel + 2), 16); |
| } | ||
| for (int channel = 1; channel < 7; channel += 2) { | ||
| int a = Integer.parseInt(hex.substring(channel, channel + 2), 16); | ||
| int b = Integer.parseInt(expected.substring(channel, channel + 2), 16); |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Cause
The Harmonia templates carry ARIA where the component library put it, but nothing checked it: there was no axe-core, pa11y or Lighthouse anywhere in
tests/or.github/. So every page the generator emits was one template edit away from an accessibility regression no one would see.Change
The check
AccessibilityHarmoniaIT(Selenide,uitag, so the nightly and masteruishards). It generates and publishes an intent application,AccessibilityHarmoniaIT/app.intent, with a record behind every page kind: a customer, an invoice with a line and a status, and a review task in the Inbox. It then scans with axe-core against the WCAG 2.1 A/AA rule tags (wcag2a,wcag2aa,wcag21a,wcag21aa):Every page is scanned in both colour schemes. The scheme is pinned, because Harmonia's default follows the OS and would differ between a developer's machine and CI, and the scan waits for the switch's colour transitions to finish.
summary.txtwith the counts per impact, goes totarget/failsafe-reports/axe/. The IT jobs already upload that folder on every outcome.seriousorcriticalviolation fails the test, naming the page, the rule and the elements.minor/moderatefindings are reported only.aria-current="step", and the line dialog returns focus to the button that opened it.It uses Deque's Selenium binding (
com.deque.html.axe-core:selenium), which runs the same axe-core engine and rules as@axe-core/playwright, on the Chrome the Selenide ITs already drive. The Playwright Java binding would have added a 194 MB driver bundle and a second browser stack totests-integrations. The binding's own oldselenium-javais excluded, because Selenide supplies Selenium.HarmoniaAccessibilityMarkupIT(static, untagged, so it's in the PR smoke gate) guards rules on markup no intent application renders: the perspective list view exists only for hand-authored models. A sortable header must sort through a button, and every step-indicator trigger must bindaria-current.The Playwright app-test runner (
npm/test, published as@aerokit/sdk/test) gets the same check as ana11yflow using@axe-core/playwright(an optional peer dependency in both package manifests). It scans each entity's list page and create form, attaches the JSON to the Playwright report, and is report-only by default;APPTEST_A11Y=strictmakes it fail, andoffskips it. This is the "report first, then red" rollout for downstream apps.Template fixes the first report and the issue's list surfaced
aria-required-attr: the column-resize grip (a focusablerole="separator") setaria-valuenowonly once focusedapp.jsannounces it when the grip is created; focus and every resize keep it currentcolor-contrast: the document's "your step" strip puttext-muted-foregroundon its primary tint (4.32:1)text-foreground<th>: not focusable, no sort state<button type="button">inside the header,:aria-sorton the cell (the manage list's shape):aria-current="... ? 'step' : null"Reviewed, no change needed:
labelrule finds nothing.role="presentation": all 194 uses (the issue counted 431) are on decorative<svg>icons, none on table markup.Not enforced, and why
Contrast against Harmonia 3.1.2's own
--primary. White on it is 3.67:1 in light mode and 4.43:1 in dark mode, and it as dark-mode link text is 4.26:1. In dark mode no single token can pass both uses, so this is fixed in codbex/harmonia, not per template. The exemption is per node: a contrast failure counts unless the primary colour (resolved in the page) is its foreground or background, so every other contrast failure still fails the test. The violations stay in the report. Overriding the palette inapplication-core/shell/css/app.cssis the alternative, but it would recolour every platform shell; I'll do it if reviewers prefer that.Verified
AccessibilityHarmoniaITgreen: 5 pages × 2 schemes, about 27 s.HarmoniaAccessibilityMarkupITgreen (2 tests).for=failed withform-light: [critical] label - Form elements must have labels (3 elements: [#f_Name], [#f_Email], [#f_Vip]), the same forform-dark. The template was restored byte-identical.HarmoniaContractIT(the changed markup passes the directive and class allowlist),HarmoniaListColumnsIT,HarmoniaHierarchyTreeTableIT,I18nKeyCoverageIT,HarmoniaTaskFormLayoutIT,ShellRuntimeVintageIT, andIntentEmissionCoverageIT(135 s, compiles and runs the generated output).mvn -T 1C formatter:validatewith the cache wiped, BUILD SUCCESS.Not verified / not in this PR
a11yflow was syntax-checked (node --check) only, not run against an instance.dirigible-io.github.iorepository. A follow-up PR there.Fixes #7645
🤖 Generated with Claude Code