From a8402fb8293f296987991b89be92fa5f5d9577df Mon Sep 17 00:00:00 2001 From: j-mendez Date: Wed, 18 Oct 2023 16:17:33 -0400 Subject: [PATCH] chore(rules): add duplicate label for [H93] --- Cargo.lock | 2 +- RULES.md | 3 +- accessibility-rs/Cargo.toml | 2 +- accessibility-rs/locales/en.json | 1 + accessibility-rs/locales/es.json | 1 + .../src/engine/rules/techniques.rs | 2 ++ .../src/engine/rules/wcag_rule_map.rs | 30 +++++++++++++++++++ accessibility-rs/tests/unit/label.rs | 21 +++++++++++++ accessibility-rs/tests/unit/mod.rs | 1 + 9 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 accessibility-rs/tests/unit/label.rs diff --git a/Cargo.lock b/Cargo.lock index fbcd33e..77892cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "accessibility-rs" -version = "0.0.37" +version = "0.0.39" dependencies = [ "accessibility-scraper", "accessibility-tree", diff --git a/RULES.md b/RULES.md index dc696d1..cd840ff 100644 --- a/RULES.md +++ b/RULES.md @@ -23,11 +23,12 @@ List of [WCAG2.1 techniques](https://www.w3.org/TR/WCAG21/) and whether or not w | [H91](https://www.w3.org/TR/WCAG20-TECHS/H91.html) | anchor valid href attribute, but no link content | A-AAA | error | A.NoContent | ✅ | | [H91](https://www.w3.org/TR/WCAG20-TECHS/H91.html) | anchor found but no link content | A-AAA | error | A.EmptyNoId | ✅ | | [H91](https://www.w3.org/TR/WCAG20-TECHS/H91.html) | form control needs name | A-AAA | error | [NodeName].Name | ✔️ | +| [H93](https://www.w3.org/TR/WCAG20-TECHS/H93.html) | label has multiple for ids | A-AAA | error | | ✅ | | [F40](https://www.w3.org/TR/WCAG20-TECHS/F40.html) | meta redirect used with a time limit | A-AAA | error | 2 | ✅ | | [F41](https://www.w3.org/TR/WCAG20-TECHS/F41.html) | meta refresh used to reload the page | A-AAA | error | 2 | ✅ | | [F47](https://www.w3.org/TR/WCAG20-TECHS/F47.html) | blink element used for attention | A-AAA | error | | ✅ | | [F77](https://www.w3.org/TR/WCAG20-TECHS/F77.html) | duplicate ID found | A-AAA | error | | ✅ | -Errors that can be to be tested with automation `21/70`. +Errors that can be to be tested with automation `22/70`. Key: ✅ = Complete, ✔️ = Complete with a bit of missing details. diff --git a/accessibility-rs/Cargo.toml b/accessibility-rs/Cargo.toml index f32594e..e7effaf 100644 --- a/accessibility-rs/Cargo.toml +++ b/accessibility-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "accessibility-rs" -version = "0.0.37" +version = "0.0.39" authors = ["The A11yWatch Project Developers", "Jeff Mendez "] edition = "2021" license = "MIT OR Apache-2.0" diff --git a/accessibility-rs/locales/en.json b/accessibility-rs/locales/en.json index 66bb000..5b9c29f 100644 --- a/accessibility-rs/locales/en.json +++ b/accessibility-rs/locales/en.json @@ -61,6 +61,7 @@ "1_3_1_H39.3.NoCaption": "If this table is a data table, consider using a caption element to the table element to identify this table.", "1_3_1_H71.NoLegend": "Fieldset does not contain a legend element. All fieldsets should contain a legend element that describes a description of the field group.", "1_3_1_H85.2": "If this selection list contains groups of related options, they should be grouped with optgroup.", + "1_3_1_H93.1": "Multiple labels exist with the same \"for\" attribute. If these labels refer to different form controls, the controls should have unique \"id\" attributes.", "1_3_1_H71.SameName": "If these radio buttons or check boxes require a further group-level description, they should be contained within a fieldset element.", "1_3_1_H48.1": "This content looks like it is simulating an unordered list using plain text. If so, marking up this content with a ul element would add proper structure information to the document.", "1_3_1_H48.2": "This content looks like it is simulating an ordered list using plain text. If so, marking up this content with an ol element would add proper structure information to the document.", diff --git a/accessibility-rs/locales/es.json b/accessibility-rs/locales/es.json index b9d8a55..f08aac6 100644 --- a/accessibility-rs/locales/es.json +++ b/accessibility-rs/locales/es.json @@ -61,6 +61,7 @@ "1_3_1_H39.3.NoCaption": "Si esta tabla es una tabla de datos, considera agregar un elemento de subtítulo (caption) al elemento table para identificar esta tabla.", "1_3_1_H71.NoLegend": "El fieldset no contiene un elemento de leyenda (legend). Todos los fieldsets deben contener un elemento de leyenda que describa una descripción del grupo de campos.", "1_3_1_H85.2": "Si esta lista de selección contiene grupos de opciones relacionadas, deberían agruparse con el elemento optgroup.", + "1_3_1_H93.1": "Existen varias etiquetas con el mismo atributo \"for\". Si estas etiquetas se refieren a controles de formulario diferentes, los controles deben tener atributos \"id\" únicos.", "1_3_1_H71.SameName": "Si estos botones de radio o casillas de verificación requieren una descripción a nivel de grupo adicional, deberían estar contenidos dentro de un elemento fieldset.", "1_3_1_H48.1": "Este contenido parece estar simulando una lista desordenada usando texto plano. Si es así, marcar este contenido con un elemento ul agregaría información de estructura adecuada al documento.", "1_3_1_H48.2": "Este contenido parece estar simulando una lista ordenada usando texto plano. Si es así, marcar este contenido con un elemento ol agregaría información de estructura adecuada al documento.", diff --git a/accessibility-rs/src/engine/rules/techniques.rs b/accessibility-rs/src/engine/rules/techniques.rs index ad3cde3..bbff678 100644 --- a/accessibility-rs/src/engine/rules/techniques.rs +++ b/accessibility-rs/src/engine/rules/techniques.rs @@ -27,6 +27,8 @@ pub enum Techniques { H71, /// H91, + /// + H93, /// F40, /// diff --git a/accessibility-rs/src/engine/rules/wcag_rule_map.rs b/accessibility-rs/src/engine/rules/wcag_rule_map.rs index 2a44e9f..2e8286e 100644 --- a/accessibility-rs/src/engine/rules/wcag_rule_map.rs +++ b/accessibility-rs/src/engine/rules/wcag_rule_map.rs @@ -287,6 +287,36 @@ lazy_static! { validate_empty_nodes(nodes, "2").into() }), ])), + ("label", Vec::from([ + Rule::new(Techniques::H93.into(), IssueType::Error, Principle::Perceivable, Guideline::Adaptable, "1", |nodes, _lang| { + let mut valid = true; + let mut elements = Vec::new(); + let mut id_map: HashMap<&str, u8> = HashMap::new(); + + for ele in nodes { + match ele.0.attr("for") { + Some(s) => { + if id_map.contains_key(s) { + let u = id_map.get(s); + match u { + Some(u) => { + valid = false; + id_map.insert(s, u.add(1)); + elements.push(get_unique_selector(&ele.0)) + } + _ => () + } + } else { + id_map.insert(s, 1); + } + } + _ => () + } + } + + Validation::new(valid, "1", elements, Default::default()).into() + }) + ])), ("input", Vec::from([ Rule::new(Techniques::H91.into(), IssueType::Error, Principle::Robust, Guideline::Compatible, "2", |nodes, lang| { let mut valid = true; diff --git a/accessibility-rs/tests/unit/label.rs b/accessibility-rs/tests/unit/label.rs new file mode 100644 index 0000000..6646a16 --- /dev/null +++ b/accessibility-rs/tests/unit/label.rs @@ -0,0 +1,21 @@ +//! Test for label elements. +use accessibility_rs::AuditConfig; +use maud::html; + +#[test] +/// label needs unique target ids +fn _audit_label_valid_name() { + let markup = html! { + label for="accessibility" { "My label" } + input id="accessibility" type="text" placeholder="Accessibility rocks!" value="Here"; + label for="accessibility" { "My label" } + }; + + let audit = accessibility_rs::audit(AuditConfig::basic(&markup.into_string())); + + let valid = !audit + .iter() + .any(|x| x.code == "WCAGAAA.Principle1.Guideline1_3.H93"); + + assert_eq!(valid, false) +} diff --git a/accessibility-rs/tests/unit/mod.rs b/accessibility-rs/tests/unit/mod.rs index 151bfc7..5cb3273 100644 --- a/accessibility-rs/tests/unit/mod.rs +++ b/accessibility-rs/tests/unit/mod.rs @@ -6,3 +6,4 @@ pub mod html; pub mod img; pub mod input; pub mod meta; +pub mod label; \ No newline at end of file