1use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer};
2use channel::{ChannelChat, ChannelMessageId};
3use gpui::{executor::Deterministic, ModelHandle, TestAppContext};
4use std::sync::Arc;
5
6#[gpui::test]
7async fn test_basic_channel_messages(
8 deterministic: Arc<Deterministic>,
9 cx_a: &mut TestAppContext,
10 cx_b: &mut TestAppContext,
11) {
12 deterministic.forbid_parking();
13 let mut server = TestServer::start(&deterministic).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
17 let channel_id = server
18 .make_channel("the-channel", (&client_a, cx_a), &mut [(&client_b, cx_b)])
19 .await;
20
21 let channel_chat_a = client_a
22 .channel_store()
23 .update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx))
24 .await
25 .unwrap();
26 let channel_chat_b = client_b
27 .channel_store()
28 .update(cx_b, |store, cx| store.open_channel_chat(channel_id, cx))
29 .await
30 .unwrap();
31
32 channel_chat_a
33 .update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap())
34 .await
35 .unwrap();
36 channel_chat_a
37 .update(cx_a, |c, cx| c.send_message("two".into(), cx).unwrap())
38 .await
39 .unwrap();
40
41 deterministic.run_until_parked();
42 channel_chat_b
43 .update(cx_b, |c, cx| c.send_message("three".into(), cx).unwrap())
44 .await
45 .unwrap();
46
47 deterministic.run_until_parked();
48 channel_chat_a.update(cx_a, |c, _| {
49 assert_eq!(
50 c.messages()
51 .iter()
52 .map(|m| m.body.as_str())
53 .collect::<Vec<_>>(),
54 vec!["one", "two", "three"]
55 );
56 })
57}
58
59#[gpui::test]
60async fn test_rejoin_channel_chat(
61 deterministic: Arc<Deterministic>,
62 cx_a: &mut TestAppContext,
63 cx_b: &mut TestAppContext,
64) {
65 deterministic.forbid_parking();
66 let mut server = TestServer::start(&deterministic).await;
67 let client_a = server.create_client(cx_a, "user_a").await;
68 let client_b = server.create_client(cx_b, "user_b").await;
69
70 let channel_id = server
71 .make_channel("the-channel", (&client_a, cx_a), &mut [(&client_b, cx_b)])
72 .await;
73
74 let channel_chat_a = client_a
75 .channel_store()
76 .update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx))
77 .await
78 .unwrap();
79 let channel_chat_b = client_b
80 .channel_store()
81 .update(cx_b, |store, cx| store.open_channel_chat(channel_id, cx))
82 .await
83 .unwrap();
84
85 channel_chat_a
86 .update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap())
87 .await
88 .unwrap();
89 channel_chat_b
90 .update(cx_b, |c, cx| c.send_message("two".into(), cx).unwrap())
91 .await
92 .unwrap();
93
94 server.forbid_connections();
95 server.disconnect_client(client_a.peer_id().unwrap());
96
97 // While client A is disconnected, clients A and B both send new messages.
98 channel_chat_a
99 .update(cx_a, |c, cx| c.send_message("three".into(), cx).unwrap())
100 .await
101 .unwrap_err();
102 channel_chat_a
103 .update(cx_a, |c, cx| c.send_message("four".into(), cx).unwrap())
104 .await
105 .unwrap_err();
106 channel_chat_b
107 .update(cx_b, |c, cx| c.send_message("five".into(), cx).unwrap())
108 .await
109 .unwrap();
110 channel_chat_b
111 .update(cx_b, |c, cx| c.send_message("six".into(), cx).unwrap())
112 .await
113 .unwrap();
114
115 // Client A reconnects.
116 server.allow_connections();
117 deterministic.advance_clock(RECONNECT_TIMEOUT);
118
119 // Client A fetches the messages that were sent while they were disconnected
120 // and resends their own messages which failed to send.
121 let expected_messages = &["one", "two", "five", "six", "three", "four"];
122 assert_messages(&channel_chat_a, expected_messages, cx_a);
123 assert_messages(&channel_chat_b, expected_messages, cx_b);
124}
125
126#[gpui::test]
127async fn test_remove_channel_message(
128 deterministic: Arc<Deterministic>,
129 cx_a: &mut TestAppContext,
130 cx_b: &mut TestAppContext,
131 cx_c: &mut TestAppContext,
132) {
133 deterministic.forbid_parking();
134 let mut server = TestServer::start(&deterministic).await;
135 let client_a = server.create_client(cx_a, "user_a").await;
136 let client_b = server.create_client(cx_b, "user_b").await;
137 let client_c = server.create_client(cx_c, "user_c").await;
138
139 let channel_id = server
140 .make_channel(
141 "the-channel",
142 (&client_a, cx_a),
143 &mut [(&client_b, cx_b), (&client_c, cx_c)],
144 )
145 .await;
146
147 let channel_chat_a = client_a
148 .channel_store()
149 .update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx))
150 .await
151 .unwrap();
152 let channel_chat_b = client_b
153 .channel_store()
154 .update(cx_b, |store, cx| store.open_channel_chat(channel_id, cx))
155 .await
156 .unwrap();
157
158 // Client A sends some messages.
159 channel_chat_a
160 .update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap())
161 .await
162 .unwrap();
163 channel_chat_a
164 .update(cx_a, |c, cx| c.send_message("two".into(), cx).unwrap())
165 .await
166 .unwrap();
167 channel_chat_a
168 .update(cx_a, |c, cx| c.send_message("three".into(), cx).unwrap())
169 .await
170 .unwrap();
171
172 // Clients A and B see all of the messages.
173 deterministic.run_until_parked();
174 let expected_messages = &["one", "two", "three"];
175 assert_messages(&channel_chat_a, expected_messages, cx_a);
176 assert_messages(&channel_chat_b, expected_messages, cx_b);
177
178 // Client A deletes one of their messages.
179 channel_chat_a
180 .update(cx_a, |c, cx| {
181 let ChannelMessageId::Saved(id) = c.message(1).id else {
182 panic!("message not saved")
183 };
184 c.remove_message(id, cx)
185 })
186 .await
187 .unwrap();
188
189 // Client B sees that the message is gone.
190 deterministic.run_until_parked();
191 let expected_messages = &["one", "three"];
192 assert_messages(&channel_chat_a, expected_messages, cx_a);
193 assert_messages(&channel_chat_b, expected_messages, cx_b);
194
195 // Client C joins the channel chat, and does not see the deleted message.
196 let channel_chat_c = client_c
197 .channel_store()
198 .update(cx_c, |store, cx| store.open_channel_chat(channel_id, cx))
199 .await
200 .unwrap();
201 assert_messages(&channel_chat_c, expected_messages, cx_c);
202}
203
204#[track_caller]
205fn assert_messages(chat: &ModelHandle<ChannelChat>, messages: &[&str], cx: &mut TestAppContext) {
206 assert_eq!(
207 chat.read_with(cx, |chat, _| chat
208 .messages()
209 .iter()
210 .map(|m| m.body.clone())
211 .collect::<Vec<_>>(),),
212 messages
213 );
214}