use minijinja::Value;
use crate::template::engine::TemplateEngine;
#[derive(Debug, Clone)]
pub struct TemplateResponse {
pub template_name: String,
pub context: Value,
rendered: Option<String>,
}
impl TemplateResponse {
#[must_use]
pub fn new(template_name: impl Into<String>, context: Value) -> Self {
Self {
template_name: template_name.into(),
context,
rendered: None,
}
}
pub fn render(&mut self, engine: &TemplateEngine) -> Result<&str, String> {
if self.rendered.is_none() {
let rendered = engine
.render(&self.template_name, self.context.clone())
.map_err(|error| error.to_string())?;
self.rendered = Some(rendered);
}
Ok(self
.rendered
.as_deref()
.expect("rendered response should contain cached content"))
}
#[must_use]
pub fn is_rendered(&self) -> bool {
self.rendered.is_some()
}
}
#[cfg(test)]
mod tests {
use minijinja::context;
use super::TemplateResponse;
use crate::template::engine::TemplateEngine;
#[test]
fn new_response_starts_unrendered() {
let response = TemplateResponse::new("hello.html", context!(name => "World"));
assert_eq!(response.template_name, "hello.html");
assert!(!response.is_rendered());
}
#[test]
fn render_uses_engine_and_caches_content() {
let mut engine = TemplateEngine::new();
engine.add_template("hello.html", "Hello {{ name }}!");
let mut response = TemplateResponse::new("hello.html", context!(name => "World"));
let first = response
.render(&engine)
.expect("response renders")
.to_string();
let second = response
.render(&engine)
.expect("response reuses cache")
.to_string();
assert_eq!(first, "Hello World!");
assert_eq!(second, "Hello World!");
assert!(response.is_rendered());
}
#[test]
fn render_returns_missing_template_errors() {
let engine = TemplateEngine::new();
let mut response = TemplateResponse::new("missing.html", context! {});
let error = response
.render(&engine)
.expect_err("missing template should error");
assert!(error.contains("missing.html"));
assert!(!response.is_rendered());
}
#[test]
fn cached_render_is_not_recomputed_after_context_changes() {
let mut engine = TemplateEngine::new();
engine.add_template("hello.html", "Hello {{ name }}!");
let mut response = TemplateResponse::new("hello.html", context!(name => "World"));
let first = response
.render(&engine)
.expect("response renders")
.to_string();
response.context = context!(name => "Changed");
let second = response
.render(&engine)
.expect("cached response returns")
.to_string();
assert_eq!(first, "Hello World!");
assert_eq!(second, "Hello World!");
}
}