1use assert_cmd::Command;
2use predicates::prelude::*;
3use tempfile::TempDir;
4
5fn td(home: &TempDir) -> Command {
6 let mut cmd = Command::cargo_bin("td").unwrap();
7 cmd.env("HOME", home.path());
8 cmd
9}
10
11#[test]
12fn init_creates_project_snapshot_and_binding() {
13 let tmp = TempDir::new().unwrap();
14
15 td(&tmp)
16 .args(["init", "demo"])
17 .current_dir(&tmp)
18 .assert()
19 .success()
20 .stderr(predicate::str::contains("initialized project 'demo'"));
21
22 let root = tmp.path().join(".local/share/td");
23 assert!(root.join("projects/demo/base.loro").is_file());
24 assert!(root.join("projects/demo/changes").is_dir());
25
26 let bindings_path = root.join("bindings.json");
27 assert!(bindings_path.is_file());
28 let bindings: serde_json::Value =
29 serde_json::from_str(&std::fs::read_to_string(bindings_path).unwrap()).unwrap();
30 let canonical_cwd = std::fs::canonicalize(tmp.path()).unwrap();
31 assert_eq!(
32 bindings["bindings"][canonical_cwd.to_string_lossy().as_ref()]
33 .as_str()
34 .unwrap(),
35 "demo"
36 );
37}
38
39#[test]
40fn init_fails_when_project_already_exists() {
41 let tmp = TempDir::new().unwrap();
42
43 td(&tmp)
44 .args(["init", "demo"])
45 .current_dir(&tmp)
46 .assert()
47 .success();
48
49 td(&tmp)
50 .args(["init", "demo"])
51 .current_dir(&tmp)
52 .assert()
53 .failure()
54 .stderr(predicate::str::contains("already exists"));
55}
56
57#[test]
58fn use_binds_another_directory_to_existing_project() {
59 let tmp = TempDir::new().unwrap();
60 let other = tmp.path().join("other");
61 std::fs::create_dir_all(&other).unwrap();
62
63 td(&tmp)
64 .args(["init", "demo"])
65 .current_dir(&tmp)
66 .assert()
67 .success();
68
69 td(&tmp)
70 .args(["create", "Created from original binding"])
71 .current_dir(&tmp)
72 .assert()
73 .success();
74
75 td(&tmp)
76 .args(["use", "demo"])
77 .current_dir(&other)
78 .assert()
79 .success();
80
81 td(&tmp)
82 .args(["list"])
83 .current_dir(&other)
84 .assert()
85 .success()
86 .stdout(predicate::str::contains("Created from original binding"));
87}
88
89#[test]
90fn init_json_outputs_success() {
91 let tmp = TempDir::new().unwrap();
92
93 td(&tmp)
94 .args(["--json", "init", "demo"])
95 .current_dir(&tmp)
96 .assert()
97 .success()
98 .stdout(predicate::str::contains(r#""success":true"#))
99 .stdout(predicate::str::contains(r#""project":"demo""#));
100}
101
102#[test]
103fn projects_lists_all_initialized_projects() {
104 let tmp = TempDir::new().unwrap();
105 let api_dir = tmp.path().join("api");
106 let web_dir = tmp.path().join("web");
107 std::fs::create_dir_all(&api_dir).unwrap();
108 std::fs::create_dir_all(&web_dir).unwrap();
109
110 td(&tmp)
111 .args(["init", "api"])
112 .current_dir(&api_dir)
113 .assert()
114 .success();
115
116 td(&tmp)
117 .args(["init", "web"])
118 .current_dir(&web_dir)
119 .assert()
120 .success();
121
122 td(&tmp)
123 .args(["projects"])
124 .current_dir(&api_dir)
125 .assert()
126 .success()
127 .stdout(predicate::str::contains("api"))
128 .stdout(predicate::str::contains("web"));
129}