use chronicle::graph::Chronicle;
use chronicle::validation::{ValidationError, ValidationWarning};
use std::path::Path;
fn data_path(scenario: &str) -> std::path::PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests/data/invalid")
.join(scenario)
}
#[test]
fn catches_dangling_reference() {
let c = Chronicle::from_directory(&data_path("dangling_ref")).unwrap();
let report = c.validate();
let dangling: Vec<_> = report.errors.iter().filter(|e| {
matches!(e, ValidationError::DanglingReference { target_id, .. } if target_id == "nonexistent_actor")
}).collect();
assert!(
!dangling.is_empty(),
"should catch dangling reference to nonexistent_actor"
);
}
#[test]
fn catches_state_violation_dead_actor() {
let c = Chronicle::from_directory(&data_path("temporal_violation")).unwrap();
let report = c.validate();
let violations: Vec<_> = report
.errors
.iter()
.filter(|e| {
matches!(e, ValidationError::StateViolation { entity_id, event_id, .. }
if entity_id == "doomed_soldier" && event_id == "later_battle")
})
.collect();
assert!(
!violations.is_empty(),
"should catch dead actor participating in later event"
);
}
#[test]
fn catches_state_violation_destroyed_place() {
let c = Chronicle::from_directory(&data_path("state_violation")).unwrap();
let report = c.validate();
let violations: Vec<_> = report
.errors
.iter()
.filter(|e| {
matches!(e, ValidationError::StateViolation { entity_id, event_id, .. }
if entity_id == "ruined_city" && event_id == "impossible_market")
})
.collect();
assert!(
!violations.is_empty(),
"should catch event at destroyed location"
);
}
#[test]
fn catches_orphan_entity() {
let c = Chronicle::from_directory(&data_path("orphan")).unwrap();
let report = c.validate();
let orphans: Vec<_> = report.warnings.iter().filter(|w| {
matches!(w, ValidationWarning::OrphanEntity { entity_id } if entity_id == "forgotten_hermit")
}).collect();
assert!(
!orphans.is_empty(),
"should warn about orphaned forgotten_hermit"
);
let false_orphans: Vec<_> = report.warnings.iter().filter(|w| {
matches!(w, ValidationWarning::OrphanEntity { entity_id } if entity_id == "connected_faction")
}).collect();
assert!(
false_orphans.is_empty(),
"connected_faction should not be orphaned"
);
}
#[test]
fn catches_duplicate_id() {
let result = Chronicle::from_directory(&data_path("duplicate_id"));
let err = match result {
Err(e) => e,
Ok(_) => panic!("should fail to load duplicate IDs"),
};
let msg = err.to_string();
assert!(
msg.contains("duplicate_id"),
"error should mention the duplicate ID: {msg}"
);
}