//! Tests for [`super`]. use super::*; use makeover_layout::{Accepted, Curve, Family}; fn field(kind: FieldKind) -> Field<'static> { Field::new(kind, "title", "Title") } #[test] fn a_value_cannot_break_out_of_the_attribute_it_sits_in() { // The payload from goingson's own CHRONIC-XSS regression test. let filling = Filling::of(Value::Text("x\" onfocus=alert(1) autofocus=\"")); let html = field_html(&field(FieldKind::Text), &filling, &Emit::default()); // The payload survives as text, which is the point: it is inert // because the quote that would have closed the attribute is encoded, // not because the words were filtered. assert!(!html.contains("\" onfocus"), "{html}"); assert!( html.contains("value=\"x" onfocus=alert(1) autofocus="\""), "{html}" ); } /// The seam quasi's suggestion source needs: a host's own attributes land /// on the control, unescaped, and after everything this crate decided. #[test] fn a_host_can_write_its_own_attributes_onto_the_control() { let mut filling = Filling::of(Value::Text("ru")); filling.control_attrs = Some(Markup( r#"role="combobox" aria-expanded="false" aria-controls="title-suggestions""#, )); let html = field_html(&field(FieldKind::Text), &filling, &Emit::default()); assert!(html.contains(r#"role="combobox""#), "{html}"); assert!( html.contains(r#"aria-controls="title-suggestions""#), "{html}" ); // After the id, which is what "last" buys: a host can read what this // emitter wrote and cannot be overwritten by it. let id = html.find(r#"id="title""#).expect("id"); let role = html.find(r#"role="combobox""#).expect("role"); assert!(id < role, "{html}"); } /// A radio group has no one control element, so there is nowhere honest to /// put an attribute meant for the control. Documented on the member. #[test] fn a_radio_group_drops_control_attributes() { let mut f = field(FieldKind::Radio); let options = [Choice::new("a", "A")]; f.options = &options; let filling = Filling { control_attrs: Some(Markup(r#"data-host="1""#)), ..Filling::default() }; let html = field_html(&f, &filling, &Emit::default()); assert!(!html.contains("data-host"), "{html}"); } #[test] fn a_label_cannot_open_a_tag() { let mut f = field(FieldKind::Text); f.label = ""; let html = field_html(&f, &Filling::default(), &Emit::default()); assert!(!html.contains("", )]; let f = Field::radio("storage", "Storage style", &hostile); let html = field_html(&f, &Filling::default(), &Emit::default()); // The payload survives as text; what must not survive is the quote // that would end the attribute and let the rest of it become markup. assert!(html.contains("value=\"x" onclick=alert(1)"), "{html}"); assert!(!html.contains("