From ed8b022b51d75c891378525f12fae9412b6bddfb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Sep 2023 18:03:38 -0700 Subject: [PATCH] Add initial failing test for following to channel notes in an unshared project --- .../collab/src/tests/channel_buffer_tests.rs | 91 ++++++++++++++++++- crates/collab/src/tests/test_server.rs | 4 +- crates/collab_ui/src/channel_view.rs | 16 ++-- 3 files changed, 102 insertions(+), 9 deletions(-) diff --git a/crates/collab/src/tests/channel_buffer_tests.rs b/crates/collab/src/tests/channel_buffer_tests.rs index ba5a70895a..fc2d118cf8 100644 --- a/crates/collab/src/tests/channel_buffer_tests.rs +++ b/crates/collab/src/tests/channel_buffer_tests.rs @@ -274,7 +274,10 @@ async fn test_channel_buffer_replica_ids( } #[gpui::test] -async fn test_reopen_channel_buffer(deterministic: Arc, cx_a: &mut TestAppContext) { +async fn test_multiple_handles_to_channel_buffer( + deterministic: Arc, + cx_a: &mut TestAppContext, +) { deterministic.forbid_parking(); let mut server = TestServer::start(&deterministic).await; let client_a = server.create_client(cx_a, "user_a").await; @@ -578,6 +581,92 @@ async fn test_channel_buffers_and_server_restarts( }); } +#[gpui::test(iterations = 10)] +async fn test_following_to_channel_notes_without_a_shared_project( + deterministic: Arc, + mut cx_a: &mut TestAppContext, + mut cx_b: &mut TestAppContext, + mut cx_c: &mut TestAppContext, +) { + deterministic.forbid_parking(); + let mut server = TestServer::start(&deterministic).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; + let client_c = server.create_client(cx_c, "user_c").await; + + let channel_1_id = server + .make_channel( + "channel-1", + (&client_a, cx_a), + &mut [(&client_b, cx_b), (&client_c, cx_c)], + ) + .await; + let channel_2_id = server + .make_channel( + "channel-2", + (&client_a, cx_a), + &mut [(&client_b, cx_b), (&client_c, cx_c)], + ) + .await; + + // Clients A, B, and C join a channel. + let active_call_a = cx_a.read(ActiveCall::global); + let active_call_b = cx_b.read(ActiveCall::global); + let active_call_c = cx_c.read(ActiveCall::global); + for (call, cx) in [ + (&active_call_a, &mut cx_a), + (&active_call_b, &mut cx_b), + (&active_call_c, &mut cx_c), + ] { + call.update(*cx, |call, cx| call.join_channel(channel_1_id, cx)) + .await + .unwrap(); + } + deterministic.run_until_parked(); + + // Clients A, B, and C all open their own unshared projects. + client_a.fs().insert_tree("/a", json!({})).await; + client_b.fs().insert_tree("/b", json!({})).await; + client_c.fs().insert_tree("/c", json!({})).await; + let (project_a, _) = client_a.build_local_project("/a", cx_a).await; + let (project_b, _) = client_b.build_local_project("/b", cx_b).await; + let (project_c, _) = client_b.build_local_project("/c", cx_c).await; + let workspace_a = client_a.build_workspace(&project_a, cx_a).root(cx_a); + let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b); + let workspace_c = client_c.build_workspace(&project_c, cx_c).root(cx_c); + + // Client A opens the notes for channel 1. + let channel_view_1_a = cx_a + .update(|cx| { + ChannelView::open( + channel_1_id, + workspace_a.read(cx).active_pane().clone(), + workspace_a.clone(), + cx, + ) + }) + .await + .unwrap(); + + // Client B follows client A. + workspace_b + .update(cx_b, |workspace, cx| { + workspace + .toggle_follow(client_a.peer_id().unwrap(), cx) + .unwrap() + }) + .await + .unwrap(); + + deterministic.run_until_parked(); + workspace_b.read_with(cx_b, |workspace, _| { + assert_eq!( + workspace.leader_for_pane(workspace.active_pane()), + Some(client_a.peer_id().unwrap()) + ); + }); +} + #[track_caller] fn assert_collaborators(collaborators: &[proto::Collaborator], ids: &[Option]) { assert_eq!( diff --git a/crates/collab/src/tests/test_server.rs b/crates/collab/src/tests/test_server.rs index 6572722df3..6a15cac9e9 100644 --- a/crates/collab/src/tests/test_server.rs +++ b/crates/collab/src/tests/test_server.rs @@ -206,11 +206,13 @@ impl TestServer { let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx)); let channel_store = cx.add_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx)); + let mut language_registry = LanguageRegistry::test(); + language_registry.set_executor(cx.background()); let app_state = Arc::new(workspace::AppState { client: client.clone(), user_store: user_store.clone(), channel_store: channel_store.clone(), - languages: Arc::new(LanguageRegistry::test()), + languages: Arc::new(language_registry), fs: fs.clone(), build_window_options: |_, _, _| Default::default(), initialize_workspace: |_, _, _, _| Task::ready(Ok(())), diff --git a/crates/collab_ui/src/channel_view.rs b/crates/collab_ui/src/channel_view.rs index c6f32cecd2..4e6a369db6 100644 --- a/crates/collab_ui/src/channel_view.rs +++ b/crates/collab_ui/src/channel_view.rs @@ -14,6 +14,7 @@ use gpui::{ }; use project::Project; use std::any::{Any, TypeId}; +use util::ResultExt; use workspace::{ item::{FollowableItem, Item, ItemHandle}, register_followable_item, @@ -53,7 +54,7 @@ impl ChannelView { &workspace.read(cx).app_state().client, cx, ); - pane.add_item(Box::new(channel_view), true, true, None, cx); + pane.add_item(Box::new(channel_view.clone()), true, true, None, cx); }); anyhow::Ok(()) }) @@ -79,12 +80,13 @@ impl ChannelView { cx.spawn(|mut cx| async move { let channel_buffer = channel_buffer.await?; - let markdown = markdown.await?; - channel_buffer.update(&mut cx, |buffer, cx| { - buffer.buffer().update(cx, |buffer, cx| { - buffer.set_language(Some(markdown), cx); - }) - }); + if let Some(markdown) = markdown.await.log_err() { + channel_buffer.update(&mut cx, |buffer, cx| { + buffer.buffer().update(cx, |buffer, cx| { + buffer.set_language(Some(markdown), cx); + }) + }); + } pane.update(&mut cx, |pane, cx| { pane.items_of_type::()