182 lines
4.9 KiB
Rust
182 lines
4.9 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use bds_core::model::{Post, PostStatus, Tag, Template, TemplateKind, TemplateStatus};
|
|
use bds_core::render::{
|
|
RenderCategorySettings, RenderTemplateLookup, TemplateLookupError, render_markdown_to_html,
|
|
resolve_post_template,
|
|
};
|
|
|
|
fn make_post() -> Post {
|
|
Post {
|
|
id: "post-1".into(),
|
|
project_id: "project-1".into(),
|
|
title: "Post".into(),
|
|
slug: "post".into(),
|
|
excerpt: None,
|
|
content: Some("# Hello".into()),
|
|
status: PostStatus::Published,
|
|
author: None,
|
|
language: Some("en".into()),
|
|
do_not_translate: false,
|
|
template_slug: None,
|
|
file_path: "posts/2026/04/10/post.md".into(),
|
|
checksum: None,
|
|
tags: vec![],
|
|
categories: vec![],
|
|
published_title: None,
|
|
published_content: None,
|
|
published_tags: None,
|
|
published_categories: None,
|
|
published_excerpt: None,
|
|
created_at: 1,
|
|
updated_at: 1,
|
|
published_at: Some(1),
|
|
}
|
|
}
|
|
|
|
fn make_template(slug: &str) -> Template {
|
|
Template {
|
|
id: format!("template-{slug}"),
|
|
project_id: "project-1".into(),
|
|
slug: slug.into(),
|
|
title: slug.into(),
|
|
kind: TemplateKind::Post,
|
|
enabled: true,
|
|
version: 1,
|
|
file_path: format!("templates/{slug}.liquid"),
|
|
status: TemplateStatus::Published,
|
|
content: Some(format!("template:{slug}")),
|
|
created_at: 1,
|
|
updated_at: 1,
|
|
}
|
|
}
|
|
|
|
fn make_tag(name: &str, post_template_slug: Option<&str>) -> Tag {
|
|
Tag {
|
|
id: format!("tag-{name}"),
|
|
project_id: "project-1".into(),
|
|
name: name.into(),
|
|
color: None,
|
|
post_template_slug: post_template_slug.map(ToOwned::to_owned),
|
|
created_at: 1,
|
|
updated_at: 1,
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn template_lookup_prefers_post_specific_template() {
|
|
let mut post = make_post();
|
|
post.template_slug = Some("custom".into());
|
|
post.tags = vec!["rust".into()];
|
|
post.categories = vec!["article".into()];
|
|
|
|
let templates = vec![
|
|
make_template("post"),
|
|
make_template("tag-template"),
|
|
make_template("custom"),
|
|
];
|
|
let tags = vec![make_tag("rust", Some("tag-template"))];
|
|
let mut categories = HashMap::new();
|
|
categories.insert(
|
|
"article".into(),
|
|
RenderCategorySettings {
|
|
post_template_slug: Some("category-template".into()),
|
|
},
|
|
);
|
|
|
|
let resolved = resolve_post_template(RenderTemplateLookup {
|
|
post: &post,
|
|
templates: &templates,
|
|
tags: &tags,
|
|
category_settings: &categories,
|
|
})
|
|
.unwrap();
|
|
|
|
assert_eq!(resolved.slug, "custom");
|
|
}
|
|
|
|
#[test]
|
|
fn template_lookup_falls_back_to_tag_then_category_then_default() {
|
|
let mut post = make_post();
|
|
post.tags = vec!["rust".into()];
|
|
post.categories = vec!["article".into()];
|
|
|
|
let templates = vec![
|
|
make_template("post"),
|
|
make_template("tag-template"),
|
|
make_template("category-template"),
|
|
];
|
|
let tags = vec![make_tag("rust", Some("tag-template"))];
|
|
let mut categories = HashMap::new();
|
|
categories.insert(
|
|
"article".into(),
|
|
RenderCategorySettings {
|
|
post_template_slug: Some("category-template".into()),
|
|
},
|
|
);
|
|
|
|
let resolved = resolve_post_template(RenderTemplateLookup {
|
|
post: &post,
|
|
templates: &templates,
|
|
tags: &tags,
|
|
category_settings: &categories,
|
|
})
|
|
.unwrap();
|
|
assert_eq!(resolved.slug, "tag-template");
|
|
|
|
let category_post = Post {
|
|
tags: vec![],
|
|
..post.clone()
|
|
};
|
|
let resolved = resolve_post_template(RenderTemplateLookup {
|
|
post: &category_post,
|
|
templates: &templates,
|
|
tags: &tags,
|
|
category_settings: &categories,
|
|
})
|
|
.unwrap();
|
|
assert_eq!(resolved.slug, "category-template");
|
|
|
|
let default_post = Post {
|
|
tags: vec![],
|
|
categories: vec![],
|
|
..post
|
|
};
|
|
let empty_categories = HashMap::new();
|
|
let resolved = resolve_post_template(RenderTemplateLookup {
|
|
post: &default_post,
|
|
templates: &templates,
|
|
tags: &tags,
|
|
category_settings: &empty_categories,
|
|
})
|
|
.unwrap();
|
|
assert_eq!(resolved.slug, "post");
|
|
}
|
|
|
|
#[test]
|
|
fn template_lookup_errors_when_explicit_template_missing() {
|
|
let mut post = make_post();
|
|
post.template_slug = Some("missing".into());
|
|
let templates = vec![make_template("post")];
|
|
|
|
let err = resolve_post_template(RenderTemplateLookup {
|
|
post: &post,
|
|
templates: &templates,
|
|
tags: &[],
|
|
category_settings: &HashMap::new(),
|
|
})
|
|
.unwrap_err();
|
|
|
|
assert_eq!(
|
|
err,
|
|
TemplateLookupError::MissingExplicitTemplate("missing".into())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn markdown_render_produces_html() {
|
|
let html = render_markdown_to_html("# Hello\n\nA paragraph with **bold** text.");
|
|
assert!(html.contains("<h1>Hello</h1>"));
|
|
assert!(html.contains("<strong>bold</strong>"));
|
|
}
|