refactor(v0): render page swap with hemplate
Move the v0 docs/page-swap partial and EffectBatch content payload from raw HTML strings into hemplate views, with scraper assertions for rendered structure. req: html_safety/002 req: view/001 req: test/005
This commit is contained in:
+71
-14
@@ -37,6 +37,18 @@ struct TodoItem {
|
|||||||
title: String,
|
title: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Hemplate)]
|
||||||
|
struct PageSwap {
|
||||||
|
content: SafeHtml,
|
||||||
|
title: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Hemplate)]
|
||||||
|
#[hemplate = "partials"]
|
||||||
|
struct DocsContent {
|
||||||
|
message: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let state = Arc::new(ExampleState::default());
|
let state = Arc::new(ExampleState::default());
|
||||||
@@ -63,16 +75,7 @@ async fn home(request: PageRequest) -> impl IntoResponse {
|
|||||||
|
|
||||||
// req: page_swap/002, req: examples/001
|
// req: page_swap/002, req: examples/001
|
||||||
async fn docs(request: PageRequest) -> impl IntoResponse {
|
async fn docs(request: PageRequest) -> impl IntoResponse {
|
||||||
let partial = ui::page_swap::lower_html(
|
let partial = render_page_swap("Docs", "This page was swapped without a full reload.");
|
||||||
r#"<main data-slhx-root="docs">
|
|
||||||
<nav data-slhx-slot="nav">
|
|
||||||
<a href="/" data-slhx-nav="">Examples</a>
|
|
||||||
<a href="/docs" data-slhx-nav="">Docs</a>
|
|
||||||
</nav>
|
|
||||||
<article data-slhx-slot="content"><h1>Docs</h1><p>This page was swapped without a full reload.</p></article>
|
|
||||||
<title data-slhx-slot="title">Docs</title>
|
|
||||||
</main>"#,
|
|
||||||
);
|
|
||||||
request
|
request
|
||||||
.page(partial, shell)
|
.page(partial, shell)
|
||||||
.title("Docs")
|
.title("Docs")
|
||||||
@@ -155,8 +158,8 @@ fn registry(state: Arc<ExampleState>) -> HandlerRegistry {
|
|||||||
.register(ui::page_swap::handles::load_docs.id().id, |_| {
|
.register(ui::page_swap::handles::load_docs.id().id, |_| {
|
||||||
// req: page_swap/002, req: examples/001
|
// req: page_swap/002, req: examples/001
|
||||||
(
|
(
|
||||||
ui::page_swap::slots::content.html(SafeHtml::trusted(
|
ui::page_swap::slots::content.html(render_docs_content(
|
||||||
"<h1>Docs</h1><p>This content came from an EffectBatch.</p>",
|
"This content came from an EffectBatch.",
|
||||||
)),
|
)),
|
||||||
ui::page_swap::slots::title.text("Docs"),
|
ui::page_swap::slots::title.text("Docs"),
|
||||||
push("/docs"),
|
push("/docs"),
|
||||||
@@ -170,7 +173,7 @@ fn all_examples() -> String {
|
|||||||
ui::todos::lower_html(include_str!("../templates/todos.heml")),
|
ui::todos::lower_html(include_str!("../templates/todos.heml")),
|
||||||
ui::wizard::lower_html(include_str!("../templates/wizard.heml")),
|
ui::wizard::lower_html(include_str!("../templates/wizard.heml")),
|
||||||
ui::auth::lower_html(include_str!("../templates/auth.heml")),
|
ui::auth::lower_html(include_str!("../templates/auth.heml")),
|
||||||
ui::page_swap::lower_html(include_str!("../templates/page_swap.heml")),
|
render_page_swap("Welcome", "Welcome"),
|
||||||
ui::notifications::lower_html(include_str!("../templates/notifications.heml")),
|
ui::notifications::lower_html(include_str!("../templates/notifications.heml")),
|
||||||
]
|
]
|
||||||
.join("\n")
|
.join("\n")
|
||||||
@@ -214,8 +217,25 @@ fn render_todos(todos: &[Todo]) -> SafeHtml {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_page_swap(title: &'static str, message: &'static str) -> String {
|
||||||
|
// req: html_safety/002 req: view/001
|
||||||
|
ui::page_swap::lower_html(render_template(&PageSwap {
|
||||||
|
content: render_docs_content(message),
|
||||||
|
title,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_docs_content(message: &'static str) -> SafeHtml {
|
||||||
|
// req: html_safety/002 req: view/001
|
||||||
|
render_html(&DocsContent { message })
|
||||||
|
}
|
||||||
|
|
||||||
fn render_html(template: &impl Hemplate) -> SafeHtml {
|
fn render_html(template: &impl Hemplate) -> SafeHtml {
|
||||||
SafeHtml::trusted(template.render().expect("v0 hemplate partial renders"))
|
SafeHtml::trusted(render_template(template))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_template(template: &impl Hemplate) -> String {
|
||||||
|
template.render().expect("v0 hemplate view renders")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -227,6 +247,43 @@ mod tests {
|
|||||||
Selector::parse(value).expect("test selector parses")
|
Selector::parse(value).expect("test selector parses")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// req: html_safety/002 req: view/001 req: test/005
|
||||||
|
#[test]
|
||||||
|
fn docs_content_payload_is_rendered_by_a_hemplate_view() {
|
||||||
|
let html = render_docs_content("This content came from an EffectBatch.");
|
||||||
|
let document = Html::parse_fragment(html.as_str());
|
||||||
|
assert_eq!(
|
||||||
|
document
|
||||||
|
.select(&selector("h1"))
|
||||||
|
.next()
|
||||||
|
.map(|heading| heading.text().collect::<String>()),
|
||||||
|
Some("Docs".to_owned())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
document
|
||||||
|
.select(&selector("p"))
|
||||||
|
.next()
|
||||||
|
.map(|paragraph| paragraph.text().collect::<String>()),
|
||||||
|
Some("This content came from an EffectBatch.".to_owned())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// req: html_safety/002 req: view/001 req: test/005
|
||||||
|
#[test]
|
||||||
|
fn docs_page_partial_is_rendered_by_a_hemplate_view() {
|
||||||
|
let html = render_page_swap("Docs", "This page was swapped without a full reload.");
|
||||||
|
let document = Html::parse_fragment(&html);
|
||||||
|
assert_eq!(document.select(&selector("main[data-slhx-root=\"docs\"]")).count(), 1);
|
||||||
|
assert_eq!(document.select(&selector("article[data-sid]")).count(), 1);
|
||||||
|
assert_eq!(
|
||||||
|
document
|
||||||
|
.select(&selector("article h1"))
|
||||||
|
.next()
|
||||||
|
.map(|heading| heading.text().collect::<String>()),
|
||||||
|
Some("Docs".to_owned())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// req: html_safety/002 req: view/001 req: test/005
|
// req: html_safety/002 req: view/001 req: test/005
|
||||||
#[test]
|
#[test]
|
||||||
fn todos_payload_is_rendered_by_a_hemplate_view() {
|
fn todos_payload_is_rendered_by_a_hemplate_view() {
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
<nav data-slhx-slot="nav">
|
<nav data-slhx-slot="nav">
|
||||||
<a href="/docs" data-slhx-nav="" data-slhx-handle="load_docs">Docs</a>
|
<a href="/docs" data-slhx-nav="" data-slhx-handle="load_docs">Docs</a>
|
||||||
</nav>
|
</nav>
|
||||||
<article data-slhx-slot="content">Welcome</article>
|
<article data-slhx-slot="content">{+= self.content =+}</article>
|
||||||
<title data-slhx-slot="title">Welcome</title>
|
<title data-slhx-slot="title">{+ self.title +}</title>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<h1>Docs</h1><p>{+ self.message +}</p>
|
||||||
Reference in New Issue
Block a user