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
15fn create_task(dir: &TempDir, title: &str) -> String {
16 let out = td()
17 .args(["--json", "create", title])
18 .current_dir(dir)
19 .output()
20 .unwrap();
21 let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
22 v["id"].as_str().unwrap().to_string()
23}
24
25fn get_task_json(dir: &TempDir, id: &str) -> serde_json::Value {
26 let out = td()
27 .args(["--json", "show", id])
28 .current_dir(dir)
29 .output()
30 .unwrap();
31 serde_json::from_slice(&out.stdout).unwrap()
32}
33
34// ── update ───────────────────────────────────────────────────────────
35
36#[test]
37fn update_changes_status() {
38 let tmp = init_tmp();
39 let id = create_task(&tmp, "In progress");
40
41 td().args(["update", &id, "-s", "in_progress"])
42 .current_dir(&tmp)
43 .assert()
44 .success()
45 .stdout(predicate::str::contains("updated"));
46
47 let t = get_task_json(&tmp, &id);
48 assert_eq!(t["status"].as_str().unwrap(), "in_progress");
49}
50
51#[test]
52fn update_changes_priority() {
53 let tmp = init_tmp();
54 let id = create_task(&tmp, "Reprioritise");
55
56 td().args(["update", &id, "-p", "high"])
57 .current_dir(&tmp)
58 .assert()
59 .success();
60
61 let t = get_task_json(&tmp, &id);
62 assert_eq!(t["priority"].as_i64().unwrap(), 1);
63}
64
65#[test]
66fn update_changes_title() {
67 let tmp = init_tmp();
68 let id = create_task(&tmp, "Old title");
69
70 td().args(["update", &id, "-t", "New title"])
71 .current_dir(&tmp)
72 .assert()
73 .success();
74
75 let t = get_task_json(&tmp, &id);
76 assert_eq!(t["title"].as_str().unwrap(), "New title");
77}
78
79#[test]
80fn update_changes_description() {
81 let tmp = init_tmp();
82 let id = create_task(&tmp, "Describe me");
83
84 td().args(["update", &id, "-d", "Now with details"])
85 .current_dir(&tmp)
86 .assert()
87 .success();
88
89 let t = get_task_json(&tmp, &id);
90 assert_eq!(t["description"].as_str().unwrap(), "Now with details");
91}
92
93#[test]
94fn update_json_returns_task() {
95 let tmp = init_tmp();
96 let id = create_task(&tmp, "JSON update");
97
98 let out = td()
99 .args(["--json", "update", &id, "-p", "high"])
100 .current_dir(&tmp)
101 .output()
102 .unwrap();
103 let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
104 assert_eq!(v["priority"].as_i64().unwrap(), 1);
105}
106
107#[test]
108fn update_changes_effort() {
109 let tmp = init_tmp();
110 let id = create_task(&tmp, "Re-estimate");
111
112 td().args(["update", &id, "-e", "high"])
113 .current_dir(&tmp)
114 .assert()
115 .success();
116
117 let t = get_task_json(&tmp, &id);
118 assert_eq!(t["effort"].as_i64().unwrap(), 3);
119}
120
121// ── done ─────────────────────────────────────────────────────────────
122
123#[test]
124fn done_closes_task() {
125 let tmp = init_tmp();
126 let id = create_task(&tmp, "Close me");
127
128 td().args(["done", &id])
129 .current_dir(&tmp)
130 .assert()
131 .success()
132 .stdout(predicate::str::contains("closed"));
133
134 let t = get_task_json(&tmp, &id);
135 assert_eq!(t["status"].as_str().unwrap(), "closed");
136}
137
138#[test]
139fn done_closes_multiple_tasks() {
140 let tmp = init_tmp();
141 let id1 = create_task(&tmp, "First");
142 let id2 = create_task(&tmp, "Second");
143
144 td().args(["done", &id1, &id2])
145 .current_dir(&tmp)
146 .assert()
147 .success();
148
149 assert_eq!(get_task_json(&tmp, &id1)["status"], "closed");
150 assert_eq!(get_task_json(&tmp, &id2)["status"], "closed");
151}
152
153// ── reopen ───────────────────────────────────────────────────────────
154
155#[test]
156fn reopen_reopens_closed_task() {
157 let tmp = init_tmp();
158 let id = create_task(&tmp, "Reopen me");
159
160 td().args(["done", &id])
161 .current_dir(&tmp)
162 .assert()
163 .success();
164 assert_eq!(get_task_json(&tmp, &id)["status"], "closed");
165
166 td().args(["reopen", &id])
167 .current_dir(&tmp)
168 .assert()
169 .success()
170 .stdout(predicate::str::contains("reopened"));
171
172 assert_eq!(get_task_json(&tmp, &id)["status"], "open");
173}