use chrono::NaiveDate;
use lazyspec::engine::document::{DocMeta, DocType, RelationType, Status};
#[test]
fn parse_frontmatter_from_markdown() {
let content = r#"---
title: "Adopt Event Sourcing"
type: adr
status: draft
author: jkaloger
date: 2026-03-04
tags: [architecture, events]
related:
- implements: rfcs/RFC-001-event-sourcing.md
---
## Context
Some body content here.
"#;
let meta = DocMeta::parse(content).unwrap();
assert_eq!(meta.title, "Adopt Event Sourcing");
assert_eq!(meta.doc_type, DocType::new("adr"));
assert_eq!(meta.status, Status::Draft);
assert_eq!(meta.author, "jkaloger");
assert_eq!(meta.date, NaiveDate::from_ymd_opt(2026, 3, 4).unwrap());
assert_eq!(meta.tags, vec!["architecture", "events"]);
assert_eq!(meta.related.len(), 1);
assert_eq!(meta.related[0].rel_type, RelationType::Implements);
assert_eq!(meta.related[0].target, "rfcs/RFC-001-event-sourcing.md");
}
#[test]
fn parse_frontmatter_minimal() {
let content = r#"---
title: "Simple Doc"
type: rfc
status: review
author: someone
date: 2026-01-01
tags: []
---
Body.
"#;
let meta = DocMeta::parse(content).unwrap();
assert_eq!(meta.title, "Simple Doc");
assert_eq!(meta.doc_type, DocType::new("rfc"));
assert!(meta.related.is_empty());
}
#[test]
fn parse_frontmatter_invalid_yaml() {
let content = "no frontmatter here";
assert!(DocMeta::parse(content).is_err());
}
#[test]
fn extract_body_skips_frontmatter() {
let content = r#"---
title: "Test"
type: story
status: draft
author: a
date: 2026-01-01
tags: []
---
## Body
Content here.
"#;
let body = DocMeta::extract_body(content).unwrap();
assert!(body.contains("## Body"));
assert!(body.contains("Content here."));
assert!(!body.contains("title:"));
}
#[test]
fn validate_ignore_defaults_to_false() {
let content = r#"---
title: "No Ignore Flag"
type: rfc
status: draft
author: someone
date: 2026-01-01
tags: []
---
Body.
"#;
let meta = DocMeta::parse(content).unwrap();
assert!(!meta.validate_ignore);
}
#[test]
fn validate_ignore_parsed_when_true() {
let content = r#"---
title: "Legacy Doc"
type: rfc
status: draft
author: someone
date: 2026-01-01
tags: []
validate-ignore: true
---
Body.
"#;
let meta = DocMeta::parse(content).unwrap();
assert!(meta.validate_ignore);
}
#[test]
fn relation_type_display() {
use lazyspec::engine::document::RelationType;
assert_eq!(format!("{}", RelationType::Implements), "implements");
assert_eq!(format!("{}", RelationType::Supersedes), "supersedes");
assert_eq!(format!("{}", RelationType::Blocks), "blocks");
assert_eq!(format!("{}", RelationType::RelatedTo), "related-to");
}
#[test]
fn relation_type_fromstr_display_roundtrip() {
use lazyspec::engine::document::RelationType;
for canonical in RelationType::ALL_STRS {
let parsed: RelationType = canonical.parse().unwrap();
assert_eq!(parsed.to_string(), canonical);
}
}
#[test]
fn relation_type_fromstr_rejects_unknown() {
assert!("garbage".parse::<RelationType>().is_err());
}
#[test]
fn relation_type_fromstr_accepts_space_variant() {
let rt: RelationType = "related to".parse().unwrap();
assert_eq!(rt, RelationType::RelatedTo);
}
#[test]
fn doctype_new_lowercases_input() {
assert_eq!(DocType::new("RFC"), DocType::new("rfc"));
assert_eq!(DocType::new("Adr"), DocType::new("adr"));
assert_eq!(DocType::new("STORY"), DocType::new("story"));
}
#[test]
fn doctype_display_returns_lowercase() {
assert_eq!(format!("{}", DocType::new("RFC")), "rfc");
assert_eq!(format!("{}", DocType::new("custom")), "custom");
}
#[test]
fn doctype_fromstr_accepts_any_string() {
let dt: DocType = "something-custom".parse().unwrap();
assert_eq!(dt, DocType::new("something-custom"));
}
#[test]
fn doctype_constants() {
assert_eq!(DocType::RFC, "rfc");
assert_eq!(DocType::STORY, "story");
assert_eq!(DocType::ITERATION, "iteration");
assert_eq!(DocType::ADR, "adr");
}
#[test]
fn doctype_deserializes_lowercase() {
let content = r#"---
title: "Custom Type Doc"
type: SomeCustomType
status: draft
author: someone
date: 2026-01-01
tags: []
---
Body.
"#;
let meta = DocMeta::parse(content).unwrap();
assert_eq!(meta.doc_type, DocType::new("somecustomtype"));
}