use std::fs;
use std::process::Command;
use tempfile::TempDir;
#[test]
fn test_site_generation_with_static_files() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::create_dir_all(input_dir.join("static")).unwrap();
let config_path = input_dir.join("marmite.yaml");
fs::write(&config_path, "name: Site").unwrap();
fs::write(
input_dir.join("static").join("style.css"),
"body { color: red; }",
)
.unwrap();
fs::write(
input_dir.join("static").join("script.js"),
"console.log('test');",
)
.unwrap();
fs::write(input_dir.join("content").join("page.md"), "# Page").unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(output_dir.join("static").join("style.css").exists());
assert!(output_dir.join("static").join("script.js").exists());
assert!(output_dir.join("static").join("marmite.css").exists());
assert!(output_dir.join("static").join("marmite.js").exists());
assert!(output_dir.join("static").join("pico.min.css").exists());
assert!(output_dir.join("static").join("search.js").exists());
}
#[test]
fn test_static_drift_warning_for_core_files() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::create_dir_all(input_dir.join("static")).unwrap();
let config_path = input_dir.join("marmite.yaml");
fs::write(&config_path, "name: Site").unwrap();
fs::write(
input_dir.join("static").join("search.js"),
"// my customized search",
)
.unwrap();
fs::write(input_dir.join("content").join("page.md"), "# Page").unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(output.status.success());
let output_search_js = fs::read_to_string(output_dir.join("static").join("search.js")).unwrap();
assert_eq!(output_search_js, "// my customized search");
assert!(output_dir.join("static").join("marmite.css").exists());
assert!(output_dir.join("static").join("pico.min.css").exists());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("search.js") && stderr.contains("differs from the embedded version"),
"Expected drift warning for search.js in stderr, got: {stderr}"
);
}
#[test]
fn test_site_generation_with_media() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::create_dir_all(input_dir.join("content").join("media")).unwrap();
let config_path = input_dir.join("marmite.yaml");
fs::write(&config_path, "name: Site").unwrap();
fs::write(
input_dir.join("content").join("media").join("image.jpg"),
"fake image data",
)
.unwrap();
let content = r"# Post with Image
";
fs::write(input_dir.join("content").join("post.md"), content).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(output_dir.join("media").join("image.jpg").exists());
}
#[test]
fn test_site_generation_with_sitemap() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
let config_path = input_dir.join("marmite.yaml");
fs::write(
&config_path,
"name: Site\nbuild_sitemap: true\nurl: https://example.com",
)
.unwrap();
fs::write(input_dir.join("content").join("page1.md"), "# Page 1").unwrap();
fs::write(input_dir.join("content").join("page2.md"), "# Page 2").unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(output_dir.join("sitemap.xml").exists());
let sitemap_content = fs::read_to_string(output_dir.join("sitemap.xml")).unwrap();
assert!(sitemap_content.contains("<urlset"));
assert!(sitemap_content.contains("page1.html"));
assert!(sitemap_content.contains("page2.html"));
}
#[test]
fn test_series_feature() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
let config_path = input_dir.join("marmite.yaml");
fs::write(&config_path, "name: Blog").unwrap();
let part1 = r"---
date: 2024-01-01
series: python-tutorial
---
# Python Tutorial Part 1";
fs::write(input_dir.join("content").join("python-part1.md"), part1).unwrap();
let part2 = r"---
date: 2024-01-02
series: python-tutorial
---
# Python Tutorial Part 2";
fs::write(input_dir.join("content").join("python-part2.md"), part2).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(output_dir.join("series-python-tutorial.html").exists());
assert!(output_dir.join("series.html").exists());
}
#[test]
fn test_fragments_feature() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
let config_path = input_dir.join("marmite.yaml");
fs::write(&config_path, "name: Site").unwrap();
let fragment = "## This is a fragment\n\nIt can be included in templates.";
fs::write(input_dir.join("content").join("_hero.md"), fragment).unwrap();
fs::write(input_dir.join("content").join("page.md"), "# Regular Page").unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(!output_dir.join("_hero.html").exists());
assert!(!output_dir.join("hero.html").exists());
assert!(output_dir.join("page.html").exists());
}
#[test]
fn test_authors_feature() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
let config = r"name: Blog
authors:
alice:
name: Alice Smith
bio: Developer
avatar: alice.jpg
bob:
name: Bob Jones
bio: Designer
avatar: bob.jpg
";
fs::write(input_dir.join("marmite.yaml"), config).unwrap();
let post1 = r"---
date: 2024-01-01
author: alice
---
# Alice's Post";
fs::write(input_dir.join("content").join("alice-post.md"), post1).unwrap();
let post2 = r"---
date: 2024-01-02
authors: [alice, bob]
---
# Collaborative Post";
fs::write(input_dir.join("content").join("collab-post.md"), post2).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(output_dir.join("author-alice.html").exists());
assert!(output_dir.join("author-bob.html").exists());
assert!(output_dir.join("authors.html").exists());
}
#[test]
fn test_file_mapping_feature() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
let config = r"name: Site
file_mapping:
- source: README.md
dest: about.html
";
fs::write(input_dir.join("marmite.yaml"), config).unwrap();
fs::write(
input_dir.join("README.md"),
"# About\n\nThis is the about page.",
)
.unwrap();
fs::write(input_dir.join("content").join("page.md"), "# Page").unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(output_dir.join("about.html").exists());
}
#[test]
fn test_favicon_copied_to_site_root() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::write(input_dir.join("marmite.yaml"), "name: Site").unwrap();
fs::write(input_dir.join("content").join("page.md"), "# Page").unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(
output_dir.join("static").join("favicon.ico").exists(),
"favicon.ico missing from output/static/"
);
assert!(
output_dir.join("favicon.ico").exists(),
"favicon.ico missing from site root - browsers request /favicon.ico automatically"
);
}
#[test]
fn test_favicon_file_mapping_not_overwritten() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::create_dir_all(input_dir.join("static")).unwrap();
fs::write(
input_dir.join("static").join("favicon.ico"),
b"CUSTOM_FAVICON",
)
.unwrap();
let config = r"name: Site
file_mapping:
- source: static/favicon.ico
dest: favicon.ico
";
fs::write(input_dir.join("marmite.yaml"), config).unwrap();
fs::write(input_dir.join("content").join("page.md"), "# Page").unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let content = fs::read(output_dir.join("favicon.ico")).unwrap();
assert_eq!(
content, b"CUSTOM_FAVICON",
"file_mapping favicon was overwritten by auto-copy"
);
}
#[test]
fn test_redirect_aliases() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::write(input_dir.join("marmite.yaml"), "name: Site").unwrap();
let post = r"---
title: My New Post
slug: my-new-post
date: 2024-01-01
aliases:
- old-post-url
- legacy-path
---
# My New Post
Content here.";
fs::write(input_dir.join("content").join("my-new-post.md"), post).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(output_dir.join("my-new-post.html").exists());
assert!(
output_dir.join("old-post-url.html").exists(),
"Redirect alias old-post-url.html should exist"
);
assert!(
output_dir.join("legacy-path.html").exists(),
"Redirect alias legacy-path.html should exist"
);
let redirect_content = fs::read_to_string(output_dir.join("old-post-url.html")).unwrap();
assert!(
redirect_content.contains("my-new-post.html"),
"Redirect should point to my-new-post.html, got: {redirect_content}"
);
assert!(
redirect_content.contains("meta http-equiv=\"refresh\""),
"Redirect should use meta refresh"
);
assert!(
redirect_content.contains("rel=\"canonical\""),
"Redirect should include canonical link"
);
}
#[test]
fn test_redirect_aliases_not_in_sitemap() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(&input_dir).unwrap();
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::write(
input_dir.join("marmite.yaml"),
"name: Site\nbuild_sitemap: true\nurl: https://example.com",
)
.unwrap();
let post = r"---
title: My Post
slug: my-post
date: 2024-01-01
aliases:
- old-url
---
# My Post";
fs::write(input_dir.join("content").join("my-post.md"), post).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let sitemap = fs::read_to_string(output_dir.join("sitemap.xml")).unwrap();
assert!(
sitemap.contains("my-post.html"),
"Sitemap should contain the real post URL"
);
assert!(
!sitemap.contains("old-url.html"),
"Sitemap should NOT contain redirect alias URLs"
);
}
#[test]
fn test_check_internal_links_warns_on_broken() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::write(
input_dir.join("marmite.yaml"),
"name: Site\ncheck_internal_links: true",
)
.unwrap();
let post = r"---
title: Post With Broken Link
date: 2024-01-01
---
# Post
Check out [this page](nonexistent-page.html).
";
fs::write(input_dir.join("content").join("post.md"), post).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Build should succeed with warnings, not fail"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("Broken internal link"),
"Should warn about broken internal link, got: {stderr}"
);
assert!(
stderr.contains("nonexistent-page"),
"Warning should mention the broken target, got: {stderr}"
);
}
#[test]
fn test_strict_internal_links_fails_build() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::write(
input_dir.join("marmite.yaml"),
"name: Site\ncheck_internal_links: true\nstrict_internal_links: true",
)
.unwrap();
let post = r"---
title: Post With Broken Link
date: 2024-01-01
---
# Post
Check out [this page](nonexistent-page.html).
";
fs::write(input_dir.join("content").join("post.md"), post).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
!output.status.success(),
"Build should fail with strict_internal_links enabled"
);
}
#[test]
fn test_check_internal_links_passes_with_valid_links() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::write(
input_dir.join("marmite.yaml"),
"name: Site\ncheck_internal_links: true",
)
.unwrap();
let post = r"---
title: My Post
date: 2024-01-01
---
# My Post
Check out [the about page](about.html).
";
fs::write(input_dir.join("content").join("post.md"), post).unwrap();
let page = "# About\n\nThis is the about page.";
fs::write(input_dir.join("content").join("about.md"), page).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Build should succeed: {}",
String::from_utf8_lossy(&output.stderr)
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
!stderr.contains("Broken internal link"),
"Should not warn about broken links when all links are valid, got: {stderr}"
);
}
#[test]
fn test_check_media_links_warns_on_broken() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(input_dir.join("content").join("media")).unwrap();
fs::write(
input_dir.join("marmite.yaml"),
"name: Site\ncheck_media_links: true",
)
.unwrap();
let post = r#"---
title: Post With Broken Media
date: 2024-01-01
---
# Post

"#;
fs::write(input_dir.join("content").join("post.md"), post).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Build should succeed with warnings, not fail"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("Broken media link"),
"Should warn about broken media link, got: {stderr}"
);
assert!(
stderr.contains("nonexistent.jpg"),
"Warning should mention the broken media file, got: {stderr}"
);
}
#[test]
fn test_check_media_links_passes_with_valid() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
let media_dir = input_dir.join("content").join("media");
fs::create_dir_all(&media_dir).unwrap();
fs::write(media_dir.join("photo.jpg"), "fake image data").unwrap();
fs::write(
input_dir.join("marmite.yaml"),
"name: Site\ncheck_media_links: true",
)
.unwrap();
let post = r#"---
title: Post With Valid Media
date: 2024-01-01
---
# Post

"#;
fs::write(input_dir.join("content").join("post.md"), post).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Build should succeed: {}",
String::from_utf8_lossy(&output.stderr)
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
!stderr.contains("Broken media link"),
"Should not warn about broken media links when all links are valid, got: {stderr}"
);
}
#[test]
fn test_strict_media_links_fails_build() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(input_dir.join("content").join("media")).unwrap();
fs::write(
input_dir.join("marmite.yaml"),
"name: Site\ncheck_media_links: true\nstrict_internal_links: true",
)
.unwrap();
let post = r#"---
title: Post With Broken Media
date: 2024-01-01
---
# Post

"#;
fs::write(input_dir.join("content").join("post.md"), post).unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
!output.status.success(),
"Build should fail with strict_internal_links enabled and broken media links"
);
}
#[test]
fn test_subfolder_media_copied_to_slug_based_path() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(
input_dir
.join("content")
.join("docs")
.join("my-post")
.join("media"),
)
.unwrap();
fs::create_dir_all(input_dir.join("content").join("media")).unwrap();
fs::write(input_dir.join("marmite.yaml"), "name: Test").unwrap();
fs::write(
input_dir
.join("content")
.join("docs")
.join("my-post")
.join("my-post.md"),
"---\ntitle: My Post\ndate: 2024-01-01\n---\n# My Post\n\n\n",
)
.unwrap();
fs::write(
input_dir
.join("content")
.join("docs")
.join("my-post")
.join("media")
.join("banner.jpg"),
"fake-banner",
)
.unwrap();
fs::write(
input_dir
.join("content")
.join("docs")
.join("my-post")
.join("media")
.join("photo.jpg"),
"fake-photo",
)
.unwrap();
fs::write(
input_dir.join("content").join("media").join("root.jpg"),
"root-file",
)
.unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(
output_dir
.join("media")
.join("my-post")
.join("photo.jpg")
.exists(),
"Subfolder media should be at media/my-post/photo.jpg"
);
assert!(
output_dir
.join("media")
.join("my-post")
.join("banner.jpg")
.exists(),
"Subfolder banner should be at media/my-post/banner.jpg"
);
assert!(
!output_dir
.join("media")
.join("docs")
.join("my-post")
.exists(),
"Media should not preserve parent subfolder structure"
);
assert!(
output_dir.join("media").join("root.jpg").exists(),
"Root media should be copied"
);
let html = fs::read_to_string(output_dir.join("my-post.html")).unwrap();
assert!(
html.contains("media/my-post/photo.jpg"),
"@/ should resolve to media/my-post/photo.jpg"
);
assert!(
html.contains("media/my-post/banner.jpg"),
"Banner should be discovered from subfolder media"
);
}
#[test]
fn test_subfolder_media_no_conflicts_between_subfolders() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(
input_dir
.join("content")
.join("docs")
.join("post-a")
.join("media"),
)
.unwrap();
fs::create_dir_all(
input_dir
.join("content")
.join("tutorials")
.join("post-b")
.join("media"),
)
.unwrap();
fs::create_dir_all(input_dir.join("content").join("media")).unwrap();
fs::write(input_dir.join("marmite.yaml"), "name: Test").unwrap();
fs::write(
input_dir
.join("content")
.join("docs")
.join("post-a")
.join("post-a.md"),
"---\ntitle: Post A\ndate: 2024-01-01\n---\n# Post A\n",
)
.unwrap();
fs::write(
input_dir
.join("content")
.join("docs")
.join("post-a")
.join("media")
.join("photo.jpg"),
"photo-from-a",
)
.unwrap();
fs::write(
input_dir
.join("content")
.join("tutorials")
.join("post-b")
.join("post-b.md"),
"---\ntitle: Post B\ndate: 2024-02-01\n---\n# Post B\n",
)
.unwrap();
fs::write(
input_dir
.join("content")
.join("tutorials")
.join("post-b")
.join("media")
.join("photo.jpg"),
"photo-from-b",
)
.unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let a_photo = fs::read_to_string(output_dir.join("media").join("post-a").join("photo.jpg"))
.expect("post-a media should exist");
let b_photo = fs::read_to_string(output_dir.join("media").join("post-b").join("photo.jpg"))
.expect("post-b media should exist");
assert_eq!(a_photo, "photo-from-a", "post-a should have its own photo");
assert_eq!(b_photo, "photo-from-b", "post-b should have its own photo");
}
#[test]
fn test_native_mermaid_render() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::write(input_dir.join("marmite.yaml"), "name: Test Site").unwrap();
fs::write(
input_dir.join("content").join("diagrams.md"),
"# Diagrams\n\n```mermaid\ngraph LR\n A --> B\n```\n",
)
.unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let html = fs::read_to_string(output_dir.join("diagrams.html")).unwrap();
assert!(
html.contains("<div class=\"mermaid-diagram\">"),
"Should contain rendered mermaid diagram div"
);
assert!(
html.contains("<svg"),
"Should contain SVG output from mermaid-rs-renderer"
);
assert!(
!html.contains("language-mermaid"),
"Should not contain raw mermaid code block"
);
}
#[test]
fn test_native_mermaid_render_disabled_preserves_js_flow() {
let temp_dir = TempDir::new().unwrap();
let input_dir = temp_dir.path().join("input");
let output_dir = temp_dir.path().join("output");
fs::create_dir_all(input_dir.join("content")).unwrap();
fs::write(
input_dir.join("marmite.yaml"),
"name: Test Site\nnative_mermaid_render: false",
)
.unwrap();
fs::write(
input_dir.join("content").join("diagrams.md"),
"---\nextra:\n mermaid: true\n---\n# Diagrams\n\n```mermaid\ngraph LR\n A --> B\n```\n",
)
.unwrap();
let output = Command::new("cargo")
.args([
"run",
"--quiet",
"--",
input_dir.to_str().unwrap(),
output_dir.to_str().unwrap(),
])
.output()
.expect("Failed to execute marmite");
assert!(
output.status.success(),
"Command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let html = fs::read_to_string(output_dir.join("diagrams.html")).unwrap();
assert!(
html.contains("language-mermaid"),
"Should contain raw mermaid code block for JS rendering"
);
assert!(
html.contains("mermaid.min.js"),
"Should load MermaidJS script"
);
assert!(
!html.contains("<div class=\"mermaid-diagram\">"),
"Should not contain build-time rendered diagram"
);
}