1use std::{
2 path::{Path, PathBuf},
3 sync::Arc,
4};
5
6use call::ActiveCall;
7use git::status::{FileStatus, StatusCode, TrackedStatus};
8use git_ui::project_diff::ProjectDiff;
9use gpui::{TestAppContext, VisualTestContext};
10use project::ProjectPath;
11use serde_json::json;
12use util::path;
13use workspace::Workspace;
14
15//
16use crate::tests::TestServer;
17
18#[gpui::test]
19async fn test_project_diff(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
20 let mut server = TestServer::start(cx_a.background_executor.clone()).await;
21 let client_a = server.create_client(cx_a, "user_a").await;
22 let client_b = server.create_client(cx_b, "user_b").await;
23 cx_a.set_name("cx_a");
24 cx_b.set_name("cx_b");
25
26 server
27 .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
28 .await;
29
30 client_a
31 .fs()
32 .insert_tree(
33 path!("/a"),
34 json!({
35 ".git": {},
36 "changed.txt": "after\n",
37 "unchanged.txt": "unchanged\n",
38 "created.txt": "created\n",
39 "secret.pem": "secret-changed\n",
40 }),
41 )
42 .await;
43
44 client_a.fs().set_git_content_for_repo(
45 Path::new(path!("/a/.git")),
46 &[
47 ("changed.txt".into(), "before\n".to_string(), None),
48 ("unchanged.txt".into(), "unchanged\n".to_string(), None),
49 ("deleted.txt".into(), "deleted\n".to_string(), None),
50 ("secret.pem".into(), "shh\n".to_string(), None),
51 ],
52 );
53 let (project_a, worktree_id) = client_a.build_local_project(path!("/a"), cx_a).await;
54 let active_call_a = cx_a.read(ActiveCall::global);
55 let project_id = active_call_a
56 .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
57 .await
58 .unwrap();
59
60 cx_b.update(editor::init);
61 cx_b.update(git_ui::init);
62 let project_b = client_b.join_remote_project(project_id, cx_b).await;
63 let workspace_b = cx_b.add_window(|window, cx| {
64 Workspace::new(
65 None,
66 project_b.clone(),
67 client_b.app_state.clone(),
68 window,
69 cx,
70 )
71 });
72 let cx_b = &mut VisualTestContext::from_window(*workspace_b, cx_b);
73 let workspace_b = workspace_b.root(cx_b).unwrap();
74
75 cx_b.update(|window, cx| {
76 window
77 .focused(cx)
78 .unwrap()
79 .dispatch_action(&git_ui::project_diff::Diff, window, cx)
80 });
81 let diff = workspace_b.update(cx_b, |workspace, cx| {
82 workspace.active_item(cx).unwrap().act_as::<ProjectDiff>(cx)
83 });
84 let diff = diff.unwrap();
85 cx_b.run_until_parked();
86
87 diff.update(cx_b, |diff, cx| {
88 assert_eq!(
89 diff.excerpt_paths(cx),
90 vec!["changed.txt", "deleted.txt", "created.txt"]
91 );
92 });
93
94 client_a
95 .fs()
96 .insert_tree(
97 path!("/a"),
98 json!({
99 ".git": {},
100 "changed.txt": "before\n",
101 "unchanged.txt": "changed\n",
102 "created.txt": "created\n",
103 "secret.pem": "secret-changed\n",
104 }),
105 )
106 .await;
107 cx_b.run_until_parked();
108
109 project_b.update(cx_b, |project, cx| {
110 let project_path = ProjectPath {
111 worktree_id,
112 path: Arc::from(PathBuf::from("unchanged.txt")),
113 };
114 let status = project.project_path_git_status(&project_path, cx);
115 assert_eq!(
116 status.unwrap(),
117 FileStatus::Tracked(TrackedStatus {
118 worktree_status: StatusCode::Modified,
119 index_status: StatusCode::Unmodified,
120 })
121 );
122 });
123
124 diff.update(cx_b, |diff, cx| {
125 assert_eq!(
126 diff.excerpt_paths(cx),
127 vec!["deleted.txt", "unchanged.txt", "created.txt"]
128 );
129 });
130}