channel_guest_tests.rs

  1use crate::tests::TestServer;
  2use call::ActiveCall;
  3use editor::Editor;
  4use gpui::{BackgroundExecutor, TestAppContext};
  5use rpc::proto;
  6
  7#[gpui::test]
  8async fn test_channel_guests(
  9    executor: BackgroundExecutor,
 10    cx_a: &mut TestAppContext,
 11    cx_b: &mut TestAppContext,
 12) {
 13    let mut server = TestServer::start(executor.clone()).await;
 14    let client_a = server.create_client(cx_a, "user_a").await;
 15    let client_b = server.create_client(cx_b, "user_b").await;
 16    let active_call_a = cx_a.read(ActiveCall::global);
 17
 18    let channel_id = server
 19        .make_public_channel("the-channel", &client_a, cx_a)
 20        .await;
 21
 22    // Client A shares a project in the channel
 23    let project_a = client_a.build_test_project(cx_a).await;
 24    active_call_a
 25        .update(cx_a, |call, cx| call.join_channel(channel_id, cx))
 26        .await
 27        .unwrap();
 28    let project_id = active_call_a
 29        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
 30        .await
 31        .unwrap();
 32    cx_a.executor().run_until_parked();
 33
 34    // Client B joins channel A as a guest
 35    cx_b.update(|cx| workspace::join_channel(channel_id, client_b.app_state.clone(), None, cx))
 36        .await
 37        .unwrap();
 38
 39    // b should be following a in the shared project.
 40    // B is a guest,
 41    executor.run_until_parked();
 42
 43    let active_call_b = cx_b.read(ActiveCall::global);
 44    let project_b =
 45        active_call_b.read_with(cx_b, |call, _| call.location().unwrap().upgrade().unwrap());
 46    let room_b = active_call_b.update(cx_b, |call, _| call.room().unwrap().clone());
 47
 48    assert_eq!(
 49        project_b.read_with(cx_b, |project, _| project.remote_id()),
 50        Some(project_id),
 51    );
 52    assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
 53    assert!(project_b
 54        .update(cx_b, |project, cx| {
 55            let worktree_id = project.worktrees().next().unwrap().read(cx).id();
 56            project.create_entry((worktree_id, "b.txt"), false, cx)
 57        })
 58        .await
 59        .is_err());
 60    assert!(room_b.read_with(cx_b, |room, _| !room.is_sharing_mic()));
 61}
 62
 63#[gpui::test]
 64async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
 65    let mut server = TestServer::start(cx_a.executor()).await;
 66    let client_a = server.create_client(cx_a, "user_a").await;
 67    let client_b = server.create_client(cx_b, "user_b").await;
 68    let active_call_a = cx_a.read(ActiveCall::global);
 69
 70    let channel_id = server
 71        .make_public_channel("the-channel", &client_a, cx_a)
 72        .await;
 73
 74    let project_a = client_a.build_test_project(cx_a).await;
 75    cx_a.update(|cx| workspace::join_channel(channel_id, client_a.app_state.clone(), None, cx))
 76        .await
 77        .unwrap();
 78
 79    // Client A shares a project in the channel
 80    active_call_a
 81        .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
 82        .await
 83        .unwrap();
 84    cx_a.run_until_parked();
 85
 86    // Client B joins channel A as a guest
 87    cx_b.update(|cx| workspace::join_channel(channel_id, client_b.app_state.clone(), None, cx))
 88        .await
 89        .unwrap();
 90    cx_a.run_until_parked();
 91
 92    // client B opens 1.txt as a guest
 93    let (workspace_b, cx_b) = client_b.active_workspace(cx_b);
 94    let room_b = cx_b
 95        .read(ActiveCall::global)
 96        .update(cx_b, |call, _| call.room().unwrap().clone());
 97    cx_b.simulate_keystrokes("cmd-p 1 enter");
 98
 99    let (project_b, editor_b) = workspace_b.update(cx_b, |workspace, cx| {
100        (
101            workspace.project().clone(),
102            workspace.active_item_as::<Editor>(cx).unwrap(),
103        )
104    });
105    assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
106    assert!(editor_b.update(cx_b, |e, cx| e.read_only(cx)));
107    assert!(room_b
108        .update(cx_b, |room, cx| room.share_microphone(cx))
109        .await
110        .is_err());
111
112    // B is promoted
113    active_call_a
114        .update(cx_a, |call, cx| {
115            call.room().unwrap().update(cx, |room, cx| {
116                room.set_participant_role(
117                    client_b.user_id().unwrap(),
118                    proto::ChannelRole::Member,
119                    cx,
120                )
121            })
122        })
123        .await
124        .unwrap();
125    cx_a.run_until_parked();
126
127    // project and buffers are now editable
128    assert!(project_b.read_with(cx_b, |project, _| !project.is_read_only()));
129    assert!(editor_b.update(cx_b, |editor, cx| !editor.read_only(cx)));
130    room_b
131        .update(cx_b, |room, cx| room.share_microphone(cx))
132        .await
133        .unwrap();
134
135    // B is demoted
136    active_call_a
137        .update(cx_a, |call, cx| {
138            call.room().unwrap().update(cx, |room, cx| {
139                room.set_participant_role(
140                    client_b.user_id().unwrap(),
141                    proto::ChannelRole::Guest,
142                    cx,
143                )
144            })
145        })
146        .await
147        .unwrap();
148    cx_a.run_until_parked();
149
150    // project and buffers are no longer editable
151    assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
152    assert!(editor_b.update(cx_b, |editor, cx| editor.read_only(cx)));
153    assert!(room_b
154        .update(cx_b, |room, cx| room.share_microphone(cx))
155        .await
156        .is_err());
157}