1use crate::{
2 db::{
3 tests::{channel_tree, new_test_connection, new_test_user, TEST_RELEASE_CHANNEL},
4 Channel, ChannelId, ChannelRole, Database, NewUserParams, RoomId,
5 },
6 test_both_dbs,
7};
8use rpc::{
9 proto::{self},
10 ConnectionId,
11};
12use std::sync::Arc;
13
14test_both_dbs!(test_channels, test_channels_postgres, test_channels_sqlite);
15
16async fn test_channels(db: &Arc<Database>) {
17 let a_id = new_test_user(db, "user1@example.com").await;
18 let b_id = new_test_user(db, "user2@example.com").await;
19
20 let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
21
22 // Make sure that people cannot read channels they haven't been invited to
23 assert!(db.get_channel(zed_id, b_id).await.is_err());
24
25 db.invite_channel_member(zed_id, b_id, a_id, ChannelRole::Member)
26 .await
27 .unwrap();
28
29 db.respond_to_channel_invite(zed_id, b_id, true)
30 .await
31 .unwrap();
32
33 let crdb_id = db.create_sub_channel("crdb", zed_id, a_id).await.unwrap();
34 let livestreaming_id = db
35 .create_sub_channel("livestreaming", zed_id, a_id)
36 .await
37 .unwrap();
38 let replace_id = db
39 .create_sub_channel("replace", zed_id, a_id)
40 .await
41 .unwrap();
42
43 let mut members = db
44 .transaction(|tx| async move {
45 let channel = db.get_channel_internal(replace_id, &*tx).await?;
46 Ok(db.get_channel_participants(&channel, &*tx).await?)
47 })
48 .await
49 .unwrap();
50 members.sort();
51 assert_eq!(members, &[a_id, b_id]);
52
53 let rust_id = db.create_root_channel("rust", a_id).await.unwrap();
54 let cargo_id = db.create_sub_channel("cargo", rust_id, a_id).await.unwrap();
55
56 let cargo_ra_id = db
57 .create_sub_channel("cargo-ra", cargo_id, a_id)
58 .await
59 .unwrap();
60
61 let result = db.get_channels_for_user(a_id).await.unwrap();
62 assert_eq!(
63 result.channels,
64 channel_tree(&[
65 (zed_id, &[], "zed", ChannelRole::Admin),
66 (crdb_id, &[zed_id], "crdb", ChannelRole::Admin),
67 (
68 livestreaming_id,
69 &[zed_id],
70 "livestreaming",
71 ChannelRole::Admin
72 ),
73 (replace_id, &[zed_id], "replace", ChannelRole::Admin),
74 (rust_id, &[], "rust", ChannelRole::Admin),
75 (cargo_id, &[rust_id], "cargo", ChannelRole::Admin),
76 (
77 cargo_ra_id,
78 &[rust_id, cargo_id],
79 "cargo-ra",
80 ChannelRole::Admin
81 )
82 ],)
83 );
84
85 let result = db.get_channels_for_user(b_id).await.unwrap();
86 assert_eq!(
87 result.channels,
88 channel_tree(&[
89 (zed_id, &[], "zed", ChannelRole::Member),
90 (crdb_id, &[zed_id], "crdb", ChannelRole::Member),
91 (
92 livestreaming_id,
93 &[zed_id],
94 "livestreaming",
95 ChannelRole::Member
96 ),
97 (replace_id, &[zed_id], "replace", ChannelRole::Member)
98 ],)
99 );
100
101 // Update member permissions
102 let set_subchannel_admin = db
103 .set_channel_member_role(crdb_id, a_id, b_id, ChannelRole::Admin)
104 .await;
105 assert!(set_subchannel_admin.is_err());
106 let set_channel_admin = db
107 .set_channel_member_role(zed_id, a_id, b_id, ChannelRole::Admin)
108 .await;
109 assert!(set_channel_admin.is_ok());
110
111 let result = db.get_channels_for_user(b_id).await.unwrap();
112 assert_eq!(
113 result.channels,
114 channel_tree(&[
115 (zed_id, &[], "zed", ChannelRole::Admin),
116 (crdb_id, &[zed_id], "crdb", ChannelRole::Admin),
117 (
118 livestreaming_id,
119 &[zed_id],
120 "livestreaming",
121 ChannelRole::Admin
122 ),
123 (replace_id, &[zed_id], "replace", ChannelRole::Admin)
124 ],)
125 );
126
127 // Remove a single channel
128 db.delete_channel(crdb_id, a_id).await.unwrap();
129 assert!(db.get_channel(crdb_id, a_id).await.is_err());
130
131 // Remove a channel tree
132 let (mut channel_ids, user_ids) = db.delete_channel(rust_id, a_id).await.unwrap();
133 channel_ids.sort();
134 assert_eq!(channel_ids, &[rust_id, cargo_id, cargo_ra_id]);
135 assert_eq!(user_ids, &[a_id]);
136
137 assert!(db.get_channel(rust_id, a_id).await.is_err());
138 assert!(db.get_channel(cargo_id, a_id).await.is_err());
139 assert!(db.get_channel(cargo_ra_id, a_id).await.is_err());
140}
141
142test_both_dbs!(
143 test_joining_channels,
144 test_joining_channels_postgres,
145 test_joining_channels_sqlite
146);
147
148async fn test_joining_channels(db: &Arc<Database>) {
149 let owner_id = db.create_server("test").await.unwrap().0 as u32;
150
151 let user_1 = new_test_user(db, "user1@example.com").await;
152 let user_2 = new_test_user(db, "user2@example.com").await;
153
154 let channel_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
155
156 // can join a room with membership to its channel
157 let (joined_room, _, _) = db
158 .join_channel(
159 channel_1,
160 user_1,
161 ConnectionId { owner_id, id: 1 },
162 TEST_RELEASE_CHANNEL,
163 )
164 .await
165 .unwrap();
166 assert_eq!(joined_room.room.participants.len(), 1);
167
168 let room_id = RoomId::from_proto(joined_room.room.id);
169 drop(joined_room);
170 // cannot join a room without membership to its channel
171 assert!(db
172 .join_room(
173 room_id,
174 user_2,
175 ConnectionId { owner_id, id: 1 },
176 TEST_RELEASE_CHANNEL
177 )
178 .await
179 .is_err());
180}
181
182test_both_dbs!(
183 test_channel_invites,
184 test_channel_invites_postgres,
185 test_channel_invites_sqlite
186);
187
188async fn test_channel_invites(db: &Arc<Database>) {
189 db.create_server("test").await.unwrap();
190
191 let user_1 = new_test_user(db, "user1@example.com").await;
192 let user_2 = new_test_user(db, "user2@example.com").await;
193 let user_3 = new_test_user(db, "user3@example.com").await;
194
195 let channel_1_1 = db.create_root_channel("channel_1", user_1).await.unwrap();
196
197 let channel_1_2 = db.create_root_channel("channel_2", user_1).await.unwrap();
198
199 db.invite_channel_member(channel_1_1, user_2, user_1, ChannelRole::Member)
200 .await
201 .unwrap();
202 db.invite_channel_member(channel_1_2, user_2, user_1, ChannelRole::Member)
203 .await
204 .unwrap();
205 db.invite_channel_member(channel_1_1, user_3, user_1, ChannelRole::Admin)
206 .await
207 .unwrap();
208
209 let user_2_invites = db
210 .get_channel_invites_for_user(user_2) // -> [channel_1_1, channel_1_2]
211 .await
212 .unwrap()
213 .into_iter()
214 .map(|channel| channel.id)
215 .collect::<Vec<_>>();
216
217 assert_eq!(user_2_invites, &[channel_1_1, channel_1_2]);
218
219 let user_3_invites = db
220 .get_channel_invites_for_user(user_3) // -> [channel_1_1]
221 .await
222 .unwrap()
223 .into_iter()
224 .map(|channel| channel.id)
225 .collect::<Vec<_>>();
226
227 assert_eq!(user_3_invites, &[channel_1_1]);
228
229 let mut members = db
230 .get_channel_participant_details(channel_1_1, user_1)
231 .await
232 .unwrap();
233
234 members.sort_by_key(|member| member.user_id);
235 assert_eq!(
236 members,
237 &[
238 proto::ChannelMember {
239 user_id: user_1.to_proto(),
240 kind: proto::channel_member::Kind::Member.into(),
241 role: proto::ChannelRole::Admin.into(),
242 },
243 proto::ChannelMember {
244 user_id: user_2.to_proto(),
245 kind: proto::channel_member::Kind::Invitee.into(),
246 role: proto::ChannelRole::Member.into(),
247 },
248 proto::ChannelMember {
249 user_id: user_3.to_proto(),
250 kind: proto::channel_member::Kind::Invitee.into(),
251 role: proto::ChannelRole::Admin.into(),
252 },
253 ]
254 );
255
256 db.respond_to_channel_invite(channel_1_1, user_2, true)
257 .await
258 .unwrap();
259
260 let channel_1_3 = db
261 .create_sub_channel("channel_3", channel_1_1, user_1)
262 .await
263 .unwrap();
264
265 let members = db
266 .get_channel_participant_details(channel_1_3, user_1)
267 .await
268 .unwrap();
269 assert_eq!(
270 members,
271 &[
272 proto::ChannelMember {
273 user_id: user_1.to_proto(),
274 kind: proto::channel_member::Kind::AncestorMember.into(),
275 role: proto::ChannelRole::Admin.into(),
276 },
277 proto::ChannelMember {
278 user_id: user_2.to_proto(),
279 kind: proto::channel_member::Kind::AncestorMember.into(),
280 role: proto::ChannelRole::Member.into(),
281 },
282 ]
283 );
284}
285
286test_both_dbs!(
287 test_channel_renames,
288 test_channel_renames_postgres,
289 test_channel_renames_sqlite
290);
291
292async fn test_channel_renames(db: &Arc<Database>) {
293 db.create_server("test").await.unwrap();
294
295 let user_1 = db
296 .create_user(
297 "user1@example.com",
298 false,
299 NewUserParams {
300 github_login: "user1".into(),
301 github_user_id: 5,
302 },
303 )
304 .await
305 .unwrap()
306 .user_id;
307
308 let user_2 = db
309 .create_user(
310 "user2@example.com",
311 false,
312 NewUserParams {
313 github_login: "user2".into(),
314 github_user_id: 6,
315 },
316 )
317 .await
318 .unwrap()
319 .user_id;
320
321 let zed_id = db.create_root_channel("zed", user_1).await.unwrap();
322
323 db.rename_channel(zed_id, user_1, "#zed-archive")
324 .await
325 .unwrap();
326
327 let channel = db.get_channel(zed_id, user_1).await.unwrap();
328 assert_eq!(channel.name, "zed-archive");
329
330 let non_permissioned_rename = db.rename_channel(zed_id, user_2, "hacked-lol").await;
331 assert!(non_permissioned_rename.is_err());
332
333 let bad_name_rename = db.rename_channel(zed_id, user_1, "#").await;
334 assert!(bad_name_rename.is_err())
335}
336
337test_both_dbs!(
338 test_db_channel_moving,
339 test_channels_moving_postgres,
340 test_channels_moving_sqlite
341);
342
343async fn test_db_channel_moving(db: &Arc<Database>) {
344 let a_id = db
345 .create_user(
346 "user1@example.com",
347 false,
348 NewUserParams {
349 github_login: "user1".into(),
350 github_user_id: 5,
351 },
352 )
353 .await
354 .unwrap()
355 .user_id;
356
357 let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
358
359 let crdb_id = db.create_sub_channel("crdb", zed_id, a_id).await.unwrap();
360
361 let gpui2_id = db.create_sub_channel("gpui2", zed_id, a_id).await.unwrap();
362
363 let livestreaming_id = db
364 .create_sub_channel("livestreaming", crdb_id, a_id)
365 .await
366 .unwrap();
367
368 let livestreaming_dag_id = db
369 .create_sub_channel("livestreaming_dag", livestreaming_id, a_id)
370 .await
371 .unwrap();
372
373 // ========================================================================
374 // sanity check
375 // Initial DAG:
376 // /- gpui2
377 // zed -- crdb - livestreaming - livestreaming_dag
378 let result = db.get_channels_for_user(a_id).await.unwrap();
379 assert_channel_tree(
380 result.channels,
381 &[
382 (zed_id, &[]),
383 (crdb_id, &[zed_id]),
384 (livestreaming_id, &[zed_id, crdb_id]),
385 (livestreaming_dag_id, &[zed_id, crdb_id, livestreaming_id]),
386 (gpui2_id, &[zed_id]),
387 ],
388 );
389}
390
391test_both_dbs!(
392 test_db_channel_moving_bugs,
393 test_db_channel_moving_bugs_postgres,
394 test_db_channel_moving_bugs_sqlite
395);
396
397async fn test_db_channel_moving_bugs(db: &Arc<Database>) {
398 let user_id = db
399 .create_user(
400 "user1@example.com",
401 false,
402 NewUserParams {
403 github_login: "user1".into(),
404 github_user_id: 5,
405 },
406 )
407 .await
408 .unwrap()
409 .user_id;
410
411 let zed_id = db.create_root_channel("zed", user_id).await.unwrap();
412
413 let projects_id = db
414 .create_sub_channel("projects", zed_id, user_id)
415 .await
416 .unwrap();
417
418 let livestreaming_id = db
419 .create_sub_channel("livestreaming", projects_id, user_id)
420 .await
421 .unwrap();
422
423 // Move to same parent should be a no-op
424 assert!(db
425 .move_channel(projects_id, Some(zed_id), user_id)
426 .await
427 .unwrap()
428 .is_none());
429
430 let result = db.get_channels_for_user(user_id).await.unwrap();
431 assert_channel_tree(
432 result.channels,
433 &[
434 (zed_id, &[]),
435 (projects_id, &[zed_id]),
436 (livestreaming_id, &[zed_id, projects_id]),
437 ],
438 );
439
440 // Move the project channel to the root
441 db.move_channel(projects_id, None, user_id).await.unwrap();
442 let result = db.get_channels_for_user(user_id).await.unwrap();
443 assert_channel_tree(
444 result.channels,
445 &[
446 (zed_id, &[]),
447 (projects_id, &[]),
448 (livestreaming_id, &[projects_id]),
449 ],
450 );
451
452 // Can't move a channel into its ancestor
453 db.move_channel(projects_id, Some(livestreaming_id), user_id)
454 .await
455 .unwrap_err();
456 let result = db.get_channels_for_user(user_id).await.unwrap();
457 assert_channel_tree(
458 result.channels,
459 &[
460 (zed_id, &[]),
461 (projects_id, &[]),
462 (livestreaming_id, &[projects_id]),
463 ],
464 );
465}
466
467test_both_dbs!(
468 test_user_is_channel_participant,
469 test_user_is_channel_participant_postgres,
470 test_user_is_channel_participant_sqlite
471);
472
473async fn test_user_is_channel_participant(db: &Arc<Database>) {
474 let admin = new_test_user(db, "admin@example.com").await;
475 let member = new_test_user(db, "member@example.com").await;
476 let guest = new_test_user(db, "guest@example.com").await;
477
478 let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
479 let active_channel_id = db
480 .create_sub_channel("active", zed_channel, admin)
481 .await
482 .unwrap();
483 let vim_channel_id = db
484 .create_sub_channel("vim", active_channel_id, admin)
485 .await
486 .unwrap();
487
488 db.set_channel_visibility(vim_channel_id, crate::db::ChannelVisibility::Public, admin)
489 .await
490 .unwrap();
491 db.invite_channel_member(active_channel_id, member, admin, ChannelRole::Member)
492 .await
493 .unwrap();
494 db.invite_channel_member(vim_channel_id, guest, admin, ChannelRole::Guest)
495 .await
496 .unwrap();
497
498 db.respond_to_channel_invite(active_channel_id, member, true)
499 .await
500 .unwrap();
501
502 db.transaction(|tx| async move {
503 db.check_user_is_channel_participant(
504 &db.get_channel_internal(vim_channel_id, &*tx).await?,
505 admin,
506 &*tx,
507 )
508 .await
509 })
510 .await
511 .unwrap();
512 db.transaction(|tx| async move {
513 db.check_user_is_channel_participant(
514 &db.get_channel_internal(vim_channel_id, &*tx).await?,
515 member,
516 &*tx,
517 )
518 .await
519 })
520 .await
521 .unwrap();
522
523 let mut members = db
524 .get_channel_participant_details(vim_channel_id, admin)
525 .await
526 .unwrap();
527
528 members.sort_by_key(|member| member.user_id);
529
530 assert_eq!(
531 members,
532 &[
533 proto::ChannelMember {
534 user_id: admin.to_proto(),
535 kind: proto::channel_member::Kind::AncestorMember.into(),
536 role: proto::ChannelRole::Admin.into(),
537 },
538 proto::ChannelMember {
539 user_id: member.to_proto(),
540 kind: proto::channel_member::Kind::AncestorMember.into(),
541 role: proto::ChannelRole::Member.into(),
542 },
543 proto::ChannelMember {
544 user_id: guest.to_proto(),
545 kind: proto::channel_member::Kind::Invitee.into(),
546 role: proto::ChannelRole::Guest.into(),
547 },
548 ]
549 );
550
551 db.respond_to_channel_invite(vim_channel_id, guest, true)
552 .await
553 .unwrap();
554
555 db.transaction(|tx| async move {
556 db.check_user_is_channel_participant(
557 &db.get_channel_internal(vim_channel_id, &*tx).await?,
558 guest,
559 &*tx,
560 )
561 .await
562 })
563 .await
564 .unwrap();
565
566 let channels = db.get_channels_for_user(guest).await.unwrap().channels;
567 assert_channel_tree(channels, &[(vim_channel_id, &[])]);
568 let channels = db.get_channels_for_user(member).await.unwrap().channels;
569 assert_channel_tree(
570 channels,
571 &[
572 (active_channel_id, &[]),
573 (vim_channel_id, &[active_channel_id]),
574 ],
575 );
576
577 db.set_channel_member_role(vim_channel_id, admin, guest, ChannelRole::Banned)
578 .await
579 .unwrap();
580 assert!(db
581 .transaction(|tx| async move {
582 db.check_user_is_channel_participant(
583 &db.get_channel_internal(vim_channel_id, &*tx).await.unwrap(),
584 guest,
585 &*tx,
586 )
587 .await
588 })
589 .await
590 .is_err());
591
592 let mut members = db
593 .get_channel_participant_details(vim_channel_id, admin)
594 .await
595 .unwrap();
596
597 members.sort_by_key(|member| member.user_id);
598
599 assert_eq!(
600 members,
601 &[
602 proto::ChannelMember {
603 user_id: admin.to_proto(),
604 kind: proto::channel_member::Kind::AncestorMember.into(),
605 role: proto::ChannelRole::Admin.into(),
606 },
607 proto::ChannelMember {
608 user_id: member.to_proto(),
609 kind: proto::channel_member::Kind::AncestorMember.into(),
610 role: proto::ChannelRole::Member.into(),
611 },
612 proto::ChannelMember {
613 user_id: guest.to_proto(),
614 kind: proto::channel_member::Kind::Member.into(),
615 role: proto::ChannelRole::Banned.into(),
616 },
617 ]
618 );
619
620 db.remove_channel_member(vim_channel_id, guest, admin)
621 .await
622 .unwrap();
623
624 db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
625 .await
626 .unwrap();
627
628 db.invite_channel_member(zed_channel, guest, admin, ChannelRole::Guest)
629 .await
630 .unwrap();
631
632 // currently people invited to parent channels are not shown here
633 let mut members = db
634 .get_channel_participant_details(vim_channel_id, admin)
635 .await
636 .unwrap();
637
638 members.sort_by_key(|member| member.user_id);
639
640 assert_eq!(
641 members,
642 &[
643 proto::ChannelMember {
644 user_id: admin.to_proto(),
645 kind: proto::channel_member::Kind::AncestorMember.into(),
646 role: proto::ChannelRole::Admin.into(),
647 },
648 proto::ChannelMember {
649 user_id: member.to_proto(),
650 kind: proto::channel_member::Kind::AncestorMember.into(),
651 role: proto::ChannelRole::Member.into(),
652 },
653 ]
654 );
655
656 db.respond_to_channel_invite(zed_channel, guest, true)
657 .await
658 .unwrap();
659
660 db.transaction(|tx| async move {
661 db.check_user_is_channel_participant(
662 &db.get_channel_internal(zed_channel, &*tx).await.unwrap(),
663 guest,
664 &*tx,
665 )
666 .await
667 })
668 .await
669 .unwrap();
670 assert!(db
671 .transaction(|tx| async move {
672 db.check_user_is_channel_participant(
673 &db.get_channel_internal(active_channel_id, &*tx)
674 .await
675 .unwrap(),
676 guest,
677 &*tx,
678 )
679 .await
680 })
681 .await
682 .is_err(),);
683
684 db.transaction(|tx| async move {
685 db.check_user_is_channel_participant(
686 &db.get_channel_internal(vim_channel_id, &*tx).await.unwrap(),
687 guest,
688 &*tx,
689 )
690 .await
691 })
692 .await
693 .unwrap();
694
695 let mut members = db
696 .get_channel_participant_details(vim_channel_id, admin)
697 .await
698 .unwrap();
699
700 members.sort_by_key(|member| member.user_id);
701
702 assert_eq!(
703 members,
704 &[
705 proto::ChannelMember {
706 user_id: admin.to_proto(),
707 kind: proto::channel_member::Kind::AncestorMember.into(),
708 role: proto::ChannelRole::Admin.into(),
709 },
710 proto::ChannelMember {
711 user_id: member.to_proto(),
712 kind: proto::channel_member::Kind::AncestorMember.into(),
713 role: proto::ChannelRole::Member.into(),
714 },
715 proto::ChannelMember {
716 user_id: guest.to_proto(),
717 kind: proto::channel_member::Kind::AncestorMember.into(),
718 role: proto::ChannelRole::Guest.into(),
719 },
720 ]
721 );
722
723 let channels = db.get_channels_for_user(guest).await.unwrap().channels;
724 assert_channel_tree(
725 channels,
726 &[(zed_channel, &[]), (vim_channel_id, &[zed_channel])],
727 )
728}
729
730test_both_dbs!(
731 test_user_joins_correct_channel,
732 test_user_joins_correct_channel_postgres,
733 test_user_joins_correct_channel_sqlite
734);
735
736async fn test_user_joins_correct_channel(db: &Arc<Database>) {
737 let admin = new_test_user(db, "admin@example.com").await;
738
739 let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
740
741 let active_channel = db
742 .create_sub_channel("active", zed_channel, admin)
743 .await
744 .unwrap();
745
746 let vim_channel = db
747 .create_sub_channel("vim", active_channel, admin)
748 .await
749 .unwrap();
750
751 let vim2_channel = db
752 .create_sub_channel("vim2", vim_channel, admin)
753 .await
754 .unwrap();
755
756 db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
757 .await
758 .unwrap();
759
760 db.set_channel_visibility(vim_channel, crate::db::ChannelVisibility::Public, admin)
761 .await
762 .unwrap();
763
764 db.set_channel_visibility(vim2_channel, crate::db::ChannelVisibility::Public, admin)
765 .await
766 .unwrap();
767
768 let most_public = db
769 .transaction(|tx| async move {
770 Ok(db
771 .public_ancestors_including_self(
772 &db.get_channel_internal(vim_channel, &*tx).await.unwrap(),
773 &tx,
774 )
775 .await?
776 .first()
777 .cloned())
778 })
779 .await
780 .unwrap()
781 .unwrap()
782 .id;
783
784 assert_eq!(most_public, zed_channel)
785}
786
787test_both_dbs!(
788 test_guest_access,
789 test_guest_access_postgres,
790 test_guest_access_sqlite
791);
792
793async fn test_guest_access(db: &Arc<Database>) {
794 let server = db.create_server("test").await.unwrap();
795
796 let admin = new_test_user(db, "admin@example.com").await;
797 let guest = new_test_user(db, "guest@example.com").await;
798 let guest_connection = new_test_connection(server);
799
800 let zed_channel = db.create_root_channel("zed", admin).await.unwrap();
801 db.set_channel_visibility(zed_channel, crate::db::ChannelVisibility::Public, admin)
802 .await
803 .unwrap();
804
805 assert!(db
806 .join_channel_chat(zed_channel, guest_connection, guest)
807 .await
808 .is_err());
809
810 db.join_channel(zed_channel, guest, guest_connection, TEST_RELEASE_CHANNEL)
811 .await
812 .unwrap();
813
814 assert!(db
815 .join_channel_chat(zed_channel, guest_connection, guest)
816 .await
817 .is_ok())
818}
819
820#[track_caller]
821fn assert_channel_tree(actual: Vec<Channel>, expected: &[(ChannelId, &[ChannelId])]) {
822 let actual = actual
823 .iter()
824 .map(|channel| (channel.id, channel.parent_path.as_slice()))
825 .collect::<Vec<_>>();
826 pretty_assertions::assert_eq!(
827 actual,
828 expected.to_vec(),
829 "wrong channel ids and parent paths"
830 );
831}