diff --git a/crates/rustmotion-html/src/element.rs b/crates/rustmotion-html/src/element.rs index 66db5c2..c308265 100644 --- a/crates/rustmotion-html/src/element.rs +++ b/crates/rustmotion-html/src/element.rs @@ -7,6 +7,16 @@ use crate::{element_attrs, tag_name, HtmlError}; enum TagKind { Container, Text, + /// Tags that never visually render in real HTML either (`

real

"#); + let children = v["children"].as_array().expect("children array"); + assert_eq!( + children.len(), + 1, + "script content must not become a component: {v}" + ); + assert_eq!(children[0]["content"], json!("real")); + } + + #[test] + fn title_and_noscript_and_template_elements_are_skipped_not_painted() { + let v = map_first( + r#"
tt

real

"#, + ); + let children = v["children"].as_array().expect("children array"); + assert_eq!( + children.len(), + 1, + "title/noscript/template content must not become a component: {v}" + ); + assert_eq!(children[0]["content"], json!("real")); + } + + #[test] + fn tag_kind_head_is_ignored() { + // content never survives as a distinct DOM node when authored + // inline (html5ever drops the wrapper per HTML5 "in body" parsing + // rules and lets its text bleed into the parent), so this can only be + // exercised at the `tag_kind` unit level, not through the full + // element_to_value/html_to_scenario_value pipeline. + assert!(matches!(tag_kind("head"), TagKind::Ignored)); + } + + // --- unsupported native elements (constat 3) --- + + #[test] + fn img_element_is_refused_with_rm_image_suggestion() { + let e = map_first_err(r#""#); + match e { + crate::HtmlError::UnsupportedNativeElement { tag, suggestion } => { + assert_eq!(tag, "img"); + assert_eq!(suggestion, "rm-image"); + } + other => panic!("expected UnsupportedNativeElement, got: {other:?}"), + } + } + + #[test] + fn video_element_is_refused_with_rm_video_suggestion() { + let e = map_first_err(r#""#); + match e { + crate::HtmlError::UnsupportedNativeElement { tag, suggestion } => { + assert_eq!(tag, "video"); + assert_eq!(suggestion, "rm-video"); + } + other => panic!("expected UnsupportedNativeElement, got: {other:?}"), + } + } + + #[test] + fn svg_element_is_refused_with_rm_svg_suggestion() { + let e = map_first_err(r#""#); + match e { + crate::HtmlError::UnsupportedNativeElement { tag, suggestion } => { + assert_eq!(tag, "svg"); + assert_eq!(suggestion, "rm-svg"); + } + other => panic!("expected UnsupportedNativeElement, got: {other:?}"), + } + } + + // --- boolean attributes on custom elements (constat 4) --- + + #[test] + fn custom_element_bool_attribute_true_and_false() { + let v = map_first(r#""#); + assert_eq!(v["auto_scroll"], json!(false)); + assert_eq!(v["diff"], json!(true)); + } + + #[test] + fn custom_element_bare_attribute_becomes_true() { + let v = map_first(r#""#); + assert_eq!( + v["diff"], + json!(true), + "bare boolean attribute must become true, not be dropped: {v}" + ); + } } diff --git a/crates/rustmotion-html/src/lib.rs b/crates/rustmotion-html/src/lib.rs index dcfd7eb..092bd1d 100644 --- a/crates/rustmotion-html/src/lib.rs +++ b/crates/rustmotion-html/src/lib.rs @@ -69,6 +69,34 @@ pub enum HtmlError { /// Emitted when `` sets both `path`/`src` and `source` — they are mutually exclusive. #[error(": 'path'/'src' and 'source' are mutually exclusive")] FontPathAndSourceConflict { family: String }, + /// Emitted for `

Styled by class

"##; + let err = html_to_scenario_value(html).expect_err("

Hi

"##; + let err = + html_to_scenario_value(html).expect_err("root-level