Skip to main content

use_accessibility_check/
lib.rs

1#![forbid(unsafe_code)]
2//! Primitive accessibility issue filtering helpers.
3//!
4//! The crate stays generic and dependency-free so it can be reused across
5//! different UI or document models.
6//!
7//! # Examples
8//!
9//! ```rust
10//! use use_accessibility_check::{
11//!     AccessibilityIssue, AccessibilitySeverity, filter_by_severity, has_errors, has_warnings,
12//!     issue_count,
13//! };
14//!
15//! let issues = [
16//!     AccessibilityIssue {
17//!         code: String::from("contrast"),
18//!         message: String::from("Low contrast"),
19//!         severity: AccessibilitySeverity::Warning,
20//!     },
21//!     AccessibilityIssue {
22//!         code: String::from("label"),
23//!         message: String::from("Missing label"),
24//!         severity: AccessibilitySeverity::Error,
25//!     },
26//! ];
27//!
28//! assert!(has_warnings(&issues));
29//! assert!(has_errors(&issues));
30//! assert_eq!(filter_by_severity(&issues, AccessibilitySeverity::Warning).len(), 1);
31//! assert_eq!(issue_count(&issues), 2);
32//! ```
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum AccessibilitySeverity {
36    Info,
37    Warning,
38    Error,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct AccessibilityIssue {
43    pub code: String,
44    pub message: String,
45    pub severity: AccessibilitySeverity,
46}
47
48#[must_use]
49pub fn has_errors(issues: &[AccessibilityIssue]) -> bool {
50    issues
51        .iter()
52        .any(|issue| issue.severity == AccessibilitySeverity::Error)
53}
54
55#[must_use]
56pub fn has_warnings(issues: &[AccessibilityIssue]) -> bool {
57    issues
58        .iter()
59        .any(|issue| issue.severity == AccessibilitySeverity::Warning)
60}
61
62#[must_use]
63pub fn filter_by_severity(
64    issues: &[AccessibilityIssue],
65    severity: AccessibilitySeverity,
66) -> Vec<AccessibilityIssue> {
67    issues
68        .iter()
69        .filter(|issue| issue.severity == severity)
70        .cloned()
71        .collect()
72}
73
74#[must_use]
75pub fn issue_count(issues: &[AccessibilityIssue]) -> usize {
76    issues.len()
77}
78
79#[cfg(test)]
80mod tests {
81    use super::{
82        AccessibilityIssue, AccessibilitySeverity, filter_by_severity, has_errors, has_warnings,
83        issue_count,
84    };
85
86    #[test]
87    fn filters_issues_by_severity() {
88        let issues = [
89            AccessibilityIssue {
90                code: String::from("contrast"),
91                message: String::from("Low contrast"),
92                severity: AccessibilitySeverity::Warning,
93            },
94            AccessibilityIssue {
95                code: String::from("label"),
96                message: String::from("Missing label"),
97                severity: AccessibilitySeverity::Error,
98            },
99            AccessibilityIssue {
100                code: String::from("info"),
101                message: String::from("Informational"),
102                severity: AccessibilitySeverity::Info,
103            },
104        ];
105
106        assert!(has_warnings(&issues));
107        assert!(has_errors(&issues));
108        assert_eq!(
109            filter_by_severity(&issues, AccessibilitySeverity::Warning).len(),
110            1
111        );
112        assert_eq!(
113            filter_by_severity(&issues, AccessibilitySeverity::Error).len(),
114            1
115        );
116        assert_eq!(issue_count(&issues), 3);
117    }
118}