use std::collections::HashMap;
use std::path::Path;
use std::process::ExitStatus;
mod test_support;
use ralph::contracts::{QueueFile, Task, TaskStatus};
fn run_in_dir(dir: &Path, args: &[&str]) -> (ExitStatus, String, String) {
test_support::run_in_dir(dir, args)
}
fn make_task(id: &str, status: TaskStatus, title: &str) -> Task {
let completed_at = matches!(status, TaskStatus::Done | TaskStatus::Rejected)
.then_some("2026-01-19T00:00:00Z".to_string());
Task {
id: id.to_string(),
status,
title: title.to_string(),
description: None,
priority: ralph::contracts::TaskPriority::Medium,
tags: vec!["test".to_string()],
scope: vec!["crates/ralph".to_string()],
evidence: vec!["evidence".to_string()],
plan: vec!["plan".to_string()],
notes: vec![],
request: Some("request".to_string()),
agent: None,
created_at: Some("2026-01-19T00:00:00Z".to_string()),
updated_at: Some("2026-01-19T00:00:00Z".to_string()),
completed_at,
started_at: None,
scheduled_start: None,
depends_on: vec![],
blocks: vec![],
relates_to: vec![],
duplicates: None,
custom_fields: HashMap::new(),
parent_id: None,
estimated_minutes: None,
actual_minutes: None,
}
}
fn make_queue_file(tasks: Vec<Task>) -> QueueFile {
QueueFile { version: 1, tasks }
}
#[test]
fn task_show_finds_task_in_queue() {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path()).expect("git init");
let (status, _stdout, stderr) =
test_support::run_in_dir(dir.path(), &["init", "--force", "--non-interactive"]);
assert!(status.success(), "ralph init failed: {}", stderr);
let queue = make_queue_file(vec![
make_task("RQ-0001", TaskStatus::Todo, "First task"),
make_task("RQ-0002", TaskStatus::Doing, "Second task"),
]);
let queue_path = dir.path().join(".ralph/queue.jsonc");
let json = serde_json::to_string_pretty(&queue).expect("serialize queue");
std::fs::write(&queue_path, json).expect("write queue.json");
let (status, stdout, stderr) = run_in_dir(dir.path(), &["task", "show", "RQ-0001"]);
assert!(status.success(), "task show failed: {}", stderr);
let combined = format!("{}\n{}", stdout, stderr);
assert!(
combined.contains("RQ-0001") && combined.contains("First task"),
"expected task details in output: {}",
combined
);
}
#[test]
fn task_show_finds_task_in_done() {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path()).expect("git init");
let (status, _stdout, stderr) =
test_support::run_in_dir(dir.path(), &["init", "--force", "--non-interactive"]);
assert!(status.success(), "ralph init failed: {}", stderr);
let done = make_queue_file(vec![make_task(
"RQ-0001",
TaskStatus::Done,
"Completed task",
)]);
let done_path = dir.path().join(".ralph/done.jsonc");
let json = serde_json::to_string_pretty(&done).expect("serialize done");
std::fs::write(&done_path, json).expect("write done.json");
let (status, stdout, stderr) = run_in_dir(dir.path(), &["task", "show", "RQ-0001"]);
assert!(status.success(), "task show failed: {}", stderr);
let combined = format!("{}\n{}", stdout, stderr);
assert!(
combined.contains("RQ-0001") && combined.contains("Completed task"),
"expected task details in output: {}",
combined
);
}
#[test]
fn task_show_details_alias_works() {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path()).expect("git init");
let (status, _stdout, stderr) =
test_support::run_in_dir(dir.path(), &["init", "--force", "--non-interactive"]);
assert!(status.success(), "ralph init failed: {}", stderr);
let queue = make_queue_file(vec![make_task("RQ-0001", TaskStatus::Todo, "Alias test")]);
let queue_path = dir.path().join(".ralph/queue.jsonc");
let json = serde_json::to_string_pretty(&queue).expect("serialize queue");
std::fs::write(&queue_path, json).expect("write queue.json");
let (status, stdout, stderr) = run_in_dir(dir.path(), &["task", "details", "RQ-0001"]);
assert!(status.success(), "task details failed: {}", stderr);
let combined = format!("{}\n{}", stdout, stderr);
assert!(
combined.contains("RQ-0001") && combined.contains("Alias test"),
"expected task details via alias: {}",
combined
);
}
#[test]
fn task_show_reports_missing_task() {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path()).expect("git init");
let (status, _stdout, stderr) =
test_support::run_in_dir(dir.path(), &["init", "--force", "--non-interactive"]);
assert!(status.success(), "ralph init failed: {}", stderr);
let (status, stdout, stderr) = run_in_dir(dir.path(), &["task", "show", "RQ-9999"]);
assert!(!status.success(), "expected failure for missing task");
let combined = format!("{}\n{}", stdout, stderr);
assert!(
combined.contains("not found") || combined.contains("No task"),
"expected 'not found' message: {}",
combined
);
}