metis_docs_cli/commands/
validate.rs1use anyhow::Result;
2use clap::Args;
3use metis_core::application::services::document::DocumentValidationService;
4use std::path::PathBuf;
5
6#[derive(Args)]
7pub struct ValidateCommand {
8 pub file_path: PathBuf,
10}
11
12impl ValidateCommand {
13 pub async fn execute(&self) -> Result<()> {
14 let service = DocumentValidationService::new();
16 let result = service.validate_document(&self.file_path).await;
17
18 match result {
19 Ok(validation_result) => {
20 if validation_result.is_valid {
21 println!(
22 "✓ Valid {} document: {}",
23 validation_result.document_type,
24 self.file_path.display()
25 );
26 Ok(())
27 } else {
28 println!("✗ Invalid document: {}", self.file_path.display());
29 for error in &validation_result.errors {
30 println!(" - {}", error);
31 }
32 anyhow::bail!("Document validation failed")
33 }
34 }
35 Err(e) => {
36 println!("✗ Error validating document: {}", self.file_path.display());
37 println!(" Error: {}", e);
38 Err(e.into())
39 }
40 }
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use crate::commands::InitCommand;
48 use std::fs;
49 use tempfile::tempdir;
50
51 #[tokio::test]
52 async fn test_validate_command_missing_file() {
53 let temp_dir = tempdir().unwrap();
54 let original_dir = std::env::current_dir().ok();
55
56 std::env::set_current_dir(temp_dir.path()).unwrap();
58
59 let cmd = ValidateCommand {
60 file_path: PathBuf::from("nonexistent.md"),
61 };
62
63 let result = cmd.execute().await;
64
65 if let Some(original) = original_dir {
67 let _ = std::env::set_current_dir(&original);
68 }
69
70 assert!(result.is_err());
71 assert!(result
72 .unwrap_err()
73 .to_string()
74 .contains("File does not exist"));
75 }
76
77 #[tokio::test]
78 async fn test_validate_command_valid_vision() {
79 let temp_dir = tempdir().unwrap();
80 let original_dir = std::env::current_dir().ok();
81
82 std::env::set_current_dir(temp_dir.path()).unwrap();
84
85 let init_cmd = InitCommand {
87 name: Some("Test Project".to_string()),
88 preset: None,
89 strategies: None,
90 initiatives: None,
91 prefix: None,
92 };
93 init_cmd.execute().await.unwrap();
94
95 let vision_path = temp_dir.path().join(".metis/vision.md");
96
97 let cmd = ValidateCommand {
98 file_path: vision_path,
99 };
100
101 let result = cmd.execute().await;
102
103 if let Some(original) = original_dir {
105 let _ = std::env::set_current_dir(&original);
106 }
107
108 assert!(result.is_ok());
109 }
110
111 #[tokio::test]
112 async fn test_validate_command_invalid_document() {
113 let temp_dir = tempdir().unwrap();
114 let original_dir = std::env::current_dir().ok();
115
116 std::env::set_current_dir(temp_dir.path()).unwrap();
118
119 let invalid_path = temp_dir.path().join("invalid.md");
121 fs::write(
122 &invalid_path,
123 "# Invalid Document\n\nThis has no frontmatter.",
124 )
125 .unwrap();
126
127 let cmd = ValidateCommand {
128 file_path: invalid_path,
129 };
130
131 let result = cmd.execute().await;
132
133 if let Some(original) = original_dir {
135 let _ = std::env::set_current_dir(&original);
136 }
137
138 assert!(result.is_err());
139 }
140}