#[cfg(test)]
mod tests {
use crate::clients::slack::*;
use crate::transport::TransportType;
use crate::core::nodes::external_mcp_client::ExternalMCPClientNode;
use serde_json::Value;
#[test]
fn test_slack_client_default_config() {
let client = SlackClientNode::with_defaults();
let config = client.get_slack_config();
assert_eq!(config.server_url, "http://localhost:8003");
assert_eq!(client.get_config().service_name, "slack");
assert!(!client.is_connected());
}
#[test]
fn test_slack_client_http_config() {
let server_url = "http://slack.example.com:9003".to_string();
let bot_token = "xoxb-test-bot-token-123".to_string();
let user_token = "xoxp-test-user-token-456".to_string();
let client = SlackClientNode::with_http_transport(
server_url.clone(),
Some(bot_token.clone()),
Some(user_token.clone()),
);
let config = client.get_slack_config();
assert_eq!(config.server_url, server_url);
assert_eq!(config.bot_token, Some(bot_token));
assert_eq!(config.user_token, Some(user_token));
match &config.transport {
TransportType::Http { base_url, .. } => {
assert_eq!(base_url, &server_url);
}
_ => panic!("Expected HTTP transport"),
}
}
#[test]
fn test_slack_client_websocket_config() {
let websocket_url = "ws://slack.example.com:9003/ws".to_string();
let bot_token = "xoxb-test-ws-token-789".to_string();
let client = SlackClientNode::with_websocket_transport(
websocket_url.clone(),
Some(bot_token.clone()),
None,
);
let config = client.get_slack_config();
assert_eq!(config.server_url, websocket_url);
assert_eq!(config.bot_token, Some(bot_token));
assert_eq!(config.user_token, None);
match &config.transport {
TransportType::WebSocket { url, .. } => {
assert_eq!(url, &websocket_url);
}
_ => panic!("Expected WebSocket transport"),
}
}
#[test]
fn test_slack_client_stdio_config() {
let command = "python3".to_string();
let args = vec![
"-m".to_string(),
"slack_mcp_server".to_string(),
"--port".to_string(),
"8003".to_string(),
];
let bot_token = "xoxb-stdio-token-101112".to_string();
let client = SlackClientNode::with_stdio_transport(
command.clone(),
args.clone(),
Some(bot_token.clone()),
None,
);
let config = client.get_slack_config();
assert_eq!(config.server_url, "stdio://python3");
assert_eq!(config.bot_token, Some(bot_token));
assert_eq!(config.user_token, None);
match &config.transport {
TransportType::Stdio {
command: cmd,
args: cmd_args,
..
} => {
assert_eq!(cmd, &command);
assert_eq!(cmd_args, &args);
}
_ => panic!("Expected Stdio transport"),
}
}
#[test]
fn test_slack_client_node_trait() {
use crate::core::nodes::Node;
use crate::core::task::TaskContext;
let client = SlackClientNode::with_defaults();
let mut task_context = TaskContext::new(
"test-task".to_string(),
Value::String("test-workflow".to_string()),
);
let result = client.process(task_context);
assert!(result.is_ok());
let updated_context = result.unwrap();
assert!(
updated_context
.get_data::<bool>("slack_client_processed")
.unwrap_or(Some(false))
.unwrap_or(false)
);
assert_eq!(
updated_context
.get_data::<String>("service_name")
.unwrap_or(Some("".to_string())),
Some("slack".to_string())
);
}
#[tokio::test]
async fn test_send_message_arguments() {
let mut client = SlackClientNode::with_defaults();
// This test validates argument preparation for send_message
// In a real test environment, you would mock the MCP client connection
let channel = "#general";
let text = "Hello, world!";
let thread_ts = Some("1234567890.123456");
// Since we can't connect to a real server in unit tests,
// we just validate the client creation and configuration
assert_eq!(client.get_config().service_name, "slack");
assert!(!client.is_connected());
// The actual tool execution would be tested in integration tests
// with a real or mocked MCP server
}
#[tokio::test]
async fn test_list_channels_arguments() {
let mut client = SlackClientNode::with_defaults();
// This test validates argument preparation for list_channels
let exclude_archived = Some(true);
let types = Some(vec![
"public_channel".to_string(),
"private_channel".to_string(),
]);
// Validate client setup
assert_eq!(client.get_config().service_name, "slack");
assert!(!client.is_connected());
// The actual tool execution would be tested in integration tests
}
#[tokio::test]
async fn test_get_user_info_arguments() {
let mut client = SlackClientNode::with_defaults();
// This test validates argument preparation for get_user_info
let user_id = "U1234567890";
// Validate client setup
assert_eq!(client.get_config().service_name, "slack");
assert!(!client.is_connected());
// The actual tool execution would be tested in integration tests
}
#[tokio::test]
async fn test_get_channel_history_arguments() {
let mut client = SlackClientNode::with_defaults();
// This test validates argument preparation for get_channel_history
let channel = "C1234567890";
let limit = Some(100);
let oldest = Some("1234567890.123456");
let latest = Some("1234567891.123456");
// Validate client setup
assert_eq!(client.get_config().service_name, "slack");
assert!(!client.is_connected());
// The actual tool execution would be tested in integration tests
}
#[tokio::test]
async fn test_create_channel_arguments() {
let mut client = SlackClientNode::with_defaults();
// This test validates argument preparation for create_channel
let name = "new-test-channel";
let is_private = Some(false);
// Validate client setup
assert_eq!(client.get_config().service_name, "slack");
assert!(!client.is_connected());
// The actual tool execution would be tested in integration tests
}
#[tokio::test]
async fn test_search_messages_arguments() {
let mut client = SlackClientNode::with_defaults();
// This test validates argument preparation for search_messages
let query = "important announcement";
let sort = Some("timestamp");
let sort_dir = Some("desc");
let count = Some(50);
// Validate client setup
assert_eq!(client.get_config().service_name, "slack");
assert!(!client.is_connected());
// The actual tool execution would be tested in integration tests
}
#[tokio::test]
async fn test_list_tools_when_not_connected() {
let mut client = SlackClientNode::with_defaults();
// Should return an error when not connected
let result = client.list_tools().await;
assert!(result.is_err());
if let Err(e) = result {
match e {
crate::core::error::WorkflowError::MCPConnectionError { message } => {
assert!(message.contains("slack client not connected"));
}
_ => panic!("Expected MCPConnectionError"),
}
}
}
#[tokio::test]
async fn test_execute_tool_when_not_connected() {
let mut client = SlackClientNode::with_defaults();
// Should return an error when not connected
let result = client.execute_tool("send_message", None).await;
assert!(result.is_err());
if let Err(e) = result {
match e {
crate::core::error::WorkflowError::MCPConnectionError { message } => {
assert!(message.contains("slack client not connected"));
}
_ => panic!("Expected MCPConnectionError"),
}
}
}
#[test]
fn test_slack_config_from_env() {
// This test would require setting environment variables
// For now, just test the default behavior
let config = SlackClientConfig::default();
// Default values when env vars are not set
assert_eq!(config.server_url, "http://localhost:8003");
match config.transport {
TransportType::Http { base_url, .. } => {
assert_eq!(base_url, "http://localhost:8003");
}
_ => panic!("Expected HTTP transport by default"),
}
}
#[test]
fn test_slack_auth_config_generation() {
let bot_token = "xoxb-test-bot-token".to_string();
let user_token = "xoxp-test-user-token".to_string();
let client = SlackClientNode::with_http_transport(
"http://localhost:8003".to_string(),
Some(bot_token.clone()),
Some(user_token.clone()),
);
let external_config = client.get_config();
// Check that auth config was properly generated
assert!(external_config.auth.is_some());
if let Some(ref auth) = external_config.auth {
assert_eq!(auth.token, Some(bot_token.clone()));
assert!(auth.headers.is_some());
if let Some(ref headers) = auth.headers {
assert_eq!(
headers.get("Authorization"),
Some(&format!("Bearer {}", bot_token))
);
assert_eq!(headers.get("X-Slack-User-Token"), Some(&user_token));
}
}
}
#[test]
fn test_slack_client_with_bot_token_only() {
let bot_token = "xoxb-only-bot-token".to_string();
let client = SlackClientNode::with_http_transport(
"http://localhost:8003".to_string(),
Some(bot_token.clone()),
None, // No user token
);
let external_config = client.get_config();
// Check that auth config was properly generated with only bot token
assert!(external_config.auth.is_some());
if let Some(ref auth) = external_config.auth {
assert_eq!(auth.token, Some(bot_token.clone()));
assert!(auth.headers.is_some());
if let Some(ref headers) = auth.headers {
assert_eq!(
headers.get("Authorization"),
Some(&format!("Bearer {}", bot_token))
);
assert!(!headers.contains_key("X-Slack-User-Token"));
}
}
}
#[test]
fn test_slack_client_without_tokens() {
let client = SlackClientNode::with_http_transport(
"http://localhost:8003".to_string(),
None, // No bot token
None, // No user token
);
let external_config = client.get_config();
// Auth should be None when no tokens are provided
assert!(external_config.auth.is_none());
}
#[test]
fn test_slack_client_with_user_token_only() {
let user_token = "xoxp-only-user-token".to_string();
let client = SlackClientNode::with_http_transport(
"http://localhost:8003".to_string(),
None, // No bot token
Some(user_token.clone()),
);
let external_config = client.get_config();
// Check that auth config was properly generated with only user token
assert!(external_config.auth.is_some());
if let Some(ref auth) = external_config.auth {
assert_eq!(auth.token, None); // No bot token for main auth
assert!(auth.headers.is_some());
if let Some(ref headers) = auth.headers {
assert!(!headers.contains_key("Authorization")); // No bot token header
assert_eq!(headers.get("X-Slack-User-Token"), Some(&user_token));
}
}
}
#[test]
fn test_slack_tool_method_coverage() {
// This test ensures all major Slack API operations are covered
let methods = [
"send_message",
"list_channels",
"get_user_info",
"get_channel_info",
"get_channel_history",
"update_message",
"delete_message",
"add_reaction",
"remove_reaction",
"search_messages",
"create_channel",
"invite_to_channel",
];
// In a real implementation, you would verify these methods
// map to actual tools available from the MCP server
assert_eq!(methods.len(), 12, "Expected 12 Slack tool methods");
}
}