test(nav): add unit tests for anchor extraction and TOC fallback
- test_anchor_extraction: verify h2-h6 extracted, h1 skipped, IDs slugified - test_slugify_edge_cases: verify special char handling, spaces, case - test_toc_config_fallback: verify frontmatter override and config default
This commit is contained in:
@@ -393,4 +393,69 @@ mod tests {
|
|||||||
assert!(html.contains("src=\"logo.png\""));
|
assert!(html.contains("src=\"logo.png\""));
|
||||||
assert!(!html.contains("title="));
|
assert!(!html.contains("title="));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_anchor_extraction() {
|
||||||
|
let md = r#"# Page Title
|
||||||
|
## Getting Started
|
||||||
|
Some intro text.
|
||||||
|
### Installation
|
||||||
|
Install steps.
|
||||||
|
## Configuration
|
||||||
|
Config details.
|
||||||
|
#### Deep Heading
|
||||||
|
"#;
|
||||||
|
let (html, anchors) = markdown_to_html(md);
|
||||||
|
|
||||||
|
// h1 should NOT be extracted (page title, not TOC)
|
||||||
|
assert!(anchors.iter().all(|a| a.level >= 2));
|
||||||
|
|
||||||
|
// Should have 4 anchors: h2, h3, h2, h4
|
||||||
|
assert_eq!(anchors.len(), 4);
|
||||||
|
|
||||||
|
// Check first anchor
|
||||||
|
assert_eq!(anchors[0].id, "getting-started");
|
||||||
|
assert_eq!(anchors[0].label, "Getting Started");
|
||||||
|
assert_eq!(anchors[0].level, 2);
|
||||||
|
|
||||||
|
// Check h3
|
||||||
|
assert_eq!(anchors[1].id, "installation");
|
||||||
|
assert_eq!(anchors[1].level, 3);
|
||||||
|
|
||||||
|
// Check second h2
|
||||||
|
assert_eq!(anchors[2].id, "configuration");
|
||||||
|
assert_eq!(anchors[2].level, 2);
|
||||||
|
|
||||||
|
// Check h4
|
||||||
|
assert_eq!(anchors[3].id, "deep-heading");
|
||||||
|
assert_eq!(anchors[3].level, 4);
|
||||||
|
|
||||||
|
// Verify IDs are in HTML
|
||||||
|
assert!(html.contains("id=\"getting-started\""));
|
||||||
|
assert!(html.contains("id=\"installation\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_slugify_edge_cases() {
|
||||||
|
// Basic case
|
||||||
|
assert_eq!(slugify("Hello World"), "hello-world");
|
||||||
|
|
||||||
|
// Multiple spaces → single hyphen
|
||||||
|
assert_eq!(slugify("Hello World"), "hello-world");
|
||||||
|
|
||||||
|
// Special characters → hyphen (apostrophe becomes hyphen)
|
||||||
|
assert_eq!(slugify("What's New?"), "what-s-new");
|
||||||
|
|
||||||
|
// Numbers preserved, dot becomes hyphen
|
||||||
|
assert_eq!(slugify("Version 2.0"), "version-2-0");
|
||||||
|
|
||||||
|
// Leading/trailing spaces trimmed
|
||||||
|
assert_eq!(slugify(" Padded "), "padded");
|
||||||
|
|
||||||
|
// Mixed case → lowercase
|
||||||
|
assert_eq!(slugify("CamelCase"), "camelcase");
|
||||||
|
|
||||||
|
// Consecutive special chars → single hyphen
|
||||||
|
assert_eq!(slugify("A -- B"), "a-b");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,4 +216,96 @@ mod tests {
|
|||||||
fn test_relative_prefix_depth_2() {
|
fn test_relative_prefix_depth_2() {
|
||||||
assert_eq!(relative_prefix("/blog/posts/foo.html"), "../..");
|
assert_eq!(relative_prefix("/blog/posts/foo.html"), "../..");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toc_config_fallback() {
|
||||||
|
use crate::content::Frontmatter;
|
||||||
|
|
||||||
|
// Create configs with different toc defaults
|
||||||
|
let config_toc_true = SiteConfig {
|
||||||
|
title: "Test".to_string(),
|
||||||
|
author: "Test".to_string(),
|
||||||
|
base_url: "https://test.com".to_string(),
|
||||||
|
paths: crate::config::PathsConfig::default(),
|
||||||
|
nav: crate::config::NavConfig {
|
||||||
|
nested: false,
|
||||||
|
toc: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let config_toc_false = SiteConfig {
|
||||||
|
title: "Test".to_string(),
|
||||||
|
author: "Test".to_string(),
|
||||||
|
base_url: "https://test.com".to_string(),
|
||||||
|
paths: crate::config::PathsConfig::default(),
|
||||||
|
nav: crate::config::NavConfig {
|
||||||
|
nested: false,
|
||||||
|
toc: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frontmatter with explicit toc: true
|
||||||
|
let fm_explicit_true = Frontmatter {
|
||||||
|
title: "Test".to_string(),
|
||||||
|
description: None,
|
||||||
|
date: None,
|
||||||
|
tags: vec![],
|
||||||
|
weight: None,
|
||||||
|
link_to: None,
|
||||||
|
nav_label: None,
|
||||||
|
section_type: None,
|
||||||
|
template: None,
|
||||||
|
toc: Some(true),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frontmatter with explicit toc: false
|
||||||
|
let fm_explicit_false = Frontmatter {
|
||||||
|
title: "Test".to_string(),
|
||||||
|
description: None,
|
||||||
|
date: None,
|
||||||
|
tags: vec![],
|
||||||
|
weight: None,
|
||||||
|
link_to: None,
|
||||||
|
nav_label: None,
|
||||||
|
section_type: None,
|
||||||
|
template: None,
|
||||||
|
toc: Some(false),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frontmatter with no toc specified (None)
|
||||||
|
let fm_none = Frontmatter {
|
||||||
|
title: "Test".to_string(),
|
||||||
|
description: None,
|
||||||
|
date: None,
|
||||||
|
tags: vec![],
|
||||||
|
weight: None,
|
||||||
|
link_to: None,
|
||||||
|
nav_label: None,
|
||||||
|
section_type: None,
|
||||||
|
template: None,
|
||||||
|
toc: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Explicit true overrides config false
|
||||||
|
let ctx = FrontmatterContext::new(&fm_explicit_true, &config_toc_false);
|
||||||
|
assert!(
|
||||||
|
ctx.toc,
|
||||||
|
"explicit toc: true should override config toc: false"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Explicit false overrides config true
|
||||||
|
let ctx = FrontmatterContext::new(&fm_explicit_false, &config_toc_true);
|
||||||
|
assert!(
|
||||||
|
!ctx.toc,
|
||||||
|
"explicit toc: false should override config toc: true"
|
||||||
|
);
|
||||||
|
|
||||||
|
// None falls back to config true
|
||||||
|
let ctx = FrontmatterContext::new(&fm_none, &config_toc_true);
|
||||||
|
assert!(ctx.toc, "toc: None should fall back to config toc: true");
|
||||||
|
|
||||||
|
// None falls back to config false
|
||||||
|
let ctx = FrontmatterContext::new(&fm_none, &config_toc_false);
|
||||||
|
assert!(!ctx.toc, "toc: None should fall back to config toc: false");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user