Get project2 tests green

Nathan Sobo created

Change summary

crates/gpui2/src/app/test_context.rs | 44 +++++++++++++++++------------
crates/project2/src/project_tests.rs |  5 ++-
crates/project2/src/worktree.rs      |  1 
crates/ui2/src/components/panes.rs   |  2 
crates/ui2/src/components/tab.rs     |  2 
5 files changed, 31 insertions(+), 23 deletions(-)

Detailed changes

crates/gpui2/src/app/test_context.rs 🔗

@@ -3,8 +3,8 @@ use crate::{
     ForegroundExecutor, Model, ModelContext, Result, Task, TestDispatcher, TestPlatform,
     WindowContext,
 };
-use anyhow::anyhow;
-use futures::{SinkExt, StreamExt};
+use anyhow::{anyhow, bail};
+use futures::{SinkExt, Stream, StreamExt};
 use std::{cell::RefCell, future::Future, rc::Rc, sync::Arc, time::Duration};
 
 #[derive(Clone)]
@@ -140,7 +140,25 @@ impl TestAppContext {
         }
     }
 
-    pub fn subscribe<T: 'static + EventEmitter>(
+    pub fn notifications<T: 'static>(&mut self, entity: &Model<T>) -> impl Stream<Item = ()> {
+        let (tx, rx) = futures::channel::mpsc::unbounded();
+
+        entity.update(self, move |_, cx: &mut ModelContext<T>| {
+            cx.observe(entity, {
+                let tx = tx.clone();
+                move |_, _, _| {
+                    let _ = tx.unbounded_send(());
+                }
+            })
+            .detach();
+
+            cx.on_release(move |_, _| tx.close_channel()).detach();
+        });
+
+        rx
+    }
+
+    pub fn events<T: 'static + EventEmitter>(
         &mut self,
         entity: &Model<T>,
     ) -> futures::channel::mpsc::UnboundedReceiver<T::Event>
@@ -160,36 +178,24 @@ impl TestAppContext {
         rx
     }
 
-    pub async fn condition<T: EventEmitter + 'static>(
+    pub async fn condition<T: 'static>(
         &mut self,
         model: &Model<T>,
         mut predicate: impl FnMut(&mut T, &mut ModelContext<T>) -> bool,
     ) {
-        let (mut tx, mut rx) = futures::channel::mpsc::unbounded::<()>();
         let timer = self.executor().timer(Duration::from_secs(3));
-
-        let subscriptions = model.update(self, move |_, cx| {
-            (
-                cx.observe(model, move |_, _, _| {
-                    // let _ = tx.send(());
-                }),
-                cx.subscribe(model, move |_, _, _, _| {
-                    let _ = tx.send(());
-                }),
-            )
-        });
+        let mut notifications = self.notifications(model);
 
         use futures::FutureExt as _;
         use smol::future::FutureExt as _;
 
         async {
-            while rx.next().await.is_some() {
+            while notifications.next().await.is_some() {
                 if model.update(self, &mut predicate) {
                     return Ok(());
                 }
             }
-            drop(subscriptions);
-            unreachable!()
+            bail!("model dropped")
         }
         .race(timer.map(|_| Err(anyhow!("condition timed out"))))
         .await

crates/project2/src/project_tests.rs 🔗

@@ -947,7 +947,7 @@ async fn test_disk_based_diagnostics_progress(cx: &mut gpui2::TestAppContext) {
         .await
         .unwrap();
 
-    let mut events = cx.subscribe(&project);
+    let mut events = cx.events(&project);
 
     let fake_server = fake_servers.next().await.unwrap();
     assert_eq!(
@@ -1078,7 +1078,7 @@ async fn test_restarting_server_with_diagnostics_running(cx: &mut gpui2::TestApp
     project.update(cx, |project, cx| {
         project.restart_language_servers_for_buffers([buffer], cx);
     });
-    let mut events = cx.subscribe(&project);
+    let mut events = cx.events(&project);
 
     // Simulate the newly started server sending more diagnostics.
     let fake_server = fake_servers.next().await.unwrap();
@@ -2788,6 +2788,7 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui2::TestAppContext) {
     });
 
     let remote = cx.update(|cx| Worktree::remote(1, 1, metadata, rpc.clone(), cx));
+
     cx.executor().run_until_parked();
 
     cx.update(|cx| {

crates/project2/src/worktree.rs 🔗

@@ -4065,6 +4065,7 @@ impl WorktreeModelHandle for Model<Worktree> {
             fs.create_file(&root_path.join(file_name), Default::default())
                 .await
                 .unwrap();
+
             cx.condition(&tree, |tree, _| tree.entry_for_path(file_name).is_some())
                 .await;
 

crates/ui2/src/components/panes.rs 🔗

@@ -51,7 +51,7 @@ impl<V: 'static> Pane<V> {
                     .id("drag-target")
                     .drag_over::<ExternalPaths>(|d| d.bg(red()))
                     .on_drop(|_, files: View<ExternalPaths>, cx| {
-                        dbg!("dropped files!", files.read(cx));
+                        eprintln!("dropped files! {:?}", files.read(cx));
                     })
                     .absolute()
                     .inset_0(),

crates/ui2/src/components/tab.rs 🔗

@@ -130,7 +130,7 @@ impl Tab {
             .on_drag(move |_view, cx| cx.build_view(|cx| drag_state.clone()))
             .drag_over::<TabDragState>(|d| d.bg(black()))
             .on_drop(|_view, state: View<TabDragState>, cx| {
-                dbg!(state.read(cx));
+                eprintln!("{:?}", state.read(cx));
             })
             .px_2()
             .py_0p5()