cli_list_show.rs

  1use assert_cmd::Command;
  2use predicates::prelude::*;
  3use tempfile::TempDir;
  4
  5fn td() -> Command {
  6    Command::cargo_bin("td").unwrap()
  7}
  8
  9fn init_tmp() -> TempDir {
 10    let tmp = TempDir::new().unwrap();
 11    td().arg("init").current_dir(&tmp).assert().success();
 12    tmp
 13}
 14
 15/// Create a task and return its JSON id.
 16fn create_task(dir: &TempDir, title: &str) -> String {
 17    let out = td()
 18        .args(["--json", "create", title])
 19        .current_dir(dir)
 20        .output()
 21        .unwrap();
 22    let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
 23    v["id"].as_str().unwrap().to_string()
 24}
 25
 26// ── list ─────────────────────────────────────────────────────────────
 27
 28#[test]
 29fn list_shows_created_tasks() {
 30    let tmp = init_tmp();
 31    create_task(&tmp, "Alpha");
 32    create_task(&tmp, "Bravo");
 33
 34    td().arg("list")
 35        .current_dir(&tmp)
 36        .assert()
 37        .success()
 38        .stdout(predicate::str::contains("Alpha"))
 39        .stdout(predicate::str::contains("Bravo"));
 40}
 41
 42#[test]
 43fn list_json_returns_array() {
 44    let tmp = init_tmp();
 45    create_task(&tmp, "One");
 46
 47    let out = td()
 48        .args(["--json", "list"])
 49        .current_dir(&tmp)
 50        .output()
 51        .unwrap();
 52    let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
 53    assert!(v.is_array(), "expected JSON array, got: {v}");
 54    assert_eq!(v.as_array().unwrap().len(), 1);
 55    assert_eq!(v[0]["title"].as_str().unwrap(), "One");
 56}
 57
 58#[test]
 59fn list_filter_by_status() {
 60    let tmp = init_tmp();
 61    create_task(&tmp, "Open task");
 62
 63    // No closed tasks yet.
 64    let out = td()
 65        .args(["--json", "list", "-s", "closed"])
 66        .current_dir(&tmp)
 67        .output()
 68        .unwrap();
 69    let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
 70    assert_eq!(v.as_array().unwrap().len(), 0);
 71}
 72
 73#[test]
 74fn list_filter_by_priority() {
 75    let tmp = init_tmp();
 76
 77    td().args(["create", "Low prio", "-p", "3"])
 78        .current_dir(&tmp)
 79        .assert()
 80        .success();
 81    td().args(["create", "High prio", "-p", "1"])
 82        .current_dir(&tmp)
 83        .assert()
 84        .success();
 85
 86    let out = td()
 87        .args(["--json", "list", "-p", "1"])
 88        .current_dir(&tmp)
 89        .output()
 90        .unwrap();
 91    let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
 92    let tasks = v.as_array().unwrap();
 93    assert_eq!(tasks.len(), 1);
 94    assert_eq!(tasks[0]["title"].as_str().unwrap(), "High prio");
 95}
 96
 97#[test]
 98fn list_filter_by_label() {
 99    let tmp = init_tmp();
100
101    td().args(["create", "Tagged", "-l", "urgent"])
102        .current_dir(&tmp)
103        .assert()
104        .success();
105    td().args(["create", "Untagged"])
106        .current_dir(&tmp)
107        .assert()
108        .success();
109
110    let out = td()
111        .args(["--json", "list", "-l", "urgent"])
112        .current_dir(&tmp)
113        .output()
114        .unwrap();
115    let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
116    let tasks = v.as_array().unwrap();
117    assert_eq!(tasks.len(), 1);
118    assert_eq!(tasks[0]["title"].as_str().unwrap(), "Tagged");
119}
120
121// ── show ─────────────────────────────────────────────────────────────
122
123#[test]
124fn show_displays_task() {
125    let tmp = init_tmp();
126    let id = create_task(&tmp, "Details here");
127
128    td().args(["show", &id])
129        .current_dir(&tmp)
130        .assert()
131        .success()
132        .stdout(predicate::str::contains("Details here"))
133        .stdout(predicate::str::contains(&id));
134}
135
136#[test]
137fn show_json_includes_labels_and_blockers() {
138    let tmp = init_tmp();
139
140    td().args(["create", "With labels", "-l", "bug,ui"])
141        .current_dir(&tmp)
142        .assert()
143        .success();
144
145    // Get the id via list.
146    let out = td()
147        .args(["--json", "list"])
148        .current_dir(&tmp)
149        .output()
150        .unwrap();
151    let list: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
152    let id = list[0]["id"].as_str().unwrap();
153
154    let out = td()
155        .args(["--json", "show", id])
156        .current_dir(&tmp)
157        .output()
158        .unwrap();
159    let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
160    assert_eq!(v["title"].as_str().unwrap(), "With labels");
161
162    let labels = v["labels"].as_array().unwrap();
163    assert!(labels.contains(&serde_json::Value::String("bug".into())));
164    assert!(labels.contains(&serde_json::Value::String("ui".into())));
165
166    // Blockers should be present (even if empty).
167    assert!(v["blockers"].is_array());
168}
169
170#[test]
171fn show_nonexistent_task_fails() {
172    let tmp = init_tmp();
173
174    td().args(["show", "td-nope"])
175        .current_dir(&tmp)
176        .assert()
177        .failure()
178        .stderr(predicate::str::contains("not found"));
179}