#[cfg(test)] #[allow(clippy::module_inception)] mod tests { use std::collections::HashMap; use std::path::PathBuf; use tempfile::TempDir; use crate::tools::guidance::*; fn create_test_system_status() -> SystemStatus { let paths = SystemPaths { provisioning_root: PathBuf::from("/test"), workspace_dir: Some(PathBuf::from("/test/workspace")), docs_dir: PathBuf::from("/test/docs"), config_dir: PathBuf::from("/test/config"), }; SystemStatus { nushell_version: Some("0.107.1".to_string()), workspace_configured: true, providers: vec!["aws".to_string(), "upcloud".to_string()], orchestrator_running: true, services_status: HashMap::new(), issues: Vec::new(), paths, metadata: HashMap::new(), } } #[test] fn test_system_status_creation() { let status = create_test_system_status(); assert!(status.nushell_version.is_some()); assert_eq!(status.providers.len(), 2); assert!(status.workspace_configured); assert!(status.orchestrator_running); } #[test] fn test_issue_severity_ordering() { assert!(IssueSeverity::Critical > IssueSeverity::Error); assert!(IssueSeverity::Error > IssueSeverity::Warning); assert!(IssueSeverity::Warning > IssueSeverity::Info); } #[test] fn test_health_status_variants() { let statuses = [ HealthStatus::Healthy, HealthStatus::Degraded, HealthStatus::Unhealthy, HealthStatus::Unknown, ]; assert_eq!(statuses.len(), 4); assert_eq!(HealthStatus::Healthy, HealthStatus::Healthy); } #[test] fn test_risk_level_variants() { let risk_low = RiskLevel::Low; let risk_medium = RiskLevel::Medium; let risk_high = RiskLevel::High; assert_eq!(risk_low, RiskLevel::Low); assert_ne!(risk_low, risk_high); } #[test] fn test_next_action_priority() { let action = NextAction { command: "test".to_string(), description: "test action".to_string(), docs_link: "docs/test.md".to_string(), expected_outcome: "success".to_string(), priority: 1, }; assert_eq!(action.priority, 1); assert!(!action.command.is_empty()); } #[test] fn test_doc_reference_relevance() { let doc = DocReference { path: "docs/test.md".to_string(), title: "Test Document".to_string(), snippet: "This is a test snippet".to_string(), relevance: 0.95, section: Some("Introduction".to_string()), }; assert!(doc.relevance > 0.9); assert!(doc.relevance <= 1.0); } #[test] fn test_validation_result_with_errors() { let result = ValidationResult { valid: false, errors: vec![ValidationError { message: "Test error".to_string(), path: "config.toml".to_string(), line: Some(10), fix: Some("Fix it".to_string()), }], warnings: Vec::new(), suggestions: Vec::new(), docs: Vec::new(), }; assert!(!result.valid); assert_eq!(result.errors.len(), 1); assert_eq!(result.errors[0].line, Some(10)); } #[test] fn test_diagnosis_with_fixes() { let diagnosis = Diagnosis { error: "Nushell not found".to_string(), root_cause: "Nushell is not installed".to_string(), fixes: vec![Fix { description: "Install Nushell".to_string(), commands: vec!["brew install nushell".to_string()], expected_outcome: "Nushell installed".to_string(), risk: RiskLevel::Low, }], related_docs: Vec::new(), confidence: 0.95, }; assert_eq!(diagnosis.fixes.len(), 1); assert!(diagnosis.confidence > 0.9); assert_eq!(diagnosis.fixes[0].risk, RiskLevel::Low); } #[test] fn test_system_status_tool_creation() { let _tool = SystemStatusTool::new(PathBuf::from("/test")); // Tool created successfully - type check is the test } #[test] fn test_next_action_tool_creation() { let _tool = NextActionTool::new(PathBuf::from("/test")); // Tool created successfully - type check is the test } #[test] fn test_doc_finder_tool_creation() { let _tool = DocFinderTool::new(PathBuf::from("/test")); // Tool created successfully - type check is the test } #[test] fn test_troubleshooter_tool_creation() { let _tool = TroubleshooterTool::new(PathBuf::from("/test")); // Tool created successfully - type check is the test } #[test] fn test_config_validator_tool_creation() { let _tool = ConfigValidatorTool::new(PathBuf::from("/test")); // Tool created successfully - type check is the test } #[test] fn test_system_status_with_issues() { let mut status = create_test_system_status(); status.issues.push(Issue { severity: IssueSeverity::Warning, category: "Configuration".to_string(), description: "Test warning".to_string(), fix: Some("Run command".to_string()), docs_link: Some("docs/help.md".to_string()), }); assert_eq!(status.issues.len(), 1); assert_eq!(status.issues[0].severity, IssueSeverity::Warning); } #[test] fn test_service_status_healthy() { let service = ServiceStatus { name: "orchestrator".to_string(), running: true, version: Some("1.0.0".to_string()), health: HealthStatus::Healthy, last_checked: "2025-10-10T00:00:00Z".to_string(), }; assert!(service.running); assert_eq!(service.health, HealthStatus::Healthy); assert!(service.version.is_some()); } #[test] fn test_next_action_tool_suggest_with_critical_issue() { let tool = NextActionTool::new(PathBuf::from("/test")); let mut status = create_test_system_status(); // Add critical issue status.issues.push(Issue { severity: IssueSeverity::Critical, category: "Prerequisites".to_string(), description: "Nushell not installed".to_string(), fix: Some("brew install nushell".to_string()), docs_link: Some("docs/setup.md".to_string()), }); let result = tool.suggest_next_action(&status); assert!(result.is_ok()); let action = result.unwrap(); assert_eq!(action.priority, 1); assert!(action.command.contains("brew install nushell")); } #[test] fn test_next_action_tool_workspace_not_configured() { let tool = NextActionTool::new(PathBuf::from("/test")); let mut status = create_test_system_status(); status.workspace_configured = false; let result = tool.suggest_next_action(&status); assert!(result.is_ok()); let action = result.unwrap(); assert_eq!(action.priority, 2); assert!(action.command.contains("workspace init")); } #[test] fn test_next_action_tool_no_providers() { let tool = NextActionTool::new(PathBuf::from("/test")); let mut status = create_test_system_status(); status.providers.clear(); let result = tool.suggest_next_action(&status); assert!(result.is_ok()); let action = result.unwrap(); assert_eq!(action.priority, 3); assert!(action.command.contains("discover providers")); } #[test] fn test_next_action_tool_orchestrator_not_running() { let tool = NextActionTool::new(PathBuf::from("/test")); let mut status = create_test_system_status(); status.orchestrator_running = false; let result = tool.suggest_next_action(&status); assert!(result.is_ok()); let action = result.unwrap(); assert_eq!(action.priority, 4); assert!(action.command.contains("orchestrator")); } #[test] fn test_troubleshooter_nushell_error() { let tool = TroubleshooterTool::new(PathBuf::from("/test")); let status = create_test_system_status(); let result = tool.diagnose_issue("command not found: nu", &status); assert!(result.is_ok()); let diagnosis = result.unwrap(); assert!(diagnosis.confidence > 0.9); assert!(diagnosis.root_cause.contains("Nushell")); assert!(!diagnosis.fixes.is_empty()); } #[test] fn test_troubleshooter_workspace_error() { let tool = TroubleshooterTool::new(PathBuf::from("/test")); let status = create_test_system_status(); let result = tool.diagnose_issue("workspace not found", &status); assert!(result.is_ok()); let diagnosis = result.unwrap(); assert!(diagnosis.confidence > 0.8); assert!(diagnosis.fixes.iter().any(|f| f .commands .iter() .any(|c: &String| c.contains("workspace init")))); } #[test] fn test_troubleshooter_orchestrator_error() { let tool = TroubleshooterTool::new(PathBuf::from("/test")); let status = create_test_system_status(); let result = tool.diagnose_issue("connection refused to orchestrator", &status); assert!(result.is_ok()); let diagnosis = result.unwrap(); assert!(diagnosis.confidence > 0.8); assert!(diagnosis .fixes .iter() .any(|f| f.description.contains("orchestrator"))); } #[test] fn test_troubleshooter_provider_error() { let tool = TroubleshooterTool::new(PathBuf::from("/test")); let status = create_test_system_status(); let result = tool.diagnose_issue("provider aws not configured", &status); assert!(result.is_ok()); let diagnosis = result.unwrap(); assert!(!diagnosis.fixes.is_empty()); } #[test] fn test_config_validator_nonexistent_file() { let tool = ConfigValidatorTool::new(PathBuf::from("/test")); let result = tool.validate_config("nonexistent.toml"); assert!(result.is_ok()); let validation = result.unwrap(); assert!(!validation.valid); assert!(!validation.errors.is_empty()); } #[test] fn test_multiple_next_actions() { let tool = NextActionTool::new(PathBuf::from("/test")); let mut status = create_test_system_status(); // Add multiple issues status.issues.push(Issue { severity: IssueSeverity::Critical, category: "Prerequisites".to_string(), description: "Critical issue 1".to_string(), fix: Some("fix 1".to_string()), docs_link: None, }); status.issues.push(Issue { severity: IssueSeverity::Critical, category: "Prerequisites".to_string(), description: "Critical issue 2".to_string(), fix: Some("fix 2".to_string()), docs_link: None, }); let result = tool.suggest_multiple_actions(&status, 3); assert!(result.is_ok()); let actions = result.unwrap(); assert!(actions.len() <= 3); assert!(actions.iter().all(|a| a.priority <= 2)); } #[test] fn test_system_paths_structure() { let paths = SystemPaths { provisioning_root: PathBuf::from("/usr/local/provisioning"), workspace_dir: Some(PathBuf::from("/workspace")), docs_dir: PathBuf::from("/usr/local/provisioning/docs"), config_dir: PathBuf::from("/usr/local/provisioning/config"), }; assert_eq!( paths.provisioning_root, PathBuf::from("/usr/local/provisioning") ); assert!(paths.workspace_dir.is_some()); } #[test] fn test_fix_risk_levels() { let low_risk_fix = Fix { description: "Safe fix".to_string(), commands: vec!["echo test".to_string()], expected_outcome: "Success".to_string(), risk: RiskLevel::Low, }; let high_risk_fix = Fix { description: "Dangerous fix".to_string(), commands: vec!["rm -rf /".to_string()], expected_outcome: "Disaster".to_string(), risk: RiskLevel::High, }; assert_eq!(low_risk_fix.risk, RiskLevel::Low); assert_eq!(high_risk_fix.risk, RiskLevel::High); assert_ne!(low_risk_fix.risk, high_risk_fix.risk); } #[test] fn test_validation_with_warnings_only() { let result = ValidationResult { valid: true, errors: Vec::new(), warnings: vec![ValidationWarning { message: "Consider updating".to_string(), path: "config.yaml".to_string(), recommendation: "Use newer format".to_string(), }], suggestions: vec!["Use TOML instead".to_string()], docs: Vec::new(), }; assert!(result.valid); assert!(result.errors.is_empty()); assert_eq!(result.warnings.len(), 1); assert_eq!(result.suggestions.len(), 1); } #[test] fn test_serialization_system_status() { let status = create_test_system_status(); let json = serde_json::to_string(&status); assert!(json.is_ok()); let deserialized: Result = serde_json::from_str(&json.unwrap()); assert!(deserialized.is_ok()); } #[test] fn test_serialization_next_action() { let action = NextAction { command: "test command".to_string(), description: "test description".to_string(), docs_link: "docs/test.md".to_string(), expected_outcome: "success".to_string(), priority: 1, }; let json = serde_json::to_string(&action); assert!(json.is_ok()); let deserialized: Result = serde_json::from_str(&json.unwrap()); assert!(deserialized.is_ok()); } #[test] fn test_serialization_diagnosis() { let diagnosis = Diagnosis { error: "test error".to_string(), root_cause: "test cause".to_string(), fixes: Vec::new(), related_docs: Vec::new(), confidence: 0.5, }; let json = serde_json::to_string(&diagnosis); assert!(json.is_ok()); let deserialized: Result = serde_json::from_str(&json.unwrap()); assert!(deserialized.is_ok()); } }