use std::io::Cursor;
use tempfile::NamedTempFile;
use things3_core::{
config::ThingsConfig, database::ThingsDatabase, test_utils::create_test_database,
};
#[tokio::test]
async fn test_print_tasks_integration() {
let temp_file = NamedTempFile::new().unwrap();
let db_path = temp_file.path();
create_test_database(db_path).await.unwrap();
let config = ThingsConfig::new(db_path, false);
let db = ThingsDatabase::new(&config.database_path).await.unwrap();
let mut output = Cursor::new(Vec::new());
things3_cli::print_tasks(&db, &[], &mut output).unwrap();
let result = String::from_utf8(output.into_inner()).unwrap();
assert!(result.contains("No tasks found"));
let tasks = db.get_inbox(None).await.unwrap();
let mut output = Cursor::new(Vec::new());
things3_cli::print_tasks(&db, &tasks, &mut output).unwrap();
let result = String::from_utf8(output.into_inner()).unwrap();
assert!(!result.is_empty());
}
#[tokio::test]
async fn test_print_projects_integration() {
let temp_file = NamedTempFile::new().unwrap();
let db_path = temp_file.path();
create_test_database(db_path).await.unwrap();
let config = ThingsConfig::new(db_path, false);
let db = ThingsDatabase::new(&config.database_path).await.unwrap();
let mut output = Cursor::new(Vec::new());
things3_cli::print_projects(&db, &[], &mut output).unwrap();
let result = String::from_utf8(output.into_inner()).unwrap();
assert!(result.contains("No projects found"));
let projects = db.get_projects(None).await.unwrap();
let mut output = Cursor::new(Vec::new());
things3_cli::print_projects(&db, &projects, &mut output).unwrap();
let result = String::from_utf8(output.into_inner()).unwrap();
assert!(!result.is_empty());
}
#[tokio::test]
async fn test_print_areas_integration() {
let temp_file = NamedTempFile::new().unwrap();
let db_path = temp_file.path();
create_test_database(db_path).await.unwrap();
let config = ThingsConfig::new(db_path, false);
let db = ThingsDatabase::new(&config.database_path).await.unwrap();
let mut output = Cursor::new(Vec::new());
things3_cli::print_areas(&db, &[], &mut output).unwrap();
let result = String::from_utf8(output.into_inner()).unwrap();
assert!(result.contains("No areas found"));
let areas = db.get_areas().await.unwrap();
let mut output = Cursor::new(Vec::new());
things3_cli::print_areas(&db, &areas, &mut output).unwrap();
let result = String::from_utf8(output.into_inner()).unwrap();
assert!(!result.is_empty());
}
#[tokio::test]
async fn test_health_check_integration() {
let temp_file = NamedTempFile::new().unwrap();
let db_path = temp_file.path();
create_test_database(db_path).await.unwrap();
let config = ThingsConfig::new(db_path, false);
let db = ThingsDatabase::new(&config.database_path).await.unwrap();
let result = things3_cli::health_check(&db).await;
assert!(result.is_ok());
let invalid_config = ThingsConfig::new("/nonexistent/path", false);
let invalid_db = ThingsDatabase::new(&invalid_config.database_path).await;
if let Ok(db) = invalid_db {
let result = things3_cli::health_check(&db).await;
let _ = result; }
}
#[tokio::test]
#[cfg(feature = "mcp-server")]
async fn test_mcp_server_integration() {
let temp_file = NamedTempFile::new().unwrap();
let db_path = temp_file.path();
create_test_database(db_path).await.unwrap();
let config = ThingsConfig::new(db_path, false);
let db = ThingsDatabase::new(&config.database_path).await.unwrap();
let server = things3_cli::mcp::ThingsMcpServer::new(db.into(), config);
let tools = server.list_tools().unwrap();
assert!(!tools.tools.is_empty());
assert!(tools.tools.iter().any(|tool| tool.name == "get_inbox"));
assert!(tools.tools.iter().any(|tool| tool.name == "get_today"));
assert!(tools.tools.iter().any(|tool| tool.name == "get_projects"));
}
#[test]
fn test_cli_parsing_integration() {
use clap::Parser;
use things3_cli::Cli;
let cli = Cli::try_parse_from(["things-cli", "inbox"]).unwrap();
assert_eq!(cli.command, things3_cli::Commands::Inbox { limit: None });
let cli = Cli::try_parse_from(["things-cli", "inbox", "--limit", "10"]).unwrap();
assert_eq!(
cli.command,
things3_cli::Commands::Inbox { limit: Some(10) }
);
let cli = Cli::try_parse_from(["things-cli", "--database", "/tmp/test.db", "inbox"]).unwrap();
assert_eq!(cli.database, Some(std::path::PathBuf::from("/tmp/test.db")));
let cli = Cli::try_parse_from(["things-cli", "--verbose", "inbox"]).unwrap();
assert!(cli.verbose);
let cli = Cli::try_parse_from(["things-cli", "--fallback-to-default", "inbox"]).unwrap();
assert!(cli.fallback_to_default);
}
#[tokio::test]
async fn test_cli_error_handling_integration() {
let config = ThingsConfig::new("/nonexistent/path", false);
let db_result = ThingsDatabase::new(&config.database_path).await;
assert!(db_result.is_err());
let config = ThingsConfig::new("/invalid/path/with/invalid/chars/\0", false);
let db_result = ThingsDatabase::new(&config.database_path).await;
assert!(db_result.is_err());
}
#[test]
fn test_cli_commands_integration() {
use clap::Parser;
use things3_cli::Cli;
let cli = Cli::try_parse_from(["things-cli", "inbox"]).unwrap();
assert_eq!(cli.command, things3_cli::Commands::Inbox { limit: None });
let cli = Cli::try_parse_from(["things-cli", "today"]).unwrap();
assert_eq!(cli.command, things3_cli::Commands::Today { limit: None });
let cli = Cli::try_parse_from(["things-cli", "projects"]).unwrap();
assert_eq!(
cli.command,
things3_cli::Commands::Projects {
area: None,
limit: None
}
);
let cli = Cli::try_parse_from(["things-cli", "areas"]).unwrap();
assert_eq!(cli.command, things3_cli::Commands::Areas { limit: None });
let cli = Cli::try_parse_from(["things-cli", "search", "test"]).unwrap();
assert_eq!(
cli.command,
things3_cli::Commands::Search {
query: "test".to_string(),
limit: None
}
);
let cli = Cli::try_parse_from(["things-cli", "health"]).unwrap();
assert_eq!(cli.command, things3_cli::Commands::Health);
let cli = Cli::try_parse_from(["things-cli", "mcp"]).unwrap();
assert_eq!(cli.command, things3_cli::Commands::Mcp);
}
#[test]
fn test_cli_flag_combinations_integration() {
use clap::Parser;
use things3_cli::Cli;
let cli = Cli::try_parse_from([
"things-cli",
"--verbose",
"--fallback-to-default",
"--database",
"/tmp/test.db",
"inbox",
"--limit",
"5",
])
.unwrap();
assert_eq!(cli.command, things3_cli::Commands::Inbox { limit: Some(5) });
assert!(cli.verbose);
assert!(cli.fallback_to_default);
assert_eq!(cli.database, Some(std::path::PathBuf::from("/tmp/test.db")));
}
#[test]
fn test_cli_help_version_integration() {
use clap::Parser;
use things3_cli::Cli;
let _ = Cli::try_parse_from(["things-cli", "--help"]);
let _ = Cli::try_parse_from(["things-cli", "--version"]);
}