use pagetop::prelude::*; /// Componente mínimo para probar `PrepareMarkup` pasando por el ciclo real /// de renderizado de componentes (`ComponentRender`). #[derive(AutoDefault)] struct TestPrepareComponent { pm: PrepareMarkup, } impl Component for TestPrepareComponent { fn new() -> Self { Self { pm: PrepareMarkup::None, } } fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup { self.pm.clone() } } impl TestPrepareComponent { fn render_pm(pm: PrepareMarkup) -> String { let mut c = TestPrepareComponent { pm }; c.render(&mut Context::default()).into_string() } } #[pagetop::test] async fn prepare_markup_none_is_empty_string() { assert_eq!(PrepareMarkup::None.into_string(), ""); } #[pagetop::test] async fn prepare_markup_escaped_escapes_html_and_ampersands() { let pm = PrepareMarkup::Escaped("& \" ' ".to_string()); assert_eq!(pm.into_string(), "<b>& " ' </b>"); } #[pagetop::test] async fn prepare_markup_raw_is_inserted_verbatim() { let pm = PrepareMarkup::Raw("bold".to_string()); assert_eq!(pm.into_string(), "bold"); } #[pagetop::test] async fn prepare_markup_with_keeps_structure() { let pm = PrepareMarkup::With(html! { h2 { "Sample title" } p { "This is a paragraph." } }); assert_eq!( pm.into_string(), "
This is a paragraph.
" ); } #[pagetop::test] async fn prepare_markup_unicode_is_preserved() { // Texto con acentos y emojis debe conservarse (salvo el escape HTML de signos). let esc = PrepareMarkup::Escaped("Hello, tomorrow coffee ☕ & donuts!".into()); assert_eq!(esc.into_string(), "Hello, tomorrow coffee ☕ & donuts!"); // Raw debe pasar íntegro. let raw = PrepareMarkup::Raw("Title — section © 2025".into()); assert_eq!(raw.into_string(), "Title — section © 2025"); } #[pagetop::test] async fn prepare_markup_is_empty_semantics() { assert!(PrepareMarkup::None.is_empty()); assert!(PrepareMarkup::Escaped(String::new()).is_empty()); assert!(PrepareMarkup::Escaped("".to_string()).is_empty()); assert!(!PrepareMarkup::Escaped("x".to_string()).is_empty()); assert!(PrepareMarkup::Raw(String::new()).is_empty()); assert!(PrepareMarkup::Raw("".to_string()).is_empty()); assert!(!PrepareMarkup::Raw("a".into()).is_empty()); assert!(PrepareMarkup::With(html! {}).is_empty()); assert!(!PrepareMarkup::With(html! { span { "!" } }).is_empty()); // Ojo: espacios NO deberían considerarse vacíos (comportamiento actual). assert!(!PrepareMarkup::Escaped(" ".into()).is_empty()); assert!(!PrepareMarkup::Raw(" ".into()).is_empty()); } #[pagetop::test] async fn prepare_markup_does_not_double_escape_when_markup_is_reinjected_in_html_macro() { let mut cx = Context::default(); // Escaped: dentro de `html!` no debe volver a escaparse. let mut comp = TestPrepareComponent { pm: PrepareMarkup::Escaped("x".into()), }; let markup = comp.render(&mut cx); // Markup let wrapped_escaped = html! { div { (markup) } }.into_string(); assert_eq!(wrapped_escaped, "