//! 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("