From e61aa578274a173fbe987ee924fd87c67fcefe08 Mon Sep 17 00:00:00 2001 From: Emiliyan Gospodinov Date: Sun, 17 Mar 2024 20:57:29 +0100 Subject: [PATCH] add validation for missing `alt` attribute on `` and `` tags. --- RULES.md | 1 + .../src/engine/rules/techniques.rs | 2 + .../src/engine/rules/wcag_rule_map.rs | 78 +++++++++++++------ accessibility-rs/tests/unit/area.rs | 42 ++++++++++ accessibility-rs/tests/unit/mod.rs | 1 + 5 files changed, 101 insertions(+), 23 deletions(-) create mode 100644 accessibility-rs/tests/unit/area.rs diff --git a/RULES.md b/RULES.md index 7731e9d..736522d 100644 --- a/RULES.md +++ b/RULES.md @@ -8,6 +8,7 @@ List of [WCAG2.1 techniques](https://www.w3.org/TR/WCAG21/) and whether or not w | -------------------------------------------------- | ---------------------------------------------------------------------------- | ----- | ----- | --------------- | -------- | | [G18](https://www.w3.org/TR/WCAG20-TECHS/G18.html) | element has insufficient contrast at this conformance level | AAA | error | | | | [H2](https://www.w3.org/TR/WCAG20-TECHS/H2.html) | img element in link has alt text that duplicates the text content of link | A-AAA | error | EG | ✅ | +| [H24](https://www.w3.org/TR/WCAG20-TECHS/H24.html) | Image map and areas must have alt texts. | A-AAA | error | ImageMapNoAlt | ✅ | [H25](https://www.w3.org/TR/WCAG20-TECHS/H25.html) | empty titles | A-AAA | error | | ✅ | | [H30](https://www.w3.org/TR/WCAG20-TECHS/H30.html) | text alternative img | A-AAA | error | | ✅ | | [H32](https://www.w3.org/TR/WCAG20-TECHS/H32.html) | missing form submit button | A-AAA | error | | ✅ | diff --git a/accessibility-rs/src/engine/rules/techniques.rs b/accessibility-rs/src/engine/rules/techniques.rs index fa224b0..877bed8 100644 --- a/accessibility-rs/src/engine/rules/techniques.rs +++ b/accessibility-rs/src/engine/rules/techniques.rs @@ -5,6 +5,8 @@ use strum_macros::IntoStaticStr; pub enum Techniques { /// H2, + /// + H24, /// H25, /// diff --git a/accessibility-rs/src/engine/rules/wcag_rule_map.rs b/accessibility-rs/src/engine/rules/wcag_rule_map.rs index 82ea7d4..dcf21ab 100644 --- a/accessibility-rs/src/engine/rules/wcag_rule_map.rs +++ b/accessibility-rs/src/engine/rules/wcag_rule_map.rs @@ -114,22 +114,22 @@ lazy_static! { "h1", "h2", "h3", - "h4", - "h5", - "h6", - "a", - "button", - "p", - "img", - "span", - "div", - "li", - "ol", - "td", - "th", - "tr", - "textarea", - "select", + "h4", + "h5", + "h6", + "a", + "button", + "p", + "img", + "span", + "div", + "li", + "ol", + "td", + "th", + "tr", + "textarea", + "select", "input"].contains(&element.value().name()) { let style = accessibility_tree::style::cascade::style_for_element_ref( &element, @@ -161,13 +161,13 @@ lazy_static! { if contrast_ratio <= min_contrast { let message = t!( - &get_message_i18n_str_raw( - &Guideline::Distinguishable, - "", - "3_G18_or_G145.Fail", - ""), - locale = auditor.locale, - required = min_contrast.to_string(), + &get_message_i18n_str_raw( + &Guideline::Distinguishable, + "", + "3_G18_or_G145.Fail", + ""), + locale = auditor.locale, + required = min_contrast.to_string(), value = contrast_ratio.to_string()); validation_errors.push(Validation::new_custom_issue(false, "", message).into()) @@ -529,6 +529,38 @@ lazy_static! { Validation::new(valid, "", elements, Default::default()).into() }), ])), + ("area",Vec::from([ + Rule::new(Techniques::H24.into(), IssueType::Error, Principle::Perceivable, Guideline::TextAlternatives, "1", |nodes,_auditor| { + let mut valid = true; + let mut elements = Vec::new(); + + for ele in nodes { + let ele = ele.0; + if !has_alt_prop(ele) { + valid = false; + elements.push(get_unique_selector(&ele)); + } + } + + Validation::new(valid, "ImageMapAreaNoAlt", elements, Default::default()).into() + }) + ])), + ("map",Vec::from([ + Rule::new(Techniques::H24.into(), IssueType::Error, Principle::Perceivable, Guideline::TextAlternatives, "1", |nodes,_auditor|{ + let mut valid = true; + let mut elements = Vec::new(); + + for ele in nodes{ + let ele = ele.0; + if !has_alt_prop(ele){ + valid = false; + elements.push(get_unique_selector(&ele)); + } + } + + Validation::new(valid,"ImageMapNoAlt",elements, Default::default()).into() + }) + ])), ("fieldset", Vec::from([ Rule::new(Techniques::H71.into(), IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _auditor| { let mut valid = true; diff --git a/accessibility-rs/tests/unit/area.rs b/accessibility-rs/tests/unit/area.rs new file mode 100644 index 0000000..620be55 --- /dev/null +++ b/accessibility-rs/tests/unit/area.rs @@ -0,0 +1,42 @@ +//! Test for anchors. + +use accessibility_rs::{engine::audit, AuditConfig}; +use maud::html; + +#[test] +fn _audit_missing_alt_area() { + //alt attribute missing on first tag + let html = r#" + Workplace + + + Phone + Cup of coffee + "#; + let audit: Vec = + accessibility_rs::audit(AuditConfig::basic(html)); + + let valid = audit + .iter() + .any(|x| x.message == "1_1_1_H24.ImageMapAreaNoAlt"); + + assert_eq!(valid, true) +} + +#[test] +fn _audit_missing_alt_map() { + // alt attribute missing on tag + let html = r#" + Workplace + + Computer + Phone + Cup of coffee + "#; + let audit: Vec = + accessibility_rs::audit(AuditConfig::basic(html)); + + let valid = audit.iter().any(|x| x.message == "1_1_1_H24.ImageMapNoAlt"); + + assert_eq!(valid, true) +} diff --git a/accessibility-rs/tests/unit/mod.rs b/accessibility-rs/tests/unit/mod.rs index 03f85c3..c94d3fb 100644 --- a/accessibility-rs/tests/unit/mod.rs +++ b/accessibility-rs/tests/unit/mod.rs @@ -8,3 +8,4 @@ pub mod img; pub mod input; pub mod label; pub mod meta; +pub mod area; \ No newline at end of file