From 56334dd7b101bf132a1e723052099cd8026bb6fb Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Wed, 24 Dec 2025 09:29:28 -0300 Subject: [PATCH] Update unit tests for basic keywords --- .../basic/basic_keywords_agent_reflection.rs | 217 +++++---- .../unit/basic/basic_keywords_code_sandbox.rs | 163 +++---- .../basic/basic_keywords_episodic_memory.rs | 219 +++++---- .../basic/basic_keywords_human_approval.rs | 283 ++++++------ tests/unit/basic/basic_keywords_on_change.rs | 415 ++++++++---------- tests/unit/basic/basic_keywords_on_email.rs | 386 ++++++++-------- tests/unit/basic/basic_keywords_play.rs | 188 ++++---- .../unit/basic/basic_keywords_set_schedule.rs | 334 +++++++------- 8 files changed, 1010 insertions(+), 1195 deletions(-) diff --git a/tests/unit/basic/basic_keywords_agent_reflection.rs b/tests/unit/basic/basic_keywords_agent_reflection.rs index 18d8933..4ede355 100644 --- a/tests/unit/basic/basic_keywords_agent_reflection.rs +++ b/tests/unit/basic/basic_keywords_agent_reflection.rs @@ -1,133 +1,114 @@ +use botserver::basic::keywords::agent_reflection::{ + extract_insights_from_text, ReflectionConfig, ReflectionResult, ReflectionType, +}; +use uuid::Uuid; +#[test] +fn test_reflection_type_from_str() { + assert_eq!( + ReflectionType::from("conversation_quality"), + ReflectionType::ConversationQuality + ); + assert_eq!( + ReflectionType::from("quality"), + ReflectionType::ConversationQuality + ); + assert_eq!( + ReflectionType::from("tool_usage"), + ReflectionType::ToolUsage + ); + assert_eq!( + ReflectionType::from("performance"), + ReflectionType::Performance + ); +} +#[test] +fn test_reflection_config_default() { + let config = ReflectionConfig::default(); + assert!(!config.enabled); + assert_eq!(config.interval, 10); + assert!(!config.auto_apply); +} -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] +#[test] +fn test_reflection_result_new() { + let bot_id = Uuid::new_v4(); + let session_id = Uuid::new_v4(); + let result = ReflectionResult::new(bot_id, session_id, ReflectionType::ConversationQuality); + assert_eq!(result.bot_id, bot_id); + assert_eq!(result.session_id, session_id); + assert_eq!(result.score, 0.0); + assert!(result.insights.is_empty()); +} - #[test] +#[test] +fn test_reflection_result_from_json() { + let json_response = r#"{ + "score": 7.5, + "key_insights": ["Users prefer concise responses", "Technical questions need more detail"], + "improvements": ["Add more examples", "Improve response time"], + "positive_patterns": ["Good greeting", "Clear explanations"] + }"#; + let result = ReflectionResult::from_llm_response( + Uuid::new_v4(), + Uuid::new_v4(), + ReflectionType::ConversationQuality, + json_response, + 10, + ); - fn test_reflection_type_from_str() { - assert_eq!( - ReflectionType::from("conversation_quality"), - ReflectionType::ConversationQuality - ); - assert_eq!( - ReflectionType::from("quality"), - ReflectionType::ConversationQuality - ); - assert_eq!( - ReflectionType::from("tool_usage"), - ReflectionType::ToolUsage - ); - assert_eq!( - ReflectionType::from("performance"), - ReflectionType::Performance - ); - } + assert_eq!(result.score, 7.5); + assert_eq!(result.insights.len(), 2); + assert_eq!(result.improvements.len(), 2); + assert_eq!(result.positive_patterns.len(), 2); +} - #[test] +#[test] +fn test_reflection_result_needs_improvement() { + let mut result = + ReflectionResult::new(Uuid::new_v4(), Uuid::new_v4(), ReflectionType::Performance); + result.score = 5.0; + assert!(result.needs_improvement(6.0)); - fn test_reflection_config_default() { - let config = ReflectionConfig::default(); - assert!(!config.enabled); - assert_eq!(config.interval, 10); - assert!(!config.auto_apply); - } + result.score = 8.0; + assert!(!result.needs_improvement(6.0)); +} - #[test] +#[test] +fn test_extract_insights_from_text() { + let text = "Here are some insights:\n\ + 1. Users prefer short responses\n\ + 2. Technical questions need examples\n\ + - Consider adding more context\n\ + • Improve response time"; + let insights = extract_insights_from_text(text); + assert!(!insights.is_empty()); +} - fn test_reflection_result_new() { - let bot_id = Uuid::new_v4(); - let session_id = Uuid::new_v4(); - let result = ReflectionResult::new(bot_id, session_id, ReflectionType::ConversationQuality); +#[test] +fn test_reflection_type_prompt_template() { + let template = ReflectionType::ConversationQuality.prompt_template(); + assert!(template.contains("{conversation}")); + assert!(template.contains("JSON format")); +} - assert_eq!(result.bot_id, bot_id); - assert_eq!(result.session_id, session_id); - assert_eq!(result.score, 0.0); - assert!(result.insights.is_empty()); - } +#[test] +fn test_reflection_result_summary() { + let mut result = + ReflectionResult::new(Uuid::new_v4(), Uuid::new_v4(), ReflectionType::Performance); + result.score = 7.5; + result.messages_analyzed = 15; + result.insights = vec!["Insight 1".to_string(), "Insight 2".to_string()]; + result.improvements = vec!["Improvement 1".to_string()]; - #[test] - - - fn test_reflection_result_from_json() { - let json_response = r#"{ - "score": 7.5, - "key_insights": ["Users prefer concise responses", "Technical questions need more detail"], - "improvements": ["Add more examples", "Improve response time"], - "positive_patterns": ["Good greeting", "Clear explanations"] - }"#; - - let result = ReflectionResult::from_llm_response( - Uuid::new_v4(), - Uuid::new_v4(), - ReflectionType::ConversationQuality, - json_response, - 10, - ); - - assert_eq!(result.score, 7.5); - assert_eq!(result.insights.len(), 2); - assert_eq!(result.improvements.len(), 2); - assert_eq!(result.positive_patterns.len(), 2); - } - - #[test] - - - fn test_reflection_result_needs_improvement() { - let mut result = - ReflectionResult::new(Uuid::new_v4(), Uuid::new_v4(), ReflectionType::Performance); - - result.score = 5.0; - assert!(result.needs_improvement(6.0)); - - result.score = 8.0; - assert!(!result.needs_improvement(6.0)); - } - - #[test] - - - fn test_extract_insights_from_text() { - let text = "Here are some insights:\n\ - 1. Users prefer short responses\n\ - 2. Technical questions need examples\n\ - - Consider adding more context\n\ - • Improve response time"; - - let insights = extract_insights_from_text(text); - assert!(!insights.is_empty()); - } - - #[test] - - - fn test_reflection_type_prompt_template() { - let template = ReflectionType::ConversationQuality.prompt_template(); - assert!(template.contains("{conversation}")); - assert!(template.contains("JSON format")); - } - - #[test] - - - fn test_reflection_result_summary() { - let mut result = - ReflectionResult::new(Uuid::new_v4(), Uuid::new_v4(), ReflectionType::Performance); - result.score = 7.5; - result.messages_analyzed = 15; - result.insights = vec!["Insight 1".to_string(), "Insight 2".to_string()]; - result.improvements = vec!["Improvement 1".to_string()]; - - let summary = result.summary(); - assert!(summary.contains("7.5")); - assert!(summary.contains("15")); - assert!(summary.contains("2")); - assert!(summary.contains("1")); - } \ No newline at end of file + let summary = result.summary(); + assert!(summary.contains("7.5")); + assert!(summary.contains("15")); + assert!(summary.contains("2")); + assert!(summary.contains("1")); +} diff --git a/tests/unit/basic/basic_keywords_code_sandbox.rs b/tests/unit/basic/basic_keywords_code_sandbox.rs index af35dd0..b21cacc 100644 --- a/tests/unit/basic/basic_keywords_code_sandbox.rs +++ b/tests/unit/basic/basic_keywords_code_sandbox.rs @@ -1,102 +1,81 @@ +use botserver::basic::keywords::code_sandbox::{ + generate_node_lxc_config, generate_python_lxc_config, CodeLanguage, ExecutionResult, + SandboxConfig, SandboxRuntime, +}; +#[test] +fn test_sandbox_config_default() { + let config = SandboxConfig::default(); + assert!(config.enabled); + assert_eq!(config.timeout_seconds, 30); + assert_eq!(config.memory_limit_mb, 256); + assert!(!config.network_enabled); +} +#[test] +fn test_execution_result_success() { + let result = ExecutionResult::success("Hello, World!".to_string(), String::new(), 100); + assert!(result.is_success()); + assert_eq!(result.output(), "Hello, World!"); +} -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] +#[test] +fn test_execution_result_error() { + let result = ExecutionResult::error("Something went wrong"); + assert!(!result.is_success()); + assert!(result.output().contains("Error")); +} +#[test] +fn test_execution_result_timeout() { + let result = ExecutionResult::timeout(); + assert!(!result.is_success()); + assert!(result.timed_out); +} - #[test] +#[test] +fn test_code_language_from_str() { + assert_eq!(CodeLanguage::from("python"), CodeLanguage::Python); + assert_eq!(CodeLanguage::from("PYTHON"), CodeLanguage::Python); + assert_eq!(CodeLanguage::from("py"), CodeLanguage::Python); + assert_eq!(CodeLanguage::from("javascript"), CodeLanguage::JavaScript); + assert_eq!(CodeLanguage::from("js"), CodeLanguage::JavaScript); + assert_eq!(CodeLanguage::from("node"), CodeLanguage::JavaScript); + assert_eq!(CodeLanguage::from("bash"), CodeLanguage::Bash); +} +#[test] +fn test_code_language_file_extension() { + assert_eq!(CodeLanguage::Python.file_extension(), "py"); + assert_eq!(CodeLanguage::JavaScript.file_extension(), "js"); + assert_eq!(CodeLanguage::Bash.file_extension(), "sh"); +} - fn test_sandbox_config_default() { - let config = SandboxConfig::default(); - assert!(config.enabled); - assert_eq!(config.timeout_seconds, 30); - assert_eq!(config.memory_limit_mb, 256); - assert!(!config.network_enabled); - } +#[test] +fn test_code_language_interpreter() { + assert_eq!(CodeLanguage::Python.interpreter(), "python3"); + assert_eq!(CodeLanguage::JavaScript.interpreter(), "node"); + assert_eq!(CodeLanguage::Bash.interpreter(), "bash"); +} - #[test] +#[test] +fn test_sandbox_runtime_from_str() { + assert_eq!(SandboxRuntime::from("lxc"), SandboxRuntime::LXC); + assert_eq!(SandboxRuntime::from("docker"), SandboxRuntime::Docker); + assert_eq!( + SandboxRuntime::from("firecracker"), + SandboxRuntime::Firecracker + ); + assert_eq!(SandboxRuntime::from("unknown"), SandboxRuntime::Process); +} +#[test] +fn test_lxc_config_generation() { + let python_config = generate_python_lxc_config(); + assert!(python_config.contains("gb-sandbox-python")); + assert!(python_config.contains("memory.max")); - fn test_execution_result_success() { - let result = ExecutionResult::success("Hello, World!".to_string(), String::new(), 100); - assert!(result.is_success()); - assert_eq!(result.output(), "Hello, World!"); - } - - #[test] - - - fn test_execution_result_error() { - let result = ExecutionResult::error("Something went wrong"); - assert!(!result.is_success()); - assert!(result.output().contains("Error")); - } - - #[test] - - - fn test_execution_result_timeout() { - let result = ExecutionResult::timeout(); - assert!(!result.is_success()); - assert!(result.timed_out); - } - - #[test] - - - fn test_code_language_from_str() { - assert_eq!(CodeLanguage::from("python"), CodeLanguage::Python); - assert_eq!(CodeLanguage::from("PYTHON"), CodeLanguage::Python); - assert_eq!(CodeLanguage::from("py"), CodeLanguage::Python); - assert_eq!(CodeLanguage::from("javascript"), CodeLanguage::JavaScript); - assert_eq!(CodeLanguage::from("js"), CodeLanguage::JavaScript); - assert_eq!(CodeLanguage::from("node"), CodeLanguage::JavaScript); - assert_eq!(CodeLanguage::from("bash"), CodeLanguage::Bash); - } - - #[test] - - - fn test_code_language_file_extension() { - assert_eq!(CodeLanguage::Python.file_extension(), "py"); - assert_eq!(CodeLanguage::JavaScript.file_extension(), "js"); - assert_eq!(CodeLanguage::Bash.file_extension(), "sh"); - } - - #[test] - - - fn test_code_language_interpreter() { - assert_eq!(CodeLanguage::Python.interpreter(), "python3"); - assert_eq!(CodeLanguage::JavaScript.interpreter(), "node"); - assert_eq!(CodeLanguage::Bash.interpreter(), "bash"); - } - - #[test] - - - fn test_sandbox_runtime_from_str() { - assert_eq!(SandboxRuntime::from("lxc"), SandboxRuntime::LXC); - assert_eq!(SandboxRuntime::from("docker"), SandboxRuntime::Docker); - assert_eq!( - SandboxRuntime::from("firecracker"), - SandboxRuntime::Firecracker - ); - assert_eq!(SandboxRuntime::from("unknown"), SandboxRuntime::Process); - } - - #[test] - - - fn test_lxc_config_generation() { - let python_config = generate_python_lxc_config(); - assert!(python_config.contains("gb-sandbox-python")); - assert!(python_config.contains("memory.max")); - - let node_config = generate_node_lxc_config(); - assert!(node_config.contains("gb-sandbox-node")); - assert!(node_config.contains("/usr/bin/node")); - } \ No newline at end of file + let node_config = generate_node_lxc_config(); + assert!(node_config.contains("gb-sandbox-node")); + assert!(node_config.contains("/usr/bin/node")); +} diff --git a/tests/unit/basic/basic_keywords_episodic_memory.rs b/tests/unit/basic/basic_keywords_episodic_memory.rs index 176f171..fd77a3c 100644 --- a/tests/unit/basic/basic_keywords_episodic_memory.rs +++ b/tests/unit/basic/basic_keywords_episodic_memory.rs @@ -1,131 +1,114 @@ +use botserver::basic::keywords::episodic_memory::{ + extract_json, ConversationMessage, Episode, EpisodicMemoryConfig, EpisodicMemoryManager, + ResolutionStatus, Sentiment, +}; +use chrono::Utc; +use rhai::Map; +use uuid::Uuid; +#[test] +fn test_default_config() { + let config = EpisodicMemoryConfig::default(); + assert!(config.enabled); + assert_eq!(config.threshold, 4); + assert_eq!(config.history, 2); + assert_eq!(config.max_episodes, 100); +} +#[test] +fn test_should_summarize() { + let manager = EpisodicMemoryManager::new(EpisodicMemoryConfig { + enabled: true, + threshold: 4, + history: 2, + auto_summarize: true, + ..Default::default() + }); -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] + assert!(!manager.should_summarize(2)); + assert!(manager.should_summarize(4)); + assert!(manager.should_summarize(10)); +} -use serde_json; +#[test] +fn test_extract_json() { + let response = "Here's the summary:\n```json\n{\"summary\": \"test\"}\n```\n"; + assert!(extract_json(response).is_ok()); + let response = "The result is {\"summary\": \"test\"}"; + assert!(extract_json(response).is_ok()); +} +#[test] +fn test_generate_summary_prompt() { + let manager = EpisodicMemoryManager::new(EpisodicMemoryConfig::default()); + let messages = vec![ConversationMessage { + id: Uuid::new_v4(), + role: "user".to_string(), + content: "Hello".to_string(), + timestamp: Utc::now(), + }]; - #[test] + let prompt = manager.generate_summary_prompt(&messages); + assert!(prompt.contains("CONVERSATION:")); + assert!(prompt.contains("Hello")); +} +#[test] +fn test_parse_summary_response() { + let manager = EpisodicMemoryManager::new(EpisodicMemoryConfig::default()); + let response = r#"{ + "summary": "User asked about billing", + "key_topics": ["billing", "payment"], + "decisions": [], + "action_items": [], + "sentiment": {"score": 0.5, "label": "positive", "confidence": 0.8}, + "resolution": "resolved" + }"#; - fn test_default_config() { - let config = EpisodicMemoryConfig::default(); - assert!(config.enabled); - assert_eq!(config.threshold, 4); - assert_eq!(config.history, 2); - assert_eq!(config.max_episodes, 100); - } + let messages = vec![ConversationMessage { + id: Uuid::new_v4(), + role: "user".to_string(), + content: "What's my balance?".to_string(), + timestamp: Utc::now(), + }]; - #[test] + let episode = manager.parse_summary_response( + response, + &messages, + Uuid::new_v4(), + Uuid::new_v4(), + Uuid::new_v4(), + ); + assert!(episode.is_ok()); + let ep = episode.unwrap(); + assert_eq!(ep.summary, "User asked about billing"); + assert_eq!(ep.key_topics, vec!["billing", "payment"]); + assert_eq!(ep.resolution, ResolutionStatus::Resolved); +} - fn test_should_summarize() { - let manager = EpisodicMemoryManager::new(EpisodicMemoryConfig { - enabled: true, - threshold: 4, - history: 2, - auto_summarize: true, - ..Default::default() - }); +#[test] +fn test_episode_to_dynamic() { + let episode = Episode { + id: Uuid::new_v4(), + user_id: Uuid::new_v4(), + bot_id: Uuid::new_v4(), + session_id: Uuid::new_v4(), + summary: "Test summary".to_string(), + key_topics: vec!["topic1".to_string()], + decisions: vec![], + action_items: vec![], + sentiment: Sentiment::default(), + resolution: ResolutionStatus::Resolved, + message_count: 5, + message_ids: vec![], + created_at: Utc::now(), + conversation_start: Utc::now(), + conversation_end: Utc::now(), + metadata: serde_json::json!({}), + }; - assert!(!manager.should_summarize(2)); - assert!(manager.should_summarize(4)); - assert!(manager.should_summarize(10)); - } - - #[test] - - - fn test_extract_json() { - - let response = "Here's the summary:\n```json\n{\"summary\": \"test\"}\n```\n"; - assert!(extract_json(response).is_ok()); - - - let response = "The result is {\"summary\": \"test\"}"; - assert!(extract_json(response).is_ok()); - } - - #[test] - - - fn test_generate_summary_prompt() { - let manager = EpisodicMemoryManager::new(EpisodicMemoryConfig::default()); - let messages = vec![ConversationMessage { - id: Uuid::new_v4(), - role: "user".to_string(), - content: "Hello".to_string(), - timestamp: Utc::now(), - }]; - - let prompt = manager.generate_summary_prompt(&messages); - assert!(prompt.contains("CONVERSATION:")); - assert!(prompt.contains("Hello")); - } - - #[test] - - - fn test_parse_summary_response() { - let manager = EpisodicMemoryManager::new(EpisodicMemoryConfig::default()); - let response = r#"{ - "summary": "User asked about billing", - "key_topics": ["billing", "payment"], - "decisions": [], - "action_items": [], - "sentiment": {"score": 0.5, "label": "positive", "confidence": 0.8}, - "resolution": "resolved" - }"#; - - let messages = vec![ConversationMessage { - id: Uuid::new_v4(), - role: "user".to_string(), - content: "What's my balance?".to_string(), - timestamp: Utc::now(), - }]; - - let episode = manager.parse_summary_response( - response, - &messages, - Uuid::new_v4(), - Uuid::new_v4(), - Uuid::new_v4(), - ); - - assert!(episode.is_ok()); - let ep = episode.unwrap(); - assert_eq!(ep.summary, "User asked about billing"); - assert_eq!(ep.key_topics, vec!["billing", "payment"]); - assert_eq!(ep.resolution, ResolutionStatus::Resolved); - } - - #[test] - - - fn test_episode_to_dynamic() { - let episode = Episode { - id: Uuid::new_v4(), - user_id: Uuid::new_v4(), - bot_id: Uuid::new_v4(), - session_id: Uuid::new_v4(), - summary: "Test summary".to_string(), - key_topics: vec!["topic1".to_string()], - decisions: vec![], - action_items: vec![], - sentiment: Sentiment::default(), - resolution: ResolutionStatus::Resolved, - message_count: 5, - message_ids: vec![], - created_at: Utc::now(), - conversation_start: Utc::now(), - conversation_end: Utc::now(), - metadata: serde_json::json!({}), - }; - - let dynamic = episode.to_dynamic(); - assert!(dynamic.is::()); - } \ No newline at end of file + let dynamic = episode.to_dynamic(); + assert!(dynamic.is::()); +} diff --git a/tests/unit/basic/basic_keywords_human_approval.rs b/tests/unit/basic/basic_keywords_human_approval.rs index de3b01b..d74c935 100644 --- a/tests/unit/basic/basic_keywords_human_approval.rs +++ b/tests/unit/basic/basic_keywords_human_approval.rs @@ -1,167 +1,148 @@ +use botserver::basic::keywords::human_approval::{ + ApprovalChannel, ApprovalConfig, ApprovalDecision, ApprovalManager, ApprovalStatus, +}; +use chrono::{Duration, Utc}; +use rhai::Map; +use uuid::Uuid; +#[test] +fn test_default_config() { + let config = ApprovalConfig::default(); + assert!(config.enabled); + assert_eq!(config.default_timeout, 3600); + assert_eq!(config.max_reminders, 3); +} +#[test] +fn test_create_request() { + let manager = ApprovalManager::new(ApprovalConfig::default()); + let request = manager.create_request( + Uuid::new_v4(), + Uuid::new_v4(), + Uuid::new_v4(), + "expense_approval", + ApprovalChannel::Email, + "manager@example.com", + serde_json::json!({"amount": 1000}), + "Please approve expense", + None, + None, + ); -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] + assert_eq!(request.status, ApprovalStatus::Pending); + assert_eq!(request.approval_type, "expense_approval"); + assert!(request.expires_at > Utc::now()); +} -use serde_json; +#[test] +fn test_is_expired() { + let manager = ApprovalManager::new(ApprovalConfig::default()); + let mut request = manager.create_request( + Uuid::new_v4(), + Uuid::new_v4(), + Uuid::new_v4(), + "test", + ApprovalChannel::Email, + "test@example.com", + serde_json::json!({}), + "Test", + Some(1), + None, + ); + assert!(!manager.is_expired(&request)); + request.expires_at = Utc::now() - Duration::seconds(10); + assert!(manager.is_expired(&request)); +} - #[test] +#[test] +fn test_process_decision() { + let manager = ApprovalManager::new(ApprovalConfig::default()); + let mut request = manager.create_request( + Uuid::new_v4(), + Uuid::new_v4(), + Uuid::new_v4(), + "test", + ApprovalChannel::Email, + "test@example.com", + serde_json::json!({}), + "Test", + None, + None, + ); + manager.process_decision( + &mut request, + ApprovalDecision::Approve, + "manager@example.com", + Some("Looks good!".to_string()), + ); - fn test_default_config() { - let config = ApprovalConfig::default(); - assert!(config.enabled); - assert_eq!(config.default_timeout, 3600); - assert_eq!(config.max_reminders, 3); - } + assert_eq!(request.status, ApprovalStatus::Approved); + assert_eq!(request.decision, Some(ApprovalDecision::Approve)); + assert_eq!(request.decided_by, Some("manager@example.com".to_string())); + assert_eq!(request.comments, Some("Looks good!".to_string())); +} - #[test] +#[test] +fn test_evaluate_condition() { + let manager = ApprovalManager::new(ApprovalConfig::default()); + let context = serde_json::json!({ + "amount": 15000, + "priority": 2 + }); + assert!(manager + .evaluate_condition("amount > 10000", &context) + .unwrap()); + assert!(!manager + .evaluate_condition("amount > 20000", &context) + .unwrap()); + assert!(manager + .evaluate_condition("priority == 2", &context) + .unwrap()); +} - fn test_create_request() { - let manager = ApprovalManager::new(ApprovalConfig::default()); - let request = manager.create_request( - Uuid::new_v4(), - Uuid::new_v4(), - Uuid::new_v4(), - "expense_approval", - ApprovalChannel::Email, - "manager@example.com", - serde_json::json!({"amount": 1000}), - "Please approve expense", - None, - None, - ); +#[test] +fn test_handle_timeout_with_default() { + let manager = ApprovalManager::new(ApprovalConfig::default()); + let mut request = manager.create_request( + Uuid::new_v4(), + Uuid::new_v4(), + Uuid::new_v4(), + "test", + ApprovalChannel::Email, + "test@example.com", + serde_json::json!({}), + "Test", + None, + Some(ApprovalDecision::Approve), + ); - assert_eq!(request.status, ApprovalStatus::Pending); - assert_eq!(request.approval_type, "expense_approval"); - assert!(request.expires_at > Utc::now()); - } + manager.handle_timeout(&mut request); - #[test] + assert_eq!(request.status, ApprovalStatus::Approved); + assert_eq!(request.decision, Some(ApprovalDecision::Approve)); + assert_eq!(request.decided_by, Some("system:timeout".to_string())); +} +#[test] +fn test_request_to_dynamic() { + let manager = ApprovalManager::new(ApprovalConfig::default()); + let request = manager.create_request( + Uuid::new_v4(), + Uuid::new_v4(), + Uuid::new_v4(), + "test", + ApprovalChannel::Email, + "test@example.com", + serde_json::json!({"key": "value"}), + "Test message", + None, + None, + ); - fn test_is_expired() { - let manager = ApprovalManager::new(ApprovalConfig::default()); - let mut request = manager.create_request( - Uuid::new_v4(), - Uuid::new_v4(), - Uuid::new_v4(), - "test", - ApprovalChannel::Email, - "test@example.com", - serde_json::json!({}), - "Test", - Some(1), - None, - ); - - assert!(!manager.is_expired(&request)); - - - request.expires_at = Utc::now() - Duration::seconds(10); - assert!(manager.is_expired(&request)); - } - - #[test] - - - fn test_process_decision() { - let manager = ApprovalManager::new(ApprovalConfig::default()); - let mut request = manager.create_request( - Uuid::new_v4(), - Uuid::new_v4(), - Uuid::new_v4(), - "test", - ApprovalChannel::Email, - "test@example.com", - serde_json::json!({}), - "Test", - None, - None, - ); - - manager.process_decision( - &mut request, - ApprovalDecision::Approve, - "manager@example.com", - Some("Looks good!".to_string()), - ); - - assert_eq!(request.status, ApprovalStatus::Approved); - assert_eq!(request.decision, Some(ApprovalDecision::Approve)); - assert_eq!(request.decided_by, Some("manager@example.com".to_string())); - assert_eq!(request.comments, Some("Looks good!".to_string())); - } - - #[test] - - - fn test_evaluate_condition() { - let manager = ApprovalManager::new(ApprovalConfig::default()); - let context = serde_json::json!({ - "amount": 15000, - "priority": 2 - }); - - assert!(manager - .evaluate_condition("amount > 10000", &context) - .unwrap()); - assert!(!manager - .evaluate_condition("amount > 20000", &context) - .unwrap()); - assert!(manager - .evaluate_condition("priority == 2", &context) - .unwrap()); - } - - #[test] - - - fn test_handle_timeout_with_default() { - let manager = ApprovalManager::new(ApprovalConfig::default()); - let mut request = manager.create_request( - Uuid::new_v4(), - Uuid::new_v4(), - Uuid::new_v4(), - "test", - ApprovalChannel::Email, - "test@example.com", - serde_json::json!({}), - "Test", - None, - Some(ApprovalDecision::Approve), - ); - - manager.handle_timeout(&mut request); - - assert_eq!(request.status, ApprovalStatus::Approved); - assert_eq!(request.decision, Some(ApprovalDecision::Approve)); - assert_eq!(request.decided_by, Some("system:timeout".to_string())); - } - - #[test] - - - fn test_request_to_dynamic() { - let manager = ApprovalManager::new(ApprovalConfig::default()); - let request = manager.create_request( - Uuid::new_v4(), - Uuid::new_v4(), - Uuid::new_v4(), - "test", - ApprovalChannel::Email, - "test@example.com", - serde_json::json!({"key": "value"}), - "Test message", - None, - None, - ); - - let dynamic = request.to_dynamic(); - assert!(dynamic.is::()); - } \ No newline at end of file + let dynamic = request.to_dynamic(); + assert!(dynamic.is::()); +} diff --git a/tests/unit/basic/basic_keywords_on_change.rs b/tests/unit/basic/basic_keywords_on_change.rs index a757ac5..d002839 100644 --- a/tests/unit/basic/basic_keywords_on_change.rs +++ b/tests/unit/basic/basic_keywords_on_change.rs @@ -1,235 +1,208 @@ +use botserver::basic::keywords::on_change::{ + detect_provider_from_email, is_cloud_path, parse_folder_path, sanitize_path_for_filename, + ChangeEventType, FolderChangeEvent, FolderMonitor, FolderProvider, +}; +use uuid::Uuid; +#[test] +fn test_parse_folder_path_account() { + let (provider, email, path) = parse_folder_path("account://user@gmail.com/Documents/invoices"); + assert_eq!(provider, FolderProvider::GDrive); + assert_eq!(email, Some("user@gmail.com".to_string())); + assert_eq!(path, "/Documents/invoices"); +} +#[test] +fn test_parse_folder_path_gdrive() { + let (provider, email, path) = parse_folder_path("gdrive:///shared/reports"); + assert_eq!(provider, FolderProvider::GDrive); + assert_eq!(email, None); + assert_eq!(path, "/shared/reports"); +} -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] +#[test] +fn test_parse_folder_path_onedrive() { + let (provider, email, path) = parse_folder_path("onedrive:///business/docs"); + assert_eq!(provider, FolderProvider::OneDrive); + assert_eq!(email, None); + assert_eq!(path, "/business/docs"); +} +#[test] +fn test_parse_folder_path_dropbox() { + let (provider, email, path) = parse_folder_path("dropbox:///team/assets"); + assert_eq!(provider, FolderProvider::Dropbox); + assert_eq!(email, None); + assert_eq!(path, "/team/assets"); +} - #[test] +#[test] +fn test_parse_folder_path_local() { + let (provider, email, path) = parse_folder_path("/home/user/documents"); + assert_eq!(provider, FolderProvider::Local); + assert_eq!(email, None); + assert_eq!(path, "/home/user/documents"); +} +#[test] +fn test_is_cloud_path() { + assert!(is_cloud_path("account://user@gmail.com/docs")); + assert!(is_cloud_path("gdrive:///shared")); + assert!(is_cloud_path("onedrive:///files")); + assert!(is_cloud_path("dropbox:///folder")); + assert!(!is_cloud_path("/local/path")); + assert!(!is_cloud_path("./relative/path")); +} - fn test_parse_folder_path_account() { - let (provider, email, path) = - parse_folder_path("account://user@gmail.com/Documents/invoices"); - assert_eq!(provider, FolderProvider::GDrive); - assert_eq!(email, Some("user@gmail.com".to_string())); - assert_eq!(path, "/Documents/invoices"); - } +#[test] +fn test_folder_provider_from_str() { + assert_eq!( + FolderProvider::from_str("gdrive"), + Some(FolderProvider::GDrive) + ); + assert_eq!( + FolderProvider::from_str("GDRIVE"), + Some(FolderProvider::GDrive) + ); + assert_eq!( + FolderProvider::from_str("googledrive"), + Some(FolderProvider::GDrive) + ); + assert_eq!( + FolderProvider::from_str("onedrive"), + Some(FolderProvider::OneDrive) + ); + assert_eq!( + FolderProvider::from_str("microsoft"), + Some(FolderProvider::OneDrive) + ); + assert_eq!( + FolderProvider::from_str("dropbox"), + Some(FolderProvider::Dropbox) + ); + assert_eq!( + FolderProvider::from_str("dbx"), + Some(FolderProvider::Dropbox) + ); + assert_eq!( + FolderProvider::from_str("local"), + Some(FolderProvider::Local) + ); + assert_eq!( + FolderProvider::from_str("filesystem"), + Some(FolderProvider::Local) + ); + assert_eq!(FolderProvider::from_str("unknown"), None); +} - #[test] +#[test] +fn test_change_event_type_from_str() { + assert_eq!( + ChangeEventType::from_str("create"), + Some(ChangeEventType::Create) + ); + assert_eq!( + ChangeEventType::from_str("created"), + Some(ChangeEventType::Create) + ); + assert_eq!( + ChangeEventType::from_str("modify"), + Some(ChangeEventType::Modify) + ); + assert_eq!( + ChangeEventType::from_str("changed"), + Some(ChangeEventType::Modify) + ); + assert_eq!( + ChangeEventType::from_str("delete"), + Some(ChangeEventType::Delete) + ); + assert_eq!( + ChangeEventType::from_str("removed"), + Some(ChangeEventType::Delete) + ); + assert_eq!( + ChangeEventType::from_str("rename"), + Some(ChangeEventType::Rename) + ); + assert_eq!( + ChangeEventType::from_str("move"), + Some(ChangeEventType::Move) + ); + assert_eq!(ChangeEventType::from_str("invalid"), None); +} +#[test] +fn test_sanitize_path() { + assert_eq!( + sanitize_path_for_filename("/home/user/docs"), + "_home_user_docs" + ); + assert_eq!( + sanitize_path_for_filename("C:\\Users\\docs"), + "c__users_docs" + ); + assert_eq!( + sanitize_path_for_filename("path with spaces"), + "path_with_spaces" + ); +} - fn test_parse_folder_path_gdrive() { - let (provider, email, path) = parse_folder_path("gdrive:///shared/reports"); - assert_eq!(provider, FolderProvider::GDrive); - assert_eq!(email, None); - assert_eq!(path, "/shared/reports"); - } +#[test] +fn test_folder_monitor_struct() { + let monitor = FolderMonitor { + id: Uuid::new_v4(), + bot_id: Uuid::new_v4(), + provider: "gdrive".to_string(), + account_email: Some("user@gmail.com".to_string()), + folder_path: "/my/folder".to_string(), + folder_id: Some("folder123".to_string()), + script_path: "on_change.rhai".to_string(), + is_active: true, + watch_subfolders: true, + event_types: vec!["create".to_string(), "modify".to_string()], + }; - #[test] + assert_eq!(monitor.provider, "gdrive"); + assert!(monitor.is_active); + assert!(monitor.watch_subfolders); + assert_eq!(monitor.account_email, Some("user@gmail.com".to_string())); +} +#[test] +fn test_folder_change_event_struct() { + let event = FolderChangeEvent { + id: Uuid::new_v4(), + monitor_id: Uuid::new_v4(), + event_type: "create".to_string(), + file_path: "/docs/new_file.pdf".to_string(), + file_id: Some("file123".to_string()), + file_name: Some("new_file.pdf".to_string()), + file_size: Some(1024), + mime_type: Some("application/pdf".to_string()), + old_path: None, + }; - fn test_parse_folder_path_onedrive() { - let (provider, email, path) = parse_folder_path("onedrive:///business/docs"); - assert_eq!(provider, FolderProvider::OneDrive); - assert_eq!(email, None); - assert_eq!(path, "/business/docs"); - } + assert_eq!(event.event_type, "create"); + assert_eq!(event.file_size, Some(1024)); +} - #[test] - - - fn test_parse_folder_path_dropbox() { - let (provider, email, path) = parse_folder_path("dropbox:///team/assets"); - assert_eq!(provider, FolderProvider::Dropbox); - assert_eq!(email, None); - assert_eq!(path, "/team/assets"); - } - - #[test] - - - fn test_parse_folder_path_local() { - let (provider, email, path) = parse_folder_path("/home/user/documents"); - assert_eq!(provider, FolderProvider::Local); - assert_eq!(email, None); - assert_eq!(path, "/home/user/documents"); - } - - #[test] - - - fn test_is_cloud_path() { - assert!(is_cloud_path("account://user@gmail.com/docs")); - assert!(is_cloud_path("gdrive:///shared")); - assert!(is_cloud_path("onedrive:///files")); - assert!(is_cloud_path("dropbox:///folder")); - assert!(!is_cloud_path("/local/path")); - assert!(!is_cloud_path("./relative/path")); - } - - #[test] - - - fn test_folder_provider_from_str() { - assert_eq!( - FolderProvider::from_str("gdrive"), - Some(FolderProvider::GDrive) - ); - assert_eq!( - FolderProvider::from_str("GDRIVE"), - Some(FolderProvider::GDrive) - ); - assert_eq!( - FolderProvider::from_str("googledrive"), - Some(FolderProvider::GDrive) - ); - assert_eq!( - FolderProvider::from_str("onedrive"), - Some(FolderProvider::OneDrive) - ); - assert_eq!( - FolderProvider::from_str("microsoft"), - Some(FolderProvider::OneDrive) - ); - assert_eq!( - FolderProvider::from_str("dropbox"), - Some(FolderProvider::Dropbox) - ); - assert_eq!( - FolderProvider::from_str("dbx"), - Some(FolderProvider::Dropbox) - ); - assert_eq!( - FolderProvider::from_str("local"), - Some(FolderProvider::Local) - ); - assert_eq!( - FolderProvider::from_str("filesystem"), - Some(FolderProvider::Local) - ); - assert_eq!(FolderProvider::from_str("unknown"), None); - } - - #[test] - - - fn test_change_event_type_from_str() { - assert_eq!( - ChangeEventType::from_str("create"), - Some(ChangeEventType::Create) - ); - assert_eq!( - ChangeEventType::from_str("created"), - Some(ChangeEventType::Create) - ); - assert_eq!( - ChangeEventType::from_str("modify"), - Some(ChangeEventType::Modify) - ); - assert_eq!( - ChangeEventType::from_str("changed"), - Some(ChangeEventType::Modify) - ); - assert_eq!( - ChangeEventType::from_str("delete"), - Some(ChangeEventType::Delete) - ); - assert_eq!( - ChangeEventType::from_str("removed"), - Some(ChangeEventType::Delete) - ); - assert_eq!( - ChangeEventType::from_str("rename"), - Some(ChangeEventType::Rename) - ); - assert_eq!( - ChangeEventType::from_str("move"), - Some(ChangeEventType::Move) - ); - assert_eq!(ChangeEventType::from_str("invalid"), None); - } - - #[test] - - - fn test_sanitize_path() { - assert_eq!( - sanitize_path_for_filename("/home/user/docs"), - "_home_user_docs" - ); - assert_eq!( - sanitize_path_for_filename("C:\\Users\\docs"), - "c__users_docs" - ); - assert_eq!( - sanitize_path_for_filename("path with spaces"), - "path_with_spaces" - ); - } - - #[test] - - - fn test_folder_monitor_struct() { - let monitor = FolderMonitor { - id: Uuid::new_v4(), - bot_id: Uuid::new_v4(), - provider: "gdrive".to_string(), - account_email: Some("user@gmail.com".to_string()), - folder_path: "/my/folder".to_string(), - folder_id: Some("folder123".to_string()), - script_path: "on_change.rhai".to_string(), - is_active: true, - watch_subfolders: true, - event_types: vec!["create".to_string(), "modify".to_string()], - }; - - assert_eq!(monitor.provider, "gdrive"); - assert!(monitor.is_active); - assert!(monitor.watch_subfolders); - assert_eq!(monitor.account_email, Some("user@gmail.com".to_string())); - } - - #[test] - - - fn test_folder_change_event_struct() { - let event = FolderChangeEvent { - id: Uuid::new_v4(), - monitor_id: Uuid::new_v4(), - event_type: "create".to_string(), - file_path: "/docs/new_file.pdf".to_string(), - file_id: Some("file123".to_string()), - file_name: Some("new_file.pdf".to_string()), - file_size: Some(1024), - mime_type: Some("application/pdf".to_string()), - old_path: None, - }; - - assert_eq!(event.event_type, "create"); - assert_eq!(event.file_size, Some(1024)); - } - - #[test] - - - fn test_detect_provider_from_email() { - assert_eq!( - detect_provider_from_email("user@gmail.com"), - FolderProvider::GDrive - ); - assert_eq!( - detect_provider_from_email("user@outlook.com"), - FolderProvider::OneDrive - ); - assert_eq!( - detect_provider_from_email("user@hotmail.com"), - FolderProvider::OneDrive - ); - assert_eq!( - detect_provider_from_email("user@company.com"), - FolderProvider::GDrive - ); - } \ No newline at end of file +#[test] +fn test_detect_provider_from_email() { + assert_eq!( + detect_provider_from_email("user@gmail.com"), + FolderProvider::GDrive + ); + assert_eq!( + detect_provider_from_email("user@outlook.com"), + FolderProvider::OneDrive + ); + assert_eq!( + detect_provider_from_email("user@hotmail.com"), + FolderProvider::OneDrive + ); + assert_eq!( + detect_provider_from_email("user@company.com"), + FolderProvider::GDrive + ); +} diff --git a/tests/unit/basic/basic_keywords_on_email.rs b/tests/unit/basic/basic_keywords_on_email.rs index 8837f4c..12e04f5 100644 --- a/tests/unit/basic/basic_keywords_on_email.rs +++ b/tests/unit/basic/basic_keywords_on_email.rs @@ -1,224 +1,198 @@ +use botserver::basic::keywords::on_email::{ + is_email_path, parse_email_path, sanitize_email_for_filename, EmailAttachment, EmailMonitor, + EmailReceivedEvent, +}; +use uuid::Uuid; +#[test] +fn test_email_monitor_struct() { + let monitor = EmailMonitor { + id: Uuid::new_v4(), + bot_id: Uuid::new_v4(), + email_address: "test@example.com".to_string(), + script_path: "on_email_test.rhai".to_string(), + is_active: true, + filter_from: None, + filter_subject: None, + }; + assert_eq!(monitor.email_address, "test@example.com"); + assert!(monitor.is_active); + assert!(monitor.filter_from.is_none()); + assert!(monitor.filter_subject.is_none()); +} -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] +#[test] +fn test_email_monitor_with_filters() { + let monitor = EmailMonitor { + id: Uuid::new_v4(), + bot_id: Uuid::new_v4(), + email_address: "orders@company.com".to_string(), + script_path: "on_email_orders.rhai".to_string(), + is_active: true, + filter_from: Some("supplier@vendor.com".to_string()), + filter_subject: Some("Invoice".to_string()), + }; + assert_eq!(monitor.email_address, "orders@company.com"); + assert_eq!(monitor.filter_from, Some("supplier@vendor.com".to_string())); + assert_eq!(monitor.filter_subject, Some("Invoice".to_string())); +} - #[test] +#[test] +fn test_email_attachment_struct() { + let attachment = EmailAttachment { + filename: "document.pdf".to_string(), + mime_type: "application/pdf".to_string(), + size: 1024, + }; + assert_eq!(attachment.filename, "document.pdf"); + assert_eq!(attachment.mime_type, "application/pdf"); + assert_eq!(attachment.size, 1024); +} - fn test_email_monitor_struct() { - let monitor = EmailMonitor { - id: Uuid::new_v4(), - bot_id: Uuid::new_v4(), - email_address: "test@example.com".to_string(), - script_path: "on_email_test.rhai".to_string(), - is_active: true, - filter_from: None, - filter_subject: None, - }; +#[test] +fn test_email_received_event_struct() { + let event = EmailReceivedEvent { + id: Uuid::new_v4(), + monitor_id: Uuid::new_v4(), + message_uid: 12345, + message_id: Some("".to_string()), + from_address: "sender@example.com".to_string(), + to_addresses: vec!["recipient@example.com".to_string()], + subject: Some("Test Subject".to_string()), + has_attachments: true, + attachments: vec![EmailAttachment { + filename: "file.pdf".to_string(), + mime_type: "application/pdf".to_string(), + size: 2048, + }], + }; - assert_eq!(monitor.email_address, "test@example.com"); - assert!(monitor.is_active); - assert!(monitor.filter_from.is_none()); - assert!(monitor.filter_subject.is_none()); - } + assert_eq!(event.message_uid, 12345); + assert_eq!(event.from_address, "sender@example.com"); + assert!(event.has_attachments); + assert_eq!(event.attachments.len(), 1); + assert_eq!(event.attachments[0].filename, "file.pdf"); +} - #[test] +#[test] +fn test_parse_email_path_basic() { + let result = parse_email_path("email://user@gmail.com"); + assert!(result.is_some()); + let (email, folder) = result.unwrap(); + assert_eq!(email, "user@gmail.com"); + assert!(folder.is_none()); +} +#[test] +fn test_parse_email_path_with_folder() { + let result = parse_email_path("email://user@gmail.com/INBOX"); + assert!(result.is_some()); + let (email, folder) = result.unwrap(); + assert_eq!(email, "user@gmail.com"); + assert_eq!(folder, Some("INBOX".to_string())); +} - fn test_email_monitor_with_filters() { - let monitor = EmailMonitor { - id: Uuid::new_v4(), - bot_id: Uuid::new_v4(), - email_address: "orders@company.com".to_string(), - script_path: "on_email_orders.rhai".to_string(), - is_active: true, - filter_from: Some("supplier@vendor.com".to_string()), - filter_subject: Some("Invoice".to_string()), - }; +#[test] +fn test_parse_email_path_invalid() { + assert!(parse_email_path("user@gmail.com").is_none()); + assert!(parse_email_path("mailto:user@gmail.com").is_none()); + assert!(parse_email_path("/local/path").is_none()); +} - assert_eq!(monitor.email_address, "orders@company.com"); - assert_eq!(monitor.filter_from, Some("supplier@vendor.com".to_string())); - assert_eq!(monitor.filter_subject, Some("Invoice".to_string())); - } +#[test] +fn test_is_email_path() { + assert!(is_email_path("email://user@gmail.com")); + assert!(is_email_path("email://user@company.com/INBOX")); + assert!(!is_email_path("user@gmail.com")); + assert!(!is_email_path("mailto:user@gmail.com")); + assert!(!is_email_path("account://user@gmail.com")); +} - #[test] +#[test] +fn test_sanitize_email_for_filename() { + assert_eq!( + sanitize_email_for_filename("user@gmail.com"), + "user_at_gmail_com" + ); + assert_eq!( + sanitize_email_for_filename("test.user@company.co.uk"), + "test_user_at_company_co_uk" + ); + assert_eq!( + sanitize_email_for_filename("USER@EXAMPLE.COM"), + "user_at_example_com" + ); +} +#[test] +fn test_email_event_without_attachments() { + let event = EmailReceivedEvent { + id: Uuid::new_v4(), + monitor_id: Uuid::new_v4(), + message_uid: 1, + message_id: None, + from_address: "no-reply@system.com".to_string(), + to_addresses: vec![], + subject: None, + has_attachments: false, + attachments: vec![], + }; - fn test_email_attachment_struct() { - let attachment = EmailAttachment { - filename: "document.pdf".to_string(), + assert!(!event.has_attachments); + assert!(event.attachments.is_empty()); + assert!(event.subject.is_none()); +} + +#[test] +fn test_multiple_to_addresses() { + let event = EmailReceivedEvent { + id: Uuid::new_v4(), + monitor_id: Uuid::new_v4(), + message_uid: 999, + message_id: Some("".to_string()), + from_address: "sender@example.com".to_string(), + to_addresses: vec![ + "user1@example.com".to_string(), + "user2@example.com".to_string(), + "user3@example.com".to_string(), + ], + subject: Some("Group Message".to_string()), + has_attachments: false, + attachments: vec![], + }; + + assert_eq!(event.to_addresses.len(), 3); + assert!(event + .to_addresses + .contains(&"user2@example.com".to_string())); +} + +#[test] +fn test_multiple_attachments() { + let attachments = vec![ + EmailAttachment { + filename: "doc1.pdf".to_string(), mime_type: "application/pdf".to_string(), size: 1024, - }; + }, + EmailAttachment { + filename: "image.png".to_string(), + mime_type: "image/png".to_string(), + size: 2048, + }, + EmailAttachment { + filename: "data.xlsx".to_string(), + mime_type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + .to_string(), + size: 4096, + }, + ]; - assert_eq!(attachment.filename, "document.pdf"); - assert_eq!(attachment.mime_type, "application/pdf"); - assert_eq!(attachment.size, 1024); - } - - #[test] - - - fn test_email_received_event_struct() { - let event = EmailReceivedEvent { - id: Uuid::new_v4(), - monitor_id: Uuid::new_v4(), - message_uid: 12345, - message_id: Some("".to_string()), - from_address: "sender@example.com".to_string(), - to_addresses: vec!["recipient@example.com".to_string()], - subject: Some("Test Subject".to_string()), - has_attachments: true, - attachments: vec![EmailAttachment { - filename: "file.pdf".to_string(), - mime_type: "application/pdf".to_string(), - size: 2048, - }], - }; - - assert_eq!(event.message_uid, 12345); - assert_eq!(event.from_address, "sender@example.com"); - assert!(event.has_attachments); - assert_eq!(event.attachments.len(), 1); - assert_eq!(event.attachments[0].filename, "file.pdf"); - } - - #[test] - - - fn test_parse_email_path_basic() { - let result = parse_email_path("email://user@gmail.com"); - assert!(result.is_some()); - let (email, folder) = result.unwrap(); - assert_eq!(email, "user@gmail.com"); - assert!(folder.is_none()); - } - - #[test] - - - fn test_parse_email_path_with_folder() { - let result = parse_email_path("email://user@gmail.com/INBOX"); - assert!(result.is_some()); - let (email, folder) = result.unwrap(); - assert_eq!(email, "user@gmail.com"); - assert_eq!(folder, Some("INBOX".to_string())); - } - - #[test] - - - fn test_parse_email_path_invalid() { - assert!(parse_email_path("user@gmail.com").is_none()); - assert!(parse_email_path("mailto:user@gmail.com").is_none()); - assert!(parse_email_path("/local/path").is_none()); - } - - #[test] - - - fn test_is_email_path() { - assert!(is_email_path("email://user@gmail.com")); - assert!(is_email_path("email://user@company.com/INBOX")); - assert!(!is_email_path("user@gmail.com")); - assert!(!is_email_path("mailto:user@gmail.com")); - assert!(!is_email_path("account://user@gmail.com")); - } - - #[test] - - - fn test_sanitize_email_for_filename() { - assert_eq!( - sanitize_email_for_filename("user@gmail.com"), - "user_at_gmail_com" - ); - assert_eq!( - sanitize_email_for_filename("test.user@company.co.uk"), - "test_user_at_company_co_uk" - ); - assert_eq!( - sanitize_email_for_filename("USER@EXAMPLE.COM"), - "user_at_example_com" - ); - } - - #[test] - - - fn test_email_event_without_attachments() { - let event = EmailReceivedEvent { - id: Uuid::new_v4(), - monitor_id: Uuid::new_v4(), - message_uid: 1, - message_id: None, - from_address: "no-reply@system.com".to_string(), - to_addresses: vec![], - subject: None, - has_attachments: false, - attachments: vec![], - }; - - assert!(!event.has_attachments); - assert!(event.attachments.is_empty()); - assert!(event.subject.is_none()); - } - - #[test] - - - fn test_multiple_to_addresses() { - let event = EmailReceivedEvent { - id: Uuid::new_v4(), - monitor_id: Uuid::new_v4(), - message_uid: 999, - message_id: Some("".to_string()), - from_address: "sender@example.com".to_string(), - to_addresses: vec![ - "user1@example.com".to_string(), - "user2@example.com".to_string(), - "user3@example.com".to_string(), - ], - subject: Some("Group Message".to_string()), - has_attachments: false, - attachments: vec![], - }; - - assert_eq!(event.to_addresses.len(), 3); - assert!(event - .to_addresses - .contains(&"user2@example.com".to_string())); - } - - #[test] - - - fn test_multiple_attachments() { - let attachments = vec![ - EmailAttachment { - filename: "doc1.pdf".to_string(), - mime_type: "application/pdf".to_string(), - size: 1024, - }, - EmailAttachment { - filename: "image.png".to_string(), - mime_type: "image/png".to_string(), - size: 2048, - }, - EmailAttachment { - filename: "data.xlsx".to_string(), - mime_type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" - .to_string(), - size: 4096, - }, - ]; - - assert_eq!(attachments.len(), 3); - assert_eq!(attachments[0].filename, "doc1.pdf"); - assert_eq!(attachments[1].mime_type, "image/png"); - assert_eq!(attachments[2].size, 4096); - } \ No newline at end of file + assert_eq!(attachments.len(), 3); + assert_eq!(attachments[0].filename, "doc1.pdf"); + assert_eq!(attachments[1].mime_type, "image/png"); + assert_eq!(attachments[2].size, 4096); +} diff --git a/tests/unit/basic/basic_keywords_play.rs b/tests/unit/basic/basic_keywords_play.rs index 8e71c9a..9895216 100644 --- a/tests/unit/basic/basic_keywords_play.rs +++ b/tests/unit/basic/basic_keywords_play.rs @@ -1,110 +1,94 @@ +use botserver::basic::keywords::play::{ + detect_content_type, extract_title_from_source, ContentType, PlayOptions, +}; +#[test] +fn test_content_type_from_extension() { + assert_eq!(ContentType::from_extension("mp4"), ContentType::Video); + assert_eq!(ContentType::from_extension("MP3"), ContentType::Audio); + assert_eq!(ContentType::from_extension("png"), ContentType::Image); + assert_eq!(ContentType::from_extension("pdf"), ContentType::Pdf); + assert_eq!(ContentType::from_extension("rs"), ContentType::Code); + assert_eq!( + ContentType::from_extension("pptx"), + ContentType::Presentation + ); + assert_eq!( + ContentType::from_extension("xlsx"), + ContentType::Spreadsheet + ); + assert_eq!(ContentType::from_extension("md"), ContentType::Markdown); +} +#[test] +fn test_content_type_from_mime() { + assert_eq!(ContentType::from_mime("video/mp4"), ContentType::Video); + assert_eq!(ContentType::from_mime("audio/mpeg"), ContentType::Audio); + assert_eq!(ContentType::from_mime("image/png"), ContentType::Image); + assert_eq!(ContentType::from_mime("application/pdf"), ContentType::Pdf); +} -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] +#[test] +fn test_play_options_from_string() { + let opts = PlayOptions::from_string("autoplay,loop,muted"); + assert!(opts.autoplay); + assert!(opts.loop_content); + assert!(opts.muted); + assert!(!opts.fullscreen); + assert!(opts.controls); + let opts = PlayOptions::from_string("fullscreen,nocontrols,start=10,end=60"); + assert!(opts.fullscreen); + assert!(!opts.controls); + assert_eq!(opts.start_time, Some(10.0)); + assert_eq!(opts.end_time, Some(60.0)); - #[test] + let opts = PlayOptions::from_string("theme=dark,zoom=1.5,page=3"); + assert_eq!(opts.theme, Some("dark".to_string())); + assert_eq!(opts.zoom, Some(1.5)); + assert_eq!(opts.page, Some(3)); +} +#[test] +fn test_detect_content_type() { + assert_eq!( + detect_content_type("https://youtube.com/watch?v=123"), + ContentType::Video + ); + assert_eq!( + detect_content_type("https://example.com/video.mp4"), + ContentType::Video + ); + assert_eq!( + detect_content_type("https://imgur.com/abc123"), + ContentType::Image + ); + assert_eq!( + detect_content_type("presentation.pptx"), + ContentType::Presentation + ); + assert_eq!(detect_content_type("report.pdf"), ContentType::Pdf); + assert_eq!(detect_content_type("main.rs"), ContentType::Code); +} - fn test_content_type_from_extension() { - assert_eq!(ContentType::from_extension("mp4"), ContentType::Video); - assert_eq!(ContentType::from_extension("MP3"), ContentType::Audio); - assert_eq!(ContentType::from_extension("png"), ContentType::Image); - assert_eq!(ContentType::from_extension("pdf"), ContentType::Pdf); - assert_eq!(ContentType::from_extension("rs"), ContentType::Code); - assert_eq!( - ContentType::from_extension("pptx"), - ContentType::Presentation - ); - assert_eq!( - ContentType::from_extension("xlsx"), - ContentType::Spreadsheet - ); - assert_eq!(ContentType::from_extension("md"), ContentType::Markdown); - } +#[test] +fn test_extract_title_from_source() { + assert_eq!(extract_title_from_source("documents/report.pdf"), "report"); + assert_eq!( + extract_title_from_source("https://example.com/video.mp4?token=abc"), + "video" + ); + assert_eq!( + extract_title_from_source("presentation.pptx"), + "presentation" + ); +} - #[test] - - - fn test_content_type_from_mime() { - assert_eq!(ContentType::from_mime("video/mp4"), ContentType::Video); - assert_eq!(ContentType::from_mime("audio/mpeg"), ContentType::Audio); - assert_eq!(ContentType::from_mime("image/png"), ContentType::Image); - assert_eq!(ContentType::from_mime("application/pdf"), ContentType::Pdf); - } - - #[test] - - - fn test_play_options_from_string() { - let opts = PlayOptions::from_string("autoplay,loop,muted"); - assert!(opts.autoplay); - assert!(opts.loop_content); - assert!(opts.muted); - assert!(!opts.fullscreen); - assert!(opts.controls); - - let opts = PlayOptions::from_string("fullscreen,nocontrols,start=10,end=60"); - assert!(opts.fullscreen); - assert!(!opts.controls); - assert_eq!(opts.start_time, Some(10.0)); - assert_eq!(opts.end_time, Some(60.0)); - - let opts = PlayOptions::from_string("theme=dark,zoom=1.5,page=3"); - assert_eq!(opts.theme, Some("dark".to_string())); - assert_eq!(opts.zoom, Some(1.5)); - assert_eq!(opts.page, Some(3)); - } - - #[test] - - - fn test_detect_content_type() { - assert_eq!( - detect_content_type("https://youtube.com/watch?v=123"), - ContentType::Video - ); - assert_eq!( - detect_content_type("https://example.com/video.mp4"), - ContentType::Video - ); - assert_eq!( - detect_content_type("https://imgur.com/abc123"), - ContentType::Image - ); - assert_eq!( - detect_content_type("presentation.pptx"), - ContentType::Presentation - ); - assert_eq!(detect_content_type("report.pdf"), ContentType::Pdf); - assert_eq!(detect_content_type("main.rs"), ContentType::Code); - } - - #[test] - - - fn test_extract_title_from_source() { - assert_eq!(extract_title_from_source("documents/report.pdf"), "report"); - assert_eq!( - extract_title_from_source("https://example.com/video.mp4?token=abc"), - "video" - ); - assert_eq!( - extract_title_from_source("presentation.pptx"), - "presentation" - ); - } - - #[test] - - - fn test_player_component() { - assert_eq!(ContentType::Video.player_component(), "video-player"); - assert_eq!(ContentType::Audio.player_component(), "audio-player"); - assert_eq!(ContentType::Image.player_component(), "image-viewer"); - assert_eq!(ContentType::Pdf.player_component(), "pdf-viewer"); - assert_eq!(ContentType::Code.player_component(), "code-viewer"); - } \ No newline at end of file +#[test] +fn test_player_component() { + assert_eq!(ContentType::Video.player_component(), "video-player"); + assert_eq!(ContentType::Audio.player_component(), "audio-player"); + assert_eq!(ContentType::Image.player_component(), "image-viewer"); + assert_eq!(ContentType::Pdf.player_component(), "pdf-viewer"); + assert_eq!(ContentType::Code.player_component(), "code-viewer"); +} diff --git a/tests/unit/basic/basic_keywords_set_schedule.rs b/tests/unit/basic/basic_keywords_set_schedule.rs index ab68627..e1c012c 100644 --- a/tests/unit/basic/basic_keywords_set_schedule.rs +++ b/tests/unit/basic/basic_keywords_set_schedule.rs @@ -1,204 +1,164 @@ +use botserver::basic::keywords::set_schedule::parse_natural_schedule; +#[test] +fn test_every_minute() { + assert_eq!(parse_natural_schedule("every minute").unwrap(), "* * * * *"); +} +#[test] +fn test_every_n_minutes() { + assert_eq!( + parse_natural_schedule("every 5 minutes").unwrap(), + "*/5 * * * *" + ); + assert_eq!( + parse_natural_schedule("every 15 minutes").unwrap(), + "*/15 * * * *" + ); + assert_eq!( + parse_natural_schedule("every 30 minutes").unwrap(), + "*/30 * * * *" + ); +} -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] +#[test] +fn test_every_hour() { + assert_eq!(parse_natural_schedule("every hour").unwrap(), "0 * * * *"); + assert_eq!(parse_natural_schedule("hourly").unwrap(), "0 * * * *"); +} +#[test] +fn test_every_n_hours() { + assert_eq!( + parse_natural_schedule("every 2 hours").unwrap(), + "0 */2 * * *" + ); + assert_eq!( + parse_natural_schedule("every 6 hours").unwrap(), + "0 */6 * * *" + ); +} - #[test] +#[test] +fn test_every_day() { + assert_eq!(parse_natural_schedule("every day").unwrap(), "0 0 * * *"); + assert_eq!(parse_natural_schedule("daily").unwrap(), "0 0 * * *"); +} +#[test] +fn test_every_week() { + assert_eq!(parse_natural_schedule("every week").unwrap(), "0 0 * * 0"); + assert_eq!(parse_natural_schedule("weekly").unwrap(), "0 0 * * 0"); +} - fn test_every_minute() { - assert_eq!(parse_natural_schedule("every minute").unwrap(), "* * * * *"); - } +#[test] +fn test_every_month() { + assert_eq!(parse_natural_schedule("every month").unwrap(), "0 0 1 * *"); + assert_eq!(parse_natural_schedule("monthly").unwrap(), "0 0 1 * *"); +} - #[test] +#[test] +fn test_at_time() { + assert_eq!(parse_natural_schedule("at 9am").unwrap(), "0 9 * * *"); + assert_eq!(parse_natural_schedule("at 9:30am").unwrap(), "30 9 * * *"); + assert_eq!(parse_natural_schedule("at 2pm").unwrap(), "0 14 * * *"); + assert_eq!(parse_natural_schedule("at 14:00").unwrap(), "0 14 * * *"); + assert_eq!(parse_natural_schedule("at midnight").unwrap(), "0 0 * * *"); + assert_eq!(parse_natural_schedule("at noon").unwrap(), "0 12 * * *"); +} +#[test] +fn test_day_of_week() { + assert_eq!(parse_natural_schedule("every monday").unwrap(), "0 0 * * 1"); + assert_eq!(parse_natural_schedule("every friday").unwrap(), "0 0 * * 5"); + assert_eq!(parse_natural_schedule("every sunday").unwrap(), "0 0 * * 0"); +} - fn test_every_n_minutes() { - assert_eq!( - parse_natural_schedule("every 5 minutes").unwrap(), - "*/5 * * * *" - ); - assert_eq!( - parse_natural_schedule("every 15 minutes").unwrap(), - "*/15 * * * *" - ); - assert_eq!( - parse_natural_schedule("every 30 minutes").unwrap(), - "*/30 * * * *" - ); - } +#[test] +fn test_day_with_time() { + assert_eq!( + parse_natural_schedule("every monday at 9am").unwrap(), + "0 9 * * 1" + ); + assert_eq!( + parse_natural_schedule("every friday at 5pm").unwrap(), + "0 17 * * 5" + ); +} - #[test] +#[test] +fn test_weekdays() { + assert_eq!(parse_natural_schedule("weekdays").unwrap(), "0 0 * * 1-5"); + assert_eq!( + parse_natural_schedule("every weekday").unwrap(), + "0 0 * * 1-5" + ); + assert_eq!( + parse_natural_schedule("weekdays at 8am").unwrap(), + "0 8 * * 1-5" + ); +} +#[test] +fn test_weekends() { + assert_eq!(parse_natural_schedule("weekends").unwrap(), "0 0 * * 0,6"); + assert_eq!( + parse_natural_schedule("every weekend").unwrap(), + "0 0 * * 0,6" + ); +} - fn test_every_hour() { - assert_eq!(parse_natural_schedule("every hour").unwrap(), "0 * * * *"); - assert_eq!(parse_natural_schedule("hourly").unwrap(), "0 * * * *"); - } +#[test] +fn test_combined() { + assert_eq!( + parse_natural_schedule("every day at 9am").unwrap(), + "0 9 * * *" + ); + assert_eq!( + parse_natural_schedule("every day at 6:30pm").unwrap(), + "30 18 * * *" + ); +} - #[test] +#[test] +fn test_hour_range() { + assert_eq!( + parse_natural_schedule("every hour from 9 to 17").unwrap(), + "0 9-17 * * *" + ); +} +#[test] +fn test_business_hours() { + assert_eq!( + parse_natural_schedule("business hours").unwrap(), + "0 9-17 * * 1-5" + ); + assert_eq!( + parse_natural_schedule("every 30 minutes during business hours").unwrap(), + "*/30 9-17 * * 1-5" + ); + assert_eq!( + parse_natural_schedule("every hour during business hours").unwrap(), + "0 9-17 * * 1-5" + ); +} - fn test_every_n_hours() { - assert_eq!( - parse_natural_schedule("every 2 hours").unwrap(), - "0 */2 * * *" - ); - assert_eq!( - parse_natural_schedule("every 6 hours").unwrap(), - "0 */6 * * *" - ); - } +#[test] +fn test_raw_cron_passthrough() { + assert_eq!(parse_natural_schedule("0 * * * *").unwrap(), "0 * * * *"); + assert_eq!( + parse_natural_schedule("*/5 * * * *").unwrap(), + "*/5 * * * *" + ); + assert_eq!( + parse_natural_schedule("0 9-17 * * 1-5").unwrap(), + "0 9-17 * * 1-5" + ); +} - #[test] - - - fn test_every_day() { - assert_eq!(parse_natural_schedule("every day").unwrap(), "0 0 * * *"); - assert_eq!(parse_natural_schedule("daily").unwrap(), "0 0 * * *"); - } - - #[test] - - - fn test_every_week() { - assert_eq!(parse_natural_schedule("every week").unwrap(), "0 0 * * 0"); - assert_eq!(parse_natural_schedule("weekly").unwrap(), "0 0 * * 0"); - } - - #[test] - - - fn test_every_month() { - assert_eq!(parse_natural_schedule("every month").unwrap(), "0 0 1 * *"); - assert_eq!(parse_natural_schedule("monthly").unwrap(), "0 0 1 * *"); - } - - #[test] - - - fn test_at_time() { - assert_eq!(parse_natural_schedule("at 9am").unwrap(), "0 9 * * *"); - assert_eq!(parse_natural_schedule("at 9:30am").unwrap(), "30 9 * * *"); - assert_eq!(parse_natural_schedule("at 2pm").unwrap(), "0 14 * * *"); - assert_eq!(parse_natural_schedule("at 14:00").unwrap(), "0 14 * * *"); - assert_eq!(parse_natural_schedule("at midnight").unwrap(), "0 0 * * *"); - assert_eq!(parse_natural_schedule("at noon").unwrap(), "0 12 * * *"); - } - - #[test] - - - fn test_day_of_week() { - assert_eq!(parse_natural_schedule("every monday").unwrap(), "0 0 * * 1"); - assert_eq!(parse_natural_schedule("every friday").unwrap(), "0 0 * * 5"); - assert_eq!(parse_natural_schedule("every sunday").unwrap(), "0 0 * * 0"); - } - - #[test] - - - fn test_day_with_time() { - assert_eq!( - parse_natural_schedule("every monday at 9am").unwrap(), - "0 9 * * 1" - ); - assert_eq!( - parse_natural_schedule("every friday at 5pm").unwrap(), - "0 17 * * 5" - ); - } - - #[test] - - - fn test_weekdays() { - assert_eq!(parse_natural_schedule("weekdays").unwrap(), "0 0 * * 1-5"); - assert_eq!( - parse_natural_schedule("every weekday").unwrap(), - "0 0 * * 1-5" - ); - assert_eq!( - parse_natural_schedule("weekdays at 8am").unwrap(), - "0 8 * * 1-5" - ); - } - - #[test] - - - fn test_weekends() { - assert_eq!(parse_natural_schedule("weekends").unwrap(), "0 0 * * 0,6"); - assert_eq!( - parse_natural_schedule("every weekend").unwrap(), - "0 0 * * 0,6" - ); - } - - #[test] - - - fn test_combined() { - assert_eq!( - parse_natural_schedule("every day at 9am").unwrap(), - "0 9 * * *" - ); - assert_eq!( - parse_natural_schedule("every day at 6:30pm").unwrap(), - "30 18 * * *" - ); - } - - #[test] - - - fn test_hour_range() { - assert_eq!( - parse_natural_schedule("every hour from 9 to 17").unwrap(), - "0 9-17 * * *" - ); - } - - #[test] - - - fn test_business_hours() { - assert_eq!( - parse_natural_schedule("business hours").unwrap(), - "0 9-17 * * 1-5" - ); - assert_eq!( - parse_natural_schedule("every 30 minutes during business hours").unwrap(), - "*/30 9-17 * * 1-5" - ); - assert_eq!( - parse_natural_schedule("every hour during business hours").unwrap(), - "0 9-17 * * 1-5" - ); - } - - #[test] - - - fn test_raw_cron_passthrough() { - assert_eq!(parse_natural_schedule("0 * * * *").unwrap(), "0 * * * *"); - assert_eq!( - parse_natural_schedule("*/5 * * * *").unwrap(), - "*/5 * * * *" - ); - assert_eq!( - parse_natural_schedule("0 9-17 * * 1-5").unwrap(), - "0 9-17 * * 1-5" - ); - } - - #[test] - - - fn test_invalid_input() { - assert!(parse_natural_schedule("potato salad").is_err()); - assert!(parse_natural_schedule("every 100 minutes").is_err()); - } \ No newline at end of file +#[test] +fn test_invalid_input() { + assert!(parse_natural_schedule("potato salad").is_err()); + assert!(parse_natural_schedule("every 100 minutes").is_err()); +}