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!(dbg!(
108        room_b
109            .update(cx_b, |room, cx| room.share_microphone(cx))
110            .await
111    )
112    .is_err());
113
114    // B is promoted
115    active_call_a
116        .update(cx_a, |call, cx| {
117            call.room().unwrap().update(cx, |room, cx| {
118                room.set_participant_role(
119                    client_b.user_id().unwrap(),
120                    proto::ChannelRole::Member,
121                    cx,
122                )
123            })
124        })
125        .await
126        .unwrap();
127    cx_a.run_until_parked();
128
129    // project and buffers are now editable
130    assert!(project_b.read_with(cx_b, |project, _| !project.is_read_only()));
131    assert!(editor_b.update(cx_b, |editor, cx| !editor.read_only(cx)));
132    room_b
133        .update(cx_b, |room, cx| room.share_microphone(cx))
134        .await
135        .unwrap();
136
137    // B is demoted
138    active_call_a
139        .update(cx_a, |call, cx| {
140            call.room().unwrap().update(cx, |room, cx| {
141                room.set_participant_role(
142                    client_b.user_id().unwrap(),
143                    proto::ChannelRole::Guest,
144                    cx,
145                )
146            })
147        })
148        .await
149        .unwrap();
150    cx_a.run_until_parked();
151
152    // project and buffers are no longer editable
153    assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
154    assert!(editor_b.update(cx_b, |editor, cx| editor.read_only(cx)));
155    assert!(room_b
156        .update(cx_b, |room, cx| room.share_microphone(cx))
157        .await
158        .is_err());
159}