fix(atomic-a11y): resolve criterion conformance from axe-core results#7686
fix(atomic-a11y): resolve criterion conformance from axe-core results#7686y-lakhdar wants to merge 2 commits into
Conversation
KIT-5756 The a11y reporter now tracks per-criterion violations and passes separately, resolving conformance directly in a11y-report.json instead of deferring to the OpenACR pipeline. Changes: - Add criteriaViolated/criteriaPassed to component automated results - Replace affectedComponents with coveredComponents/violatingComponents on criterion entries - Resolve conformance in report-builder (violations -> doesNotSupport, passes -> supports, partial -> partiallySupports) - Summary counters now reflect resolved conformance values - Merge-shards re-resolves conformance post-merge - Simplified OpenACR buildCriterionAggregates to read directly from report criterion fields
|
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9b6b3edaad
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| // No violations — check if any component has an explicit pass for this criterion | ||
| // (not just incomplete/inapplicable coverage) | ||
| return 'supports'; |
There was a problem hiding this comment.
Require explicit passes before reporting supports
For a criterion that appears only via axeResults.incomplete or axeResults.inapplicable, collectCriteria adds it to criteriaCovered but not criteriaPassed; this resolver never reads criteriaPassed, so it reports supports whenever there are no violations. That contradicts the intended notEvaluated case and inflates summaries/OpenACR for rules Axe could not actually pass; please require at least one explicit pass before returning supports.
Useful? React with 👍 / 👎.
|
Important Testing in progress…🟢 UI Tests: 367 tests unchanged |
|
Tip All tests passed and all changes approved!🟢 UI Tests: 367 tests unchanged |
@coveo/atomic
@coveo/atomic-hosted-page
@coveo/atomic-legacy
@coveo/atomic-react
@coveo/auth
@coveo/bueno
@coveo/create-atomic
@coveo/create-atomic-component
@coveo/create-atomic-component-project
@coveo/create-atomic-result-component
@coveo/create-atomic-rollup-plugin
@coveo/headless
@coveo/headless-react
@coveo/shopify
commit: |
There was a problem hiding this comment.
Pull request overview
Fixes the a11y reporter so that WCAG criterion conformance is resolved at report-build time (and during shard merge) from per-criterion violation vs. pass tracking, instead of being deferred and always emitted as notEvaluated. Per-component automated results now carry criteriaViolated and criteriaPassed sets, and the criterion-level shape replaces the ambiguous affectedComponents with explicit coveredComponents / violatingComponents. The OpenACR aggregate builder is simplified to read straight from the merged criterion data.
Changes:
- Extend
A11yAutomatedResultsandComponentAccumulatorwithcriteriaViolated/criteriaPassed; haveVitestA11yReporter.collectCriteriaroute axe buckets into them. - Replace
A11yCriterionReport.affectedComponentswithcoveredComponents+violatingComponents, resolve conformance inreport-builder.tsandmerge-shards.ts, and populatesummarycounts accordingly. - Simplify OpenACR
buildCriterionAggregatesto derive aggregates directly from criterion-level data, and update tests accordingly.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/atomic-a11y/src/shared/types.ts | Adds criteriaViolated/criteriaPassed and renames affectedComponents to coveredComponents/violatingComponents. |
| packages/atomic-a11y/src/reporter/reporter-utils.ts | Adds violated/passed sets to the component accumulator. |
| packages/atomic-a11y/src/reporter/vitest-a11y-reporter.ts | Tags collected criteria as violated or passed and seeds the new sets. |
| packages/atomic-a11y/src/reporter/report-builder.ts | Tracks covered/violating components per criterion and resolves automated conformance. |
| packages/atomic-a11y/src/reporter/merge-shards.ts | Merges new component sets and re-resolves criterion conformance after merge. |
| packages/atomic-a11y/src/reporter/summary.ts | Computes supports/partiallySupports/doesNotSupport/notApplicable from criterion conformance. |
| packages/atomic-a11y/src/openacr/report-builder.ts | Builds aggregates directly from criterion.coveredComponents / violatingComponents. |
| packages/atomic-a11y/src/tests/merge-shards.test.ts | Updates fixtures for the new shape and asserts supports conformance. |
| packages/atomic-a11y/test/interactive-reporting.test.ts | Updates fixtures and assertions to the renamed fields. |
| function resolveAutomatedConformance( | ||
| criterion: A11yCriterionReport | ||
| ): A11yCriterionReport['conformance'] { | ||
| const coveredCount = criterion.coveredComponents.length; | ||
| if (coveredCount === 0) { | ||
| return 'notEvaluated'; | ||
| } | ||
|
|
||
| const violatingCount = criterion.violatingComponents.length; | ||
| if (violatingCount >= coveredCount) { | ||
| return 'doesNotSupport'; | ||
| } | ||
| if (violatingCount > 0) { | ||
| return 'partiallySupports'; | ||
| } | ||
|
|
||
| // No violations — check if any component has an explicit pass for this criterion | ||
| // (not just incomplete/inapplicable coverage) | ||
| return 'supports'; | ||
| } |
|
|
||
| describe('interactive report aggregation', () => { | ||
| it('does not duplicate affected components covered by automated and interactive results', () => { | ||
| it('does not duplicate covered components covered by automated and interactive results', () => { |
Problem
The a11y reporter marked all WCAG criteria as
notEvaluatedina11y-report.json— even when axe-core clearly detected violations or clean passes. Two bugs in the downstream OpenACR pipeline made things worse:buildCriterionAggregates()treatedaffectedComponentsas the "violating" set, but this field actually contained all components with coverage (passes included) — so every component was incorrectly flagged as violating.a11y-report.jsonon disk, producing placeholdernot-evaluatedfor every criterion.Solution
Resolve conformance directly in the reporter using per-criterion violation/pass tracking:
doesNotSupportpartiallySupportssupportsnotEvaluatedDesign decisions
incomplete= no conformance signal — contributes to coverage but doesn't resolve to pass or failsupports— even for criteria with known limited automated coverage (e.g., 2.1.1 Keyboard). Manual/interactive overrides correct laterhttps://coveord.atlassian.net/browse/KIT-5756