Accessibility: compare checker results after each recheck (#1250)

* Compare accessibility checks after document fixes

* Assert both pre-fix title findings in comparison test
This commit is contained in:
Earl Co 2026-10-12 07:32:26 +02:00 committed by GitHub
parent ef49fad861
commit f9bec964cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 3 deletions

View File

@ -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<Options>,
/// Collapsed categories and expanded rules.
pub collapsed: BTreeSet<Category>,
pub expanded: BTreeSet<Rule>,
@ -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 {

View File

@ -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();

View File

@ -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"