Kévin Commaille d568d579ad html: Remove support for name attribute
According to MSC4159.
2024-09-06 09:21:24 +02:00

315 lines
12 KiB
Rust

use assert_matches2::assert_matches;
use ruma_html::{
matrix::{AnchorUri, MatrixElement},
Html,
};
#[test]
fn elements() {
let raw_html = "\
<h1>Title</h1>\
<div class=\"text\">\
<p>This is some <em>text</em></p>\
</div>\
<marquee id=\"scrolling_text\">This is scrolling</marquee>
";
let html = Html::parse(raw_html);
let mut html_children = html.children();
// `<h1>` element.
let h1_node = html_children.next().unwrap();
let h1_element = h1_node.as_element().unwrap().to_matrix();
assert_matches!(h1_element.element, MatrixElement::H(heading));
assert_eq!(heading.level, 1);
assert!(h1_element.attrs.is_empty());
// `<div>` element.
let div_node = html_children.next().unwrap();
let div_element = div_node.as_element().unwrap().to_matrix();
assert_matches!(div_element.element, MatrixElement::Div(div));
assert_eq!(div.maths, None);
// The `class` attribute is not supported.
assert_eq!(div_element.attrs.len(), 1);
// `<p>` element.
let p_node = div_node.first_child().unwrap();
let p_element = p_node.as_element().unwrap().to_matrix();
assert_matches!(p_element.element, MatrixElement::P);
assert!(p_element.attrs.is_empty());
// Text of `<p>` element.
let p_text_node = p_node.first_child().unwrap();
// `<em>` element.
let em_node = p_text_node.next_sibling().unwrap();
let em_element = em_node.as_element().unwrap().to_matrix();
assert_matches!(em_element.element, MatrixElement::Em);
assert!(em_element.attrs.is_empty());
// `<marquee>` element.
let marquee_node = html_children.next().unwrap();
let marquee_element = marquee_node.as_element().unwrap().to_matrix();
assert_matches!(marquee_element.element, MatrixElement::Other(_));
assert_eq!(marquee_element.attrs.len(), 1);
}
#[test]
fn span_attributes() {
let raw_html = "\
<span \
data-mx-color=\"#00ff00\" \
data-mx-bg-color=\"#ff0000\" \
data-mx-spoiler \
data-mx-spoiler=\"This is a spoiler\"\
>\
Hidden and colored\
</span>\
";
let html = Html::parse(raw_html);
let mut html_children = html.children();
let span_node = html_children.next().unwrap();
let span_element = span_node.as_element().unwrap().to_matrix();
assert_matches!(span_element.element, MatrixElement::Span(span));
assert_eq!(span.color.unwrap().as_ref(), "#00ff00");
assert_eq!(span.bg_color.unwrap().as_ref(), "#ff0000");
// Uses the first spoiler attribute, the second is dropped.
assert!(span.spoiler.unwrap().is_empty());
assert!(span_element.attrs.is_empty());
}
#[test]
fn a_attributes() {
let raw_html = "\
<a target=\"_blank\" href=\"https://localhost/\">\
Link with all supported attributes\
</a>\
<a href=\"matrix:r/somewhere:localhost\">Link with valid matrix scheme URI</a>\
<a href=\"matrix:somewhere:localhost\">Link with invalid matrix scheme URI</a>\
<a href=\"https://matrix.to/#/%23somewhere:example.org\">Link with valid matrix.to URI</a>\
<a href=\"https://matrix.to/#/somewhere:example.org\">Link with invalid matrix.to URI</a>\
<a href=\"ruma:html\">Link with unsupported scheme</a>\
";
let html = Html::parse(raw_html);
let mut html_children = html.children();
// First `<a>` element, with all supported attributes.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::A(anchor));
assert_eq!(anchor.target.unwrap().as_ref(), "_blank");
assert_matches!(anchor.href.unwrap(), AnchorUri::Other(uri));
assert_eq!(uri.as_ref(), "https://localhost/");
assert!(element.attrs.is_empty());
// Second `<a>` element, with valid matrix scheme URI.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::A(anchor));
assert!(anchor.target.is_none());
assert_matches!(anchor.href.unwrap(), AnchorUri::Matrix(uri));
assert_eq!(uri.to_string(), "matrix:r/somewhere:localhost");
assert!(element.attrs.is_empty());
// Third `<a>` element, with invalid matrix scheme URI.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::A(anchor));
assert!(anchor.target.is_none());
assert!(anchor.href.is_none());
// The `href` attribute is in the unsupported attributes.
assert_eq!(element.attrs.len(), 1);
// Fourth `<a>` element, with valid matrix.to URI.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::A(anchor));
assert!(anchor.target.is_none());
assert_matches!(anchor.href.unwrap(), AnchorUri::MatrixTo(uri));
assert_eq!(uri.to_string(), "https://matrix.to/#/%23somewhere:example.org");
assert!(element.attrs.is_empty());
// Fifth `<a>` element, with invalid matrix.to URI.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::A(anchor));
assert!(anchor.target.is_none());
assert!(anchor.href.is_none());
// The `href` attribute is in the unsupported attributes.
assert_eq!(element.attrs.len(), 1);
// Sixth `<a>` element, with unsupported scheme.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::A(anchor));
assert!(anchor.target.is_none());
assert!(anchor.href.is_none());
// The `href` attribute is in the unsupported attributes.
assert_eq!(element.attrs.len(), 1);
}
#[test]
fn img_attributes() {
let raw_html = "\
<img \
width=200 \
height=200 \
alt=\"Image with valid attributes\" \
title=\"Image with valid attributes\" \
src=\"mxc://localhost/abc123\" \
/>\
<img \
width=\"\" \
height=\"\" \
alt=\"Image with invalid attributes\" \
title=\"Image with invalid attributes\" \
src=\"https://localhost/abc123.png\" \
/>\
";
let html = Html::parse(raw_html);
let mut html_children = html.children();
// First `<img>` element, with valid attributes.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Img(image));
assert_eq!(image.width.unwrap(), 200);
assert_eq!(image.height.unwrap(), 200);
assert_eq!(image.alt.unwrap().as_ref(), "Image with valid attributes");
assert_eq!(image.title.unwrap().as_ref(), "Image with valid attributes");
assert_eq!(image.src.unwrap(), "mxc://localhost/abc123");
assert!(element.attrs.is_empty());
// Second `<img>` element, with invalid attributes.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Img(image));
assert!(image.width.is_none());
assert!(image.height.is_none());
assert_eq!(image.alt.unwrap().as_ref(), "Image with invalid attributes");
assert_eq!(image.title.unwrap().as_ref(), "Image with invalid attributes");
assert!(image.src.is_none());
// Invalid attributes are in the unsupported attributes.
assert_eq!(element.attrs.len(), 3);
}
#[test]
fn ol_attributes() {
let raw_html = "\
<ol start=2>\
<li>Item in list with valid start attribute</li>\
</ol>\
<ol start=\"beginning\">\
<li>Item in list with invalid start attribute</li>\
</ol>\
";
let html = Html::parse(raw_html);
let mut html_children = html.children();
// First `<ol>` element, with valid `start` attribute.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Ol(ol));
assert_eq!(ol.start.unwrap(), 2);
assert!(element.attrs.is_empty());
// First `<ol>` element, with invalid `start` attribute.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Ol(ol));
assert!(ol.start.is_none());
assert_eq!(element.attrs.len(), 1);
}
#[test]
fn code_attributes() {
let raw_html = "\
<code class=\"language-rust\">\
let s = \"Code with only `language-` class\";\
</code>\
<code class=\"rust-code\">\
let s = \"Code with other class\";\
</code>\
<code class=\"language-rust rust-code\">\
let s = \"Code with several classes beginning with `language-` class\";\
</code>\
<code class=\"rust-code language-rust\">\
let s = \"Code with several classes not beginning with `language-` class\";\
</code>\
<code class=\"language-\">\
let s = \"Code with invalid `language-` class\";\
</code>\
<code class=\"code-language-rust\">\
let s = \"Code with other class containing `language-`\";\
</code>\
";
let html = Html::parse(raw_html);
let mut html_children = html.children();
// First `<code>` element, with only `language-` class.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Code(code));
assert_eq!(code.language.unwrap().as_ref(), "rust");
assert!(element.attrs.is_empty());
// Second `<code>` element, with other class.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Code(code));
assert!(code.language.is_none());
// `class` is in unsupported attributes.
assert_eq!(element.attrs.len(), 1);
// Third `<code>` element, with several classes beginning with `language-` class.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Code(code));
assert_eq!(code.language.unwrap().as_ref(), "rust");
// Because it contains other classes, `class` is also in unsupported attributes.
assert_eq!(element.attrs.len(), 1);
// Fourth `<code>` element, with several classes not beginning with `language-` class.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Code(code));
assert_eq!(code.language.unwrap().as_ref(), "rust");
// Because it contains other classes, `class` is also in unsupported attributes.
assert_eq!(element.attrs.len(), 1);
// Fifth `<code>` element, with invalid `language-` class.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Code(code));
assert!(code.language.is_none());
// `class` is in unsupported attributes.
assert_eq!(element.attrs.len(), 1);
// Sixth `<code>` element, with other class containing `language-`.
let node = html_children.next().unwrap();
let element = node.as_element().unwrap().to_matrix();
assert_matches!(element.element, MatrixElement::Code(code));
assert!(code.language.is_none());
// `class` is in unsupported attributes.
assert_eq!(element.attrs.len(), 1);
}