1use call::ActiveCall;
2use client::Channel;
3use gpui::{executor::Deterministic, TestAppContext};
4use std::sync::Arc;
5
6use crate::tests::{room_participants, RoomParticipants};
7
8use super::TestServer;
9
10#[gpui::test]
11async fn test_basic_channels(
12 deterministic: Arc<Deterministic>,
13 cx_a: &mut TestAppContext,
14 cx_b: &mut TestAppContext,
15) {
16 deterministic.forbid_parking();
17 let mut server = TestServer::start(&deterministic).await;
18 let client_a = server.create_client(cx_a, "user_a").await;
19 let client_b = server.create_client(cx_b, "user_b").await;
20
21 let channel_a_id = client_a
22 .channel_store()
23 .update(cx_a, |channel_store, _| {
24 channel_store.create_channel("channel-a", None)
25 })
26 .await
27 .unwrap();
28
29 client_a.channel_store().read_with(cx_a, |channels, _| {
30 assert_eq!(
31 channels.channels(),
32 &[Arc::new(Channel {
33 id: channel_a_id,
34 name: "channel-a".to_string(),
35 parent_id: None,
36 depth: 0,
37 })]
38 )
39 });
40
41 client_b
42 .channel_store()
43 .read_with(cx_b, |channels, _| assert_eq!(channels.channels(), &[]));
44
45 // Invite client B to channel A as client A.
46 client_a
47 .channel_store()
48 .update(cx_a, |channel_store, _| {
49 channel_store.invite_member(channel_a_id, client_b.user_id().unwrap(), false)
50 })
51 .await
52 .unwrap();
53
54 // Wait for client b to see the invitation
55 deterministic.run_until_parked();
56
57 client_b.channel_store().read_with(cx_b, |channels, _| {
58 assert_eq!(
59 channels.channel_invitations(),
60 &[Arc::new(Channel {
61 id: channel_a_id,
62 name: "channel-a".to_string(),
63 parent_id: None,
64 depth: 0,
65 })]
66 )
67 });
68
69 // Client B now sees that they are a member channel A.
70 client_b
71 .channel_store()
72 .update(cx_b, |channels, _| {
73 channels.respond_to_channel_invite(channel_a_id, true)
74 })
75 .await
76 .unwrap();
77 client_b.channel_store().read_with(cx_b, |channels, _| {
78 assert_eq!(channels.channel_invitations(), &[]);
79 assert_eq!(
80 channels.channels(),
81 &[Arc::new(Channel {
82 id: channel_a_id,
83 name: "channel-a".to_string(),
84 parent_id: None,
85 depth: 0,
86 })]
87 )
88 });
89
90 // Client A deletes the channel
91 client_a
92 .channel_store()
93 .update(cx_a, |channel_store, _| {
94 channel_store.remove_channel(channel_a_id)
95 })
96 .await
97 .unwrap();
98
99 deterministic.run_until_parked();
100 client_a
101 .channel_store()
102 .read_with(cx_a, |channels, _| assert_eq!(channels.channels(), &[]));
103 client_b
104 .channel_store()
105 .read_with(cx_b, |channels, _| assert_eq!(channels.channels(), &[]));
106}
107
108#[gpui::test]
109async fn test_channel_room(
110 deterministic: Arc<Deterministic>,
111 cx_a: &mut TestAppContext,
112 cx_b: &mut TestAppContext,
113 cx_c: &mut TestAppContext,
114) {
115 deterministic.forbid_parking();
116 let mut server = TestServer::start(&deterministic).await;
117 let client_a = server.create_client(cx_a, "user_a").await;
118 let client_b = server.create_client(cx_b, "user_b").await;
119 let client_c = server.create_client(cx_b, "user_c").await;
120
121 let zed_id = server
122 .make_channel(
123 "zed",
124 (&client_a, cx_a),
125 &mut [(&client_b, cx_b), (&client_c, cx_c)],
126 )
127 .await;
128
129 let active_call_a = cx_a.read(ActiveCall::global);
130 let active_call_b = cx_b.read(ActiveCall::global);
131
132 active_call_a
133 .update(cx_a, |active_call, cx| active_call.join_channel(zed_id, cx))
134 .await
135 .unwrap();
136
137 // TODO Test that B and C sees A in the channel room
138 client_b.channel_store().read_with(cx_b, |channels, _| {
139 assert_eq!(
140 channels.channels(),
141 &[Arc::new(Channel {
142 id: zed_id,
143 name: "zed".to_string(),
144 parent_id: None,
145 depth: 0,
146 })]
147 )
148 });
149
150 active_call_b
151 .update(cx_b, |active_call, cx| active_call.join_channel(zed_id, cx))
152 .await
153 .unwrap();
154
155 // TODO Test that C sees A and B in the channel room
156
157 deterministic.run_until_parked();
158
159 let room_a = active_call_a.read_with(cx_a, |call, _| call.room().unwrap().clone());
160 room_a.read_with(cx_a, |room, _| assert!(room.is_connected()));
161 assert_eq!(
162 room_participants(&room_a, cx_a),
163 RoomParticipants {
164 remote: vec!["user_b".to_string()],
165 pending: vec![]
166 }
167 );
168
169 let room_b = active_call_b.read_with(cx_b, |call, _| call.room().unwrap().clone());
170 room_b.read_with(cx_b, |room, _| assert!(room.is_connected()));
171 assert_eq!(
172 room_participants(&room_b, cx_b),
173 RoomParticipants {
174 remote: vec!["user_a".to_string()],
175 pending: vec![]
176 }
177 );
178
179 // Make sure that leaving and rejoining works
180
181 active_call_a
182 .update(cx_a, |active_call, cx| active_call.hang_up(cx))
183 .await
184 .unwrap();
185
186 // TODO Make sure that C sees A leave
187
188 active_call_b
189 .update(cx_b, |active_call, cx| active_call.hang_up(cx))
190 .await
191 .unwrap();
192
193 // TODO Make sure that C sees B leave
194
195 active_call_a
196 .update(cx_a, |active_call, cx| active_call.join_channel(zed_id, cx))
197 .await
198 .unwrap();
199
200 active_call_b
201 .update(cx_b, |active_call, cx| active_call.join_channel(zed_id, cx))
202 .await
203 .unwrap();
204
205 deterministic.run_until_parked();
206
207 let room_a = active_call_a.read_with(cx_a, |call, _| call.room().unwrap().clone());
208 room_a.read_with(cx_a, |room, _| assert!(room.is_connected()));
209 assert_eq!(
210 room_participants(&room_a, cx_a),
211 RoomParticipants {
212 remote: vec!["user_b".to_string()],
213 pending: vec![]
214 }
215 );
216
217 let room_b = active_call_b.read_with(cx_b, |call, _| call.room().unwrap().clone());
218 room_b.read_with(cx_b, |room, _| assert!(room.is_connected()));
219 assert_eq!(
220 room_participants(&room_b, cx_b),
221 RoomParticipants {
222 remote: vec!["user_a".to_string()],
223 pending: vec![]
224 }
225 );
226}