auto_watch_tests.rs

  1use crate::TestServer;
  2use call::ActiveCall;
  3use gpui::{App, BackgroundExecutor, Entity, TestAppContext, TestScreenCaptureSource};
  4use project::Project;
  5use serde_json::json;
  6use util::path;
  7use workspace::Workspace;
  8
  9use super::TestClient;
 10
 11struct AutoWatchTestSetup {
 12    client_a: TestClient,
 13    _client_b: TestClient,
 14    _client_c: TestClient,
 15    project_a: Entity<Project>,
 16}
 17
 18async fn setup_auto_watch_test(
 19    server: &mut TestServer,
 20    user_a: &mut TestAppContext,
 21    user_b: &mut TestAppContext,
 22    user_c: &mut TestAppContext,
 23) -> AutoWatchTestSetup {
 24    let client_a = server.create_client(user_a, "user_a").await;
 25    let client_b = server.create_client(user_b, "user_b").await;
 26    let client_c = server.create_client(user_c, "user_c").await;
 27    server
 28        .create_room(&mut [
 29            (&client_a, user_a),
 30            (&client_b, user_b),
 31            (&client_c, user_c),
 32        ])
 33        .await;
 34
 35    let active_call_a = user_a.read(ActiveCall::global);
 36
 37    client_a
 38        .fs()
 39        .insert_tree(path!("/a"), json!({ "file.txt": "content" }))
 40        .await;
 41    let (project_a, _worktree_id) = client_a.build_local_project(path!("/a"), user_a).await;
 42    active_call_a
 43        .update(user_a, |call, cx| call.set_location(Some(&project_a), cx))
 44        .await
 45        .unwrap();
 46
 47    AutoWatchTestSetup {
 48        client_a,
 49        _client_b: client_b,
 50        _client_c: client_c,
 51        project_a,
 52    }
 53}
 54
 55#[gpui::test]
 56async fn test_auto_watch_opens_existing_share_on_toggle(
 57    executor: BackgroundExecutor,
 58    user_a: &mut TestAppContext,
 59    user_b: &mut TestAppContext,
 60    user_c: &mut TestAppContext,
 61) {
 62    let mut server = TestServer::start(executor.clone()).await;
 63    let setup = setup_auto_watch_test(&mut server, user_a, user_b, user_c).await;
 64    let (workspace_a, user_a) = setup.client_a.build_workspace(&setup.project_a, user_a);
 65    executor.run_until_parked();
 66
 67    start_screen_share(user_b).await;
 68    executor.run_until_parked();
 69
 70    workspace_a.update_in(user_a, |workspace, window, cx| {
 71        workspace.toggle_auto_watch(window, cx);
 72    });
 73    executor.run_until_parked();
 74
 75    workspace_a.update(user_a, |workspace, cx| {
 76        assert_active_matches_title(workspace, "user_b's screen", cx);
 77    });
 78}
 79
 80#[gpui::test]
 81async fn test_auto_watch_opens_share_when_no_one_is_sharing_yet(
 82    executor: BackgroundExecutor,
 83    user_a: &mut TestAppContext,
 84    user_b: &mut TestAppContext,
 85    user_c: &mut TestAppContext,
 86) {
 87    let mut server = TestServer::start(executor.clone()).await;
 88    let setup = setup_auto_watch_test(&mut server, user_a, user_b, user_c).await;
 89    let (workspace_a, user_a) = setup.client_a.build_workspace(&setup.project_a, user_a);
 90
 91    workspace_a.update_in(user_a, |workspace, window, cx| {
 92        workspace.toggle_auto_watch(window, cx);
 93    });
 94
 95    start_screen_share(user_b).await;
 96    executor.run_until_parked();
 97
 98    workspace_a.update(user_a, |workspace, cx| {
 99        assert_active_matches_title(workspace, "user_b's screen", cx);
100    });
101}
102
103#[gpui::test]
104async fn test_auto_watch_switches_to_next_share_on_share_end(
105    executor: BackgroundExecutor,
106    user_a: &mut TestAppContext,
107    user_b: &mut TestAppContext,
108    user_c: &mut TestAppContext,
109) {
110    let mut server = TestServer::start(executor.clone()).await;
111    let setup = setup_auto_watch_test(&mut server, user_a, user_b, user_c).await;
112    let (workspace_a, user_a) = setup.client_a.build_workspace(&setup.project_a, user_a);
113
114    workspace_a.update_in(user_a, |workspace, window, cx| {
115        workspace.toggle_auto_watch(window, cx);
116    });
117
118    start_screen_share(user_b).await;
119    executor.run_until_parked();
120
121    workspace_a.update(user_a, |workspace, cx| {
122        assert_active_matches_title(workspace, "user_b's screen", cx);
123    });
124
125    start_screen_share(user_c).await;
126    executor.run_until_parked();
127
128    stop_screen_share(user_b);
129    executor.run_until_parked();
130
131    workspace_a.update(user_a, |workspace, cx| {
132        assert_active_matches_title(workspace, "user_c's screen", cx);
133    });
134}
135
136#[gpui::test]
137async fn test_auto_watch_ignores_shares_while_user_is_sharing(
138    executor: BackgroundExecutor,
139    user_a: &mut TestAppContext,
140    user_b: &mut TestAppContext,
141    user_c: &mut TestAppContext,
142) {
143    let mut server = TestServer::start(executor.clone()).await;
144    let setup = setup_auto_watch_test(&mut server, user_a, user_b, user_c).await;
145    let (workspace_a, user_a) = setup.client_a.build_workspace(&setup.project_a, user_a);
146
147    start_screen_share(user_a).await;
148    executor.run_until_parked();
149    start_screen_share(user_b).await;
150    executor.run_until_parked();
151
152    // Should NOT open B's screen cause we are sharing
153    workspace_a.update_in(user_a, |workspace, window, cx| {
154        workspace.toggle_auto_watch(window, cx);
155    });
156    executor.run_until_parked();
157
158    // Ensure that no screen share is found in user a's tab bar
159    workspace_a.update(user_a, |workspace, cx| {
160        let has_shared_screen_tab = workspace
161            .active_pane()
162            .read(cx)
163            .items()
164            .any(|item| item.tab_content_text(0, cx).contains("screen"));
165        assert!(
166            !has_shared_screen_tab,
167            "should not open anyone's screen share when toggling on while sharing"
168        );
169    });
170}
171
172#[gpui::test]
173async fn test_auto_watch_opens_share_after_local_user_stops_sharing(
174    executor: BackgroundExecutor,
175    user_a: &mut TestAppContext,
176    user_b: &mut TestAppContext,
177    user_c: &mut TestAppContext,
178) {
179    let mut server = TestServer::start(executor.clone()).await;
180    let setup = setup_auto_watch_test(&mut server, user_a, user_b, user_c).await;
181    let (workspace_a, user_a) = setup.client_a.build_workspace(&setup.project_a, user_a);
182
183    workspace_a.update_in(user_a, |workspace, window, cx| {
184        workspace.toggle_auto_watch(window, cx);
185    });
186    start_screen_share(user_a).await;
187    executor.run_until_parked();
188
189    start_screen_share(user_b).await;
190    executor.run_until_parked();
191
192    stop_screen_share(user_a);
193    executor.run_until_parked();
194
195    workspace_a.update(user_a, |workspace, cx| {
196        assert_active_matches_title(workspace, "user_b's screen", cx);
197    });
198}
199
200#[gpui::test]
201async fn test_auto_watch_toggle_off_leaves_tabs_open(
202    executor: BackgroundExecutor,
203    user_a: &mut TestAppContext,
204    user_b: &mut TestAppContext,
205    user_c: &mut TestAppContext,
206) {
207    let mut server = TestServer::start(executor.clone()).await;
208    let setup = setup_auto_watch_test(&mut server, user_a, user_b, user_c).await;
209    let (workspace_a, user_a) = setup.client_a.build_workspace(&setup.project_a, user_a);
210
211    workspace_a.update_in(user_a, |workspace, window, cx| {
212        workspace.toggle_auto_watch(window, cx);
213    });
214    start_screen_share(user_b).await;
215    executor.run_until_parked();
216
217    workspace_a.update(user_a, |workspace, cx| {
218        assert_active_matches_title(workspace, "user_b's screen", cx);
219    });
220
221    workspace_a.update_in(user_a, |workspace, window, cx| {
222        workspace.toggle_auto_watch(window, cx);
223    });
224
225    workspace_a.update(user_a, |workspace, cx| {
226        assert_active_matches_title(workspace, "user_b's screen", cx);
227    });
228}
229
230#[track_caller]
231fn assert_active_matches_title(workspace: &Workspace, expected_title: &str, cx: &App) {
232    let active_item = workspace.active_item(cx).expect("no active item");
233    assert_eq!(
234        active_item.tab_content_text(0, cx),
235        expected_title,
236        "expected active item to be '{}'",
237        expected_title
238    );
239}
240
241async fn start_screen_share(cx: &mut TestAppContext) {
242    let display = TestScreenCaptureSource::new();
243    cx.set_screen_capture_sources(vec![display]);
244    let screen = cx
245        .update(|cx| cx.screen_capture_sources())
246        .await
247        .unwrap()
248        .unwrap()
249        .into_iter()
250        .next()
251        .unwrap();
252    let active_call = cx.read(ActiveCall::global);
253    active_call
254        .update(cx, |call, cx| {
255            call.room()
256                .unwrap()
257                .update(cx, |room, cx| room.share_screen(screen, cx))
258        })
259        .await
260        .unwrap();
261}
262
263fn stop_screen_share(cx: &mut TestAppContext) {
264    let active_call = cx.read(ActiveCall::global);
265    active_call
266        .update(cx, |call, cx| {
267            call.room()
268                .unwrap()
269                .update(cx, |room, cx| room.unshare_screen(true, cx))
270        })
271        .unwrap();
272}