1use assert_cmd::cargo::cargo_bin_cmd;
2use predicates::prelude::*;
3use tempfile::TempDir;
4
5fn td(home: &TempDir) -> assert_cmd::Command {
6 let mut cmd = cargo_bin_cmd!("td");
7 cmd.env("HOME", home.path());
8 cmd
9}
10
11#[test]
12fn init_sets_loro_schema_version_in_meta() {
13 let tmp = TempDir::new().unwrap();
14
15 td(&tmp)
16 .args(["project", "init", "demo"])
17 .current_dir(&tmp)
18 .assert()
19 .success();
20
21 let root = tmp.path().join(".local/share/td");
22 let store = yatd::db::Store::open(&root, "demo").unwrap();
23 assert_eq!(store.schema_version().unwrap(), 1);
24}
25
26#[test]
27fn corrupted_delta_file_is_tolerated_on_open() {
28 let tmp = TempDir::new().unwrap();
29
30 td(&tmp)
31 .args(["project", "init", "demo"])
32 .current_dir(&tmp)
33 .assert()
34 .success();
35
36 td(&tmp)
37 .args(["create", "kept task"])
38 .current_dir(&tmp)
39 .assert()
40 .success();
41
42 let corrupted = tmp
43 .path()
44 .join(".local/share/td/projects/demo/changes")
45 .join("01ARZ3NDEKTSV4RRFFQ69G5FAV.loro");
46 std::fs::write(corrupted, b"not-a-valid-loro-delta").unwrap();
47
48 td(&tmp)
49 .args(["list"])
50 .current_dir(&tmp)
51 .assert()
52 .success()
53 .stdout(predicate::str::contains("kept task"))
54 .stderr(predicate::str::contains("skipping unreadable delta"));
55}
56
57#[test]
58fn project_env_overrides_directory_binding() {
59 let tmp = TempDir::new().unwrap();
60 let alpha_dir = tmp.path().join("alpha");
61 let beta_dir = tmp.path().join("beta");
62 std::fs::create_dir_all(&alpha_dir).unwrap();
63 std::fs::create_dir_all(&beta_dir).unwrap();
64
65 td(&tmp)
66 .args(["project", "init", "alpha"])
67 .current_dir(&alpha_dir)
68 .assert()
69 .success();
70 td(&tmp)
71 .args(["create", "alpha task"])
72 .current_dir(&alpha_dir)
73 .assert()
74 .success();
75
76 td(&tmp)
77 .args(["project", "init", "beta"])
78 .current_dir(&beta_dir)
79 .assert()
80 .success();
81 td(&tmp)
82 .args(["create", "beta task"])
83 .current_dir(&beta_dir)
84 .assert()
85 .success();
86
87 let out = td(&tmp)
88 .args(["--json", "list"])
89 .env("TD_PROJECT", "beta")
90 .current_dir(&alpha_dir)
91 .output()
92 .unwrap();
93 let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
94
95 let titles: Vec<&str> = v
96 .as_array()
97 .unwrap()
98 .iter()
99 .map(|task| task["title"].as_str().unwrap())
100 .collect();
101
102 assert!(titles.contains(&"beta task"));
103 assert!(!titles.contains(&"alpha task"));
104}
105
106#[test]
107fn legacy_local_sqlite_artifacts_do_not_affect_commands() {
108 let tmp = TempDir::new().unwrap();
109
110 td(&tmp)
111 .args(["project", "init", "demo"])
112 .current_dir(&tmp)
113 .assert()
114 .success();
115
116 let legacy_dir = tmp.path().join(".td");
117 std::fs::create_dir_all(&legacy_dir).unwrap();
118 std::fs::write(legacy_dir.join("tasks.db"), b"legacy-sqlite-placeholder").unwrap();
119
120 td(&tmp)
121 .args(["create", "new storage path works"])
122 .current_dir(&tmp)
123 .assert()
124 .success();
125
126 td(&tmp)
127 .args(["list"])
128 .current_dir(&tmp)
129 .assert()
130 .success()
131 .stdout(predicate::str::contains("new storage path works"));
132}