feat(atomic-a11y): add OpenACR converter modules#7124
feat(atomic-a11y): add OpenACR converter modules#7124y-lakhdar wants to merge 39 commits intofeat/a11y-merge-shardsfrom
Conversation
- Add VitestA11yReporter class for collecting axe-core results during vitest runs - Add reporter-utils.ts with shard resolution, component extraction, error processing - Add axe-integration.ts with axe-core type guards and WCAG tag parsing - Add merge-shards.ts for combining sharded a11y reports - Add unit tests for reporter (9 tests) and merge-shards (3 tests) - Update index.ts with reporter exports - Add test and a11y:merge-shards scripts to package.json
- Add src/openacr/types.ts with OpenACR interfaces and conformance mappings - Add src/openacr/overrides.ts for loading override configuration - Add src/openacr/manual-audit.ts for manual audit baseline parsing and resolution - Add src/openacr/conformance.ts for multi-source conformance calculation - Add src/openacr/report-builder.ts for building OpenACR report structure - Add src/openacr/yaml-serializer.ts with hand-rolled YAML serializer (no deps) - Add src/reporter/json-to-openacr.ts as slim CLI orchestrator (137 lines) - Add unit tests for json-to-openacr (7 tests) - Update index.ts with OpenACR exports - Add a11y:vpat script to package.json
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 94a34f0b09
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d26e8a39e0
ℹ️ 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".
⛔ Snyk checks have failed. 1 issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
| @@ -0,0 +1 @@ | |||
| [] | |||
There was a problem hiding this comment.
The file as is doesn't seem super useful 😅
Should we fill it with sample data? Or just remove it? Or is it just there so that the reports folder is kept? If so we can just add a .gitkeep file instead.
There was a problem hiding this comment.
good point. this is something i forgot to fill. even tho it is explained in the readme. I will update the file and commit it. good catch
There was a problem hiding this comment.
The problem with this format is that it leaves no room for comments from the human auditor.
The VPAT report might ignore such remarks, but as engineers working on the project, we need to understand precisely why a criteria was given a status of fail, partial, or not-applicable by the human who did the manual audit, so that we can either challenge the conclusion or take remedial action.
If I put myself in the shoes of a QA working on a manual audit, I'd probably leave these kinds of remarks somewhere. If I can't leave them in the structured manual audit file, then I'd leave them in some kind of document somewhere. I personally think it would be much better to have the information live in the same place (in the repo), and be cleanly a consistently structured.
|
|
||
| const DEFAULT_REPORT_TITLE = 'Coveo Accessibility Conformance Report'; | ||
| const DEFAULT_REPORT_PRODUCT_NAME = 'Coveo Atomic'; | ||
| const DEFAULT_REPORT_PRODUCT_VERSION = '3.x.x'; |
There was a problem hiding this comment.
If we don't receive a specific, something is seriously wrong and we should probably not even bother producing the report.
I think that's how we should handle missing version; not with a default value.
| }, | ||
| success_criteria_level_aa: { | ||
| notes: | ||
| 'Conformance is based on automated Storybook + axe-core output, interactive keyboard/screen-reader testing, and pending manual validation.', |
There was a problem hiding this comment.
This is the exact same note as in success_criteria_level_a; consider storing it in a variable instead of duplicating it.
| export const DEFAULT_A11Y_REPORT_FILENAME = 'a11y-report.json'; | ||
| export const DEFAULT_WCAG_22_AA_CRITERIA_COUNT = 55; | ||
| export const BASELINE_FILE_PATTERN = | ||
| /^manual-audit-(?!example\.json$)(?!.*-violations)([\w-]+)\.json$/; |
There was a problem hiding this comment.
If you decide to remove the example file and use a .gitkeep instead, you can update the regex accordingly.
| "a11y:vpat": "pnpm build && node scripts/json-to-openacr.mjs && npx --yes @openacr/openacr output -f reports/openacr.yaml -o reports/vpat-2.5-coveo-atomic.md -t scripts/vpat-from-openacr.handlebars", | ||
| "a11y:merge-shards": "pnpm build && node scripts/merge-shards-cli.mjs" | ||
| }, | ||
| "dependencies": { |
There was a problem hiding this comment.
we also have yaml as a dependency in the create-atomic package, so we could put it in the root package.json instead and use catalog:
| }); | ||
| ``` | ||
|
|
||
| ```ts |
There was a problem hiding this comment.
Do we need this? We have pnpm a11y:merge-shards and pnpm a11y:vpat
If we don't then we could just remove mergeA11yShardReports and transformJsonToOpenAcr from index.ts.
Co-authored-by: Frederic Beaudoin <fbeaudoin@coveo.com>
|
Hey @y-lakhdar 👋 ✅ This PR does not need a changeset file — you don't have one currently, so it's perfect. This PR only affects |
TL;DR
Converts the
a11y-report.json(from the Vitest reporter) into OpenACR-compliant YAML — the machine-readable format behind VPAT 2.5 accessibility conformance reports.What it does
After the reporter (#7123) captures axe-core results and the shard merger (#7137) consolidates parallel runs, we need to translate that data into an industry-standard format. OpenACR is the format the U.S. GSA uses for machine-readable VPATs.
Conformance priority: override → manual audit → existing report → automated (axe-core)
Design decisions
Schema-aligned output types
The
OpenAcrReportandOpenAcrCriteriontypes match the official GSA OpenACR 0.1.0 JSON Schema exactly. No custom extensions are added to the YAML output — the@openacr/openacrCLI only reads official schema fields (num,components[].adherence.level,components[].adherence.notes), so anything extra would be dead data.Runtime validation of the generated YAML against the official schema is handled in #7164.
Options objects for conformance functions
resolveConformance()andbuildRemarks()use typed context objects (ConformanceContext,RemarksContext) instead of positional parameters. Both share the same base context (criterion, aggregate, manual aggregates, override), andbuildRemarksextends it with the resolved conformance and component lists.File organization
types.ts— Only type definitions and mapping constants. No functions.manual-audit.ts— Parsing, loading, and counting logic for manual audit baselines.conformance.ts— Conformance resolution priority chain and remarks generation.report-builder.ts— Assembles the full OpenACR structure.json-to-openacr.ts— Entry point that wires I/O together.How to review
json-to-openacr.tsconformance.tsresolveConformance()priority chain +buildRemarks()report-builder.tsmanual-audit.tsmanual-audit-*.jsonbaselines, worst-wins resolutionoverrides.tsa11y-overrides.jsonper-criterion exceptionstypes.tsTry it
Minimal run (automated data only)
If
reports/a11y-report.jsonexists (from the Vitest reporter), you can generate the OpenACR YAML immediately:node scripts/json-to-openacr.mjs # → writes reports/openacr.yamlIf the input report doesn't exist yet, the converter still runs — it produces a placeholder YAML with all 55 criteria set to
not-evaluated.Full loop (with manual audits + overrides)
1. Create a manual audit baseline in
a11y/reports/:Files must match
manual-audit-*.json(no-violationsin the name). Only entries with"status": "complete"are processed. Status values:pass,fail,partial,not-applicable.See
docs/manual-audit-guide.mdfor the full QA reference on manual baselines.2. (Optional) Add a conformance override in
a11y/:3. Run the converter:
You'll see output like:
Tests
Extracted to #7163 to keep this PR focused on implementation.
PR Chain (5 of 8)
KIT-5470