From f9bec964cb815d54b51e3e7df5463b83a30ce3b5 Mon Sep 17 00:00:00 2001 From: Earl Co Date: Mon, 12 Oct 2026 07:32:26 +0200 Subject: [PATCH] Accessibility: compare checker results after each recheck (#1250) * Compare accessibility checks after document fixes * Assert both pre-fix title findings in comparison test --- crates/ui-egui/src/a11y_ui.rs | 26 ++++++++++++++++++++++++++ crates/ui-egui/tests/accessibility.rs | 3 +++ parity/acrobat-features.toml | 6 +++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/crates/ui-egui/src/a11y_ui.rs b/crates/ui-egui/src/a11y_ui.rs index 1e7ab215..c688c58f 100644 --- a/crates/ui-egui/src/a11y_ui.rs +++ b/crates/ui-egui/src/a11y_ui.rs @@ -45,6 +45,9 @@ impl Default for A11yOptions { #[derive(Clone, Debug, Default)] pub struct A11yState { pub report: Option<(DocId, Report)>, + /// The prior check of the same document with the same checker options. + pub previous: Option<(DocId, Report)>, + pub options: Option, /// Collapsed categories and expanded rules. pub collapsed: BTreeSet, pub expanded: BTreeSet, @@ -191,6 +194,26 @@ pub(crate) fn panel(ui: &mut egui::Ui, t: &Tokens, state: &mut A11yState, doc: D } }); }); + if let Some((_, previous)) = state.previous.as_ref().filter(|(d, _)| *d == doc) { + egui::CollapsingHeader::new(tl!("Compare")).default_open(true).show(ui, |ui| { + for status in [Status::Passed, Status::Failed, Status::Manual, Status::Skipped] { + ui.label(format!("{}: {} → {}", tl!(status.label()), previous.count(status), report.count(status))); + } + for current in &report.results { + let Some(prior) = previous.result(current.rule) else { continue }; + if prior.status != current.status || prior.findings.len() != current.findings.len() { + ui.label(format!( + "{}: {} ({}) → {} ({})", + tl!(current.rule.name()), + tl!(prior.status.label()), + prior.findings.len(), + tl!(current.status.label()), + current.findings.len() + )); + } + } + }); + } ui.add_space(6.0); for c in Category::ALL { let rules: Vec<_> = report.in_category(c).collect(); @@ -331,6 +354,9 @@ impl PdfCraftApp { r.findings.clear(); } let failed = report.count(Status::Failed); + self.a11y.previous = + if self.a11y.options.as_ref() == Some(&options) { self.a11y.report.take().filter(|(prior_id, _)| *prior_id == id) } else { None }; + self.a11y.options = Some(options); self.a11y.report = Some((id, report)); self.right = Some(RightPanel::Accessibility); self.notify(if failed == 0 { diff --git a/crates/ui-egui/tests/accessibility.rs b/crates/ui-egui/tests/accessibility.rs index f8c69c81..967dd6a5 100644 --- a/crates/ui-egui/tests/accessibility.rs +++ b/crates/ui-egui/tests/accessibility.rs @@ -61,10 +61,13 @@ fn checking_fixing_skipping_and_reporting() { h.get_by_label("Fix").click(); h.run_steps(3); assert_eq!(status(&h, Rule::Title), Status::Passed); + assert_eq!(h.state().a11y.previous.as_ref().unwrap().1.result(Rule::Title).unwrap().status, Status::Failed); assert!(matches!(h.state().dialog, Some(Dialog::Properties(_)))); assert_eq!(h.state().window_title, "notes — PdfCraft"); h.state_mut().dialog = None; h.run_steps(2); + h.get_by_label("Compare"); + h.get_by_label_contains("Title: Failed (2) → Passed (0)"); // Skip a rule; it stays skipped when checking again. right_click(&mut h, "Tagged PDF - Failed"); h.get_by_label("Skip Rule").click(); diff --git a/parity/acrobat-features.toml b/parity/acrobat-features.toml index e9144a04..e6e15139 100644 --- a/parity/acrobat-features.toml +++ b/parity/acrobat-features.toml @@ -8413,9 +8413,9 @@ tier = "P1" milestone = "M12" status = "shipped" commands = ["a11y.check"] -tools = ["accessibility_fix"] -evidence = ["crates/ui-egui/tests/accessibility.rs::checking_fixing_skipping_and_reporting", "crates/automation/tests/automation.rs::accessibility_check_report_and_fixes_through_tools"] -notes = "right-click a rule: Fix (language via Document Properties, title, tab order), Skip Rule (kept on Check Again), Explain, Check Again, Show Report, Options" +tools = ["accessibility_fix", "accessibility_review_record"] +evidence = ["crates/ui-egui/tests/accessibility.rs::checking_fixing_skipping_and_reporting", "crates/automation/tests/automation.rs::accessibility_check_report_and_fixes_through_tools", "crates/automation/tests/automation.rs::accessibility_review_record_compares_two_versions_without_changing_them"] +notes = "right-click a rule: Fix (language via Document Properties, title, tab order), Skip Rule (kept on Check Again), Explain, Check Again, Show Report, Options. The panel compares outcome counts and changed rules with the previous check of the same document and options; the headless review record compares two open revisions." [[feature]] id = "a11y.rule-permission-flag"