my_task 1.3.0

A simple CLI task manager powered by SQLite
use assert_cmd::Command;
use predicates::prelude::*;
use tempfile::TempDir;

fn cmd(db_path: &std::path::Path) -> Command {
    let mut c = Command::cargo_bin("my-task").unwrap();
    c.env("MY_TASK_DATA_FILE", db_path);
    c
}

#[test]
fn test_search_finds_matching_tasks() {
    let tmp = TempDir::new().unwrap();
    let db_path = tmp.path().join("tasks.db");

    cmd(&db_path)
        .args(["add", "Buy groceries"])
        .assert()
        .success();
    cmd(&db_path)
        .args(["add", "Write report"])
        .assert()
        .success();
    cmd(&db_path)
        .args(["add", "Buy flowers"])
        .assert()
        .success();

    let output = cmd(&db_path).args(["search", "Buy"]).assert().success();
    let stdout = String::from_utf8(output.get_output().stdout.clone()).unwrap();
    assert!(stdout.contains("Buy groceries"));
    assert!(stdout.contains("Buy flowers"));
    assert!(!stdout.contains("Write report"));
    assert!(stdout.contains("2 tasks"));
}

#[test]
fn test_search_default_open_only() {
    let tmp = TempDir::new().unwrap();
    let db_path = tmp.path().join("tasks.db");

    cmd(&db_path)
        .args(["add", "Open match task"])
        .assert()
        .success();
    cmd(&db_path)
        .args(["add", "Done match task"])
        .assert()
        .success();
    cmd(&db_path).args(["done", "2"]).assert().success();

    let output = cmd(&db_path).args(["search", "match"]).assert().success();
    let stdout = String::from_utf8(output.get_output().stdout.clone()).unwrap();
    assert!(stdout.contains("Open match task"));
    assert!(!stdout.contains("Done match task"));
    assert!(stdout.contains("1 tasks"));
}

#[test]
fn test_search_all_flag() {
    let tmp = TempDir::new().unwrap();
    let db_path = tmp.path().join("tasks.db");

    cmd(&db_path)
        .args(["add", "Open match task"])
        .assert()
        .success();
    cmd(&db_path)
        .args(["add", "Done match task"])
        .assert()
        .success();
    cmd(&db_path).args(["done", "2"]).assert().success();

    let output = cmd(&db_path)
        .args(["search", "match", "--all"])
        .assert()
        .success();
    let stdout = String::from_utf8(output.get_output().stdout.clone()).unwrap();
    assert!(stdout.contains("Open match task"));
    assert!(stdout.contains("Done match task"));
    assert!(stdout.contains("2 tasks"));
}

#[test]
fn test_search_with_project_filter() {
    let tmp = TempDir::new().unwrap();
    let db_path = tmp.path().join("tasks.db");

    cmd(&db_path)
        .args(["add", "Task alpha one", "--project", "alpha"])
        .assert()
        .success();
    cmd(&db_path)
        .args(["add", "Task beta one", "--project", "beta"])
        .assert()
        .success();
    cmd(&db_path)
        .args(["add", "Task alpha two", "--project", "alpha"])
        .assert()
        .success();

    let output = cmd(&db_path)
        .args(["search", "Task", "--project", "alpha"])
        .assert()
        .success();
    let stdout = String::from_utf8(output.get_output().stdout.clone()).unwrap();
    assert!(stdout.contains("Task alpha one"));
    assert!(stdout.contains("Task alpha two"));
    assert!(!stdout.contains("Task beta one"));
    assert!(stdout.contains("2 tasks"));
}

#[test]
fn test_search_no_results() {
    let tmp = TempDir::new().unwrap();
    let db_path = tmp.path().join("tasks.db");

    cmd(&db_path).args(["add", "Some task"]).assert().success();

    cmd(&db_path)
        .args(["search", "nonexistent"])
        .assert()
        .success()
        .stdout(predicate::str::contains("No tasks found"));
}

#[test]
fn test_search_table_format() {
    let tmp = TempDir::new().unwrap();
    let db_path = tmp.path().join("tasks.db");

    cmd(&db_path)
        .args(["add", "Searchable task"])
        .assert()
        .success();

    let output = cmd(&db_path)
        .args(["search", "Searchable"])
        .assert()
        .success();
    let stdout = String::from_utf8(output.get_output().stdout.clone()).unwrap();
    assert!(stdout.contains("ID"));
    assert!(stdout.contains("Title"));
    assert!(stdout.contains("Status"));
}

#[test]
fn test_search_combined_all_and_project() {
    let tmp = TempDir::new().unwrap();
    let db_path = tmp.path().join("tasks.db");

    cmd(&db_path)
        .args(["add", "Open alpha task", "--project", "alpha"])
        .assert()
        .success();
    cmd(&db_path)
        .args(["add", "Done alpha task", "--project", "alpha"])
        .assert()
        .success();
    cmd(&db_path).args(["done", "2"]).assert().success();
    cmd(&db_path)
        .args(["add", "Open beta task", "--project", "beta"])
        .assert()
        .success();

    let output = cmd(&db_path)
        .args(["search", "task", "--all", "--project", "alpha"])
        .assert()
        .success();
    let stdout = String::from_utf8(output.get_output().stdout.clone()).unwrap();
    assert!(stdout.contains("Open alpha task"));
    assert!(stdout.contains("Done alpha task"));
    assert!(!stdout.contains("Open beta task"));
    assert!(stdout.contains("2 tasks"));
}