Refactored terminal tests

Mikayla Maki created

Change summary

crates/terminal/src/terminal.rs                    | 160 ++-------------
crates/terminal/src/tests/terminal_test_context.rs | 108 +++++++++-
2 files changed, 121 insertions(+), 147 deletions(-)

Detailed changes

crates/terminal/src/terminal.rs 🔗

@@ -507,7 +507,6 @@ mod tests {
     use gpui::TestAppContext;
 
     use std::path::Path;
-    use workspace::AppState;
 
     mod terminal_test_context;
 
@@ -515,7 +514,7 @@ mod tests {
     //and produce noticable output?
     #[gpui::test(retries = 5)]
     async fn test_terminal(cx: &mut TestAppContext) {
-        let mut cx = TerminalTestContext::new(cx);
+        let mut cx = TerminalTestContext::new(cx, true);
 
         cx.execute_and_wait("expr 3 + 4", |content, _cx| content.contains("7"))
             .await;
@@ -527,12 +526,10 @@ mod tests {
     #[gpui::test]
     async fn no_worktree(cx: &mut TestAppContext) {
         //Setup variables
-        let params = cx.update(AppState::test);
-        let project = Project::test(params.fs.clone(), [], cx).await;
-        let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
-
+        let mut cx = TerminalTestContext::new(cx, true);
+        let (project, workspace) = cx.blank_workspace().await;
         //Test
-        cx.read(|cx| {
+        cx.cx.read(|cx| {
             let workspace = workspace.read(cx);
             let active_entry = project.read(cx).active_entry();
 
@@ -551,28 +548,12 @@ mod tests {
     #[gpui::test]
     async fn no_active_entry_worktree_is_file(cx: &mut TestAppContext) {
         //Setup variables
-        let params = cx.update(AppState::test);
-        let project = Project::test(params.fs.clone(), [], cx).await;
-        let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
-        let (wt, _) = project
-            .update(cx, |project, cx| {
-                project.find_or_create_local_worktree("/root.txt", true, cx)
-            })
-            .await
-            .unwrap();
-
-        cx.update(|cx| {
-            wt.update(cx, |wt, cx| {
-                wt.as_local()
-                    .unwrap()
-                    .create_entry(Path::new(""), false, cx)
-            })
-        })
-        .await
-        .unwrap();
 
-        //Test
-        cx.read(|cx| {
+        let mut cx = TerminalTestContext::new(cx, true);
+        let (project, workspace) = cx.blank_workspace().await;
+        cx.create_file_wt(project.clone(), "/root.txt").await;
+
+        cx.cx.read(|cx| {
             let workspace = workspace.read(cx);
             let active_entry = project.read(cx).active_entry();
 
@@ -591,27 +572,12 @@ mod tests {
     #[gpui::test]
     async fn no_active_entry_worktree_is_dir(cx: &mut TestAppContext) {
         //Setup variables
-        let params = cx.update(AppState::test);
-        let project = Project::test(params.fs.clone(), [], cx).await;
-        let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
-        let (wt, _) = project
-            .update(cx, |project, cx| {
-                project.find_or_create_local_worktree("/root/", true, cx)
-            })
-            .await
-            .unwrap();
-
-        //Setup root folder
-        cx.update(|cx| {
-            wt.update(cx, |wt, cx| {
-                wt.as_local().unwrap().create_entry(Path::new(""), true, cx)
-            })
-        })
-        .await
-        .unwrap();
+        let mut cx = TerminalTestContext::new(cx, true);
+        let (project, workspace) = cx.blank_workspace().await;
+        let (_wt, _entry) = cx.create_folder_wt(project.clone(), "/root/").await;
 
         //Test
-        cx.update(|cx| {
+        cx.cx.update(|cx| {
             let workspace = workspace.read(cx);
             let active_entry = project.read(cx).active_entry();
 
@@ -629,53 +595,14 @@ mod tests {
     #[gpui::test]
     async fn active_entry_worktree_is_file(cx: &mut TestAppContext) {
         //Setup variables
-        let params = cx.update(AppState::test);
-        let project = Project::test(params.fs.clone(), [], cx).await;
-        let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
-        let (wt1, _) = project
-            .update(cx, |project, cx| {
-                project.find_or_create_local_worktree("/root1/", true, cx)
-            })
-            .await
-            .unwrap();
-
-        let (wt2, _) = project
-            .update(cx, |project, cx| {
-                project.find_or_create_local_worktree("/root2.txt", true, cx)
-            })
-            .await
-            .unwrap();
-
-        //Setup root
-        let _ = cx
-            .update(|cx| {
-                wt1.update(cx, |wt, cx| {
-                    wt.as_local().unwrap().create_entry(Path::new(""), true, cx)
-                })
-            })
-            .await
-            .unwrap();
-        let entry2 = cx
-            .update(|cx| {
-                wt2.update(cx, |wt, cx| {
-                    wt.as_local()
-                        .unwrap()
-                        .create_entry(Path::new(""), false, cx)
-                })
-            })
-            .await
-            .unwrap();
-
-        cx.update(|cx| {
-            let p = ProjectPath {
-                worktree_id: wt2.read(cx).id(),
-                path: entry2.path,
-            };
-            project.update(cx, |project, cx| project.set_active_path(Some(p), cx));
-        });
+        let mut cx = TerminalTestContext::new(cx, true);
+        let (project, workspace) = cx.blank_workspace().await;
+        let (_wt, _entry) = cx.create_folder_wt(project.clone(), "/root1/").await;
+        let (wt2, entry2) = cx.create_file_wt(project.clone(), "/root2.txt").await;
+        cx.insert_active_entry_for(wt2, entry2, project.clone());
 
         //Test
-        cx.update(|cx| {
+        cx.cx.update(|cx| {
             let workspace = workspace.read(cx);
             let active_entry = project.read(cx).active_entry();
 
@@ -692,51 +619,14 @@ mod tests {
     #[gpui::test]
     async fn active_entry_worktree_is_dir(cx: &mut TestAppContext) {
         //Setup variables
-        let params = cx.update(AppState::test);
-        let project = Project::test(params.fs.clone(), [], cx).await;
-        let (_, workspace) = cx.add_window(|cx| Workspace::new(project.clone(), cx));
-        let (wt1, _) = project
-            .update(cx, |project, cx| {
-                project.find_or_create_local_worktree("/root1/", true, cx)
-            })
-            .await
-            .unwrap();
-
-        let (wt2, _) = project
-            .update(cx, |project, cx| {
-                project.find_or_create_local_worktree("/root2/", true, cx)
-            })
-            .await
-            .unwrap();
-
-        //Setup root
-        let _ = cx
-            .update(|cx| {
-                wt1.update(cx, |wt, cx| {
-                    wt.as_local().unwrap().create_entry(Path::new(""), true, cx)
-                })
-            })
-            .await
-            .unwrap();
-        let entry2 = cx
-            .update(|cx| {
-                wt2.update(cx, |wt, cx| {
-                    wt.as_local().unwrap().create_entry(Path::new(""), true, cx)
-                })
-            })
-            .await
-            .unwrap();
-
-        cx.update(|cx| {
-            let p = ProjectPath {
-                worktree_id: wt2.read(cx).id(),
-                path: entry2.path,
-            };
-            project.update(cx, |project, cx| project.set_active_path(Some(p), cx));
-        });
+        let mut cx = TerminalTestContext::new(cx, true);
+        let (project, workspace) = cx.blank_workspace().await;
+        let (_wt, _entry) = cx.create_folder_wt(project.clone(), "/root1/").await;
+        let (wt2, entry2) = cx.create_folder_wt(project.clone(), "/root2/").await;
+        cx.insert_active_entry_for(wt2, entry2, project.clone());
 
         //Test
-        cx.update(|cx| {
+        cx.cx.update(|cx| {
             let workspace = workspace.read(cx);
             let active_entry = project.read(cx).active_entry();
 

crates/terminal/src/tests/terminal_test_context.rs 🔗

@@ -1,7 +1,11 @@
-use std::time::Duration;
+use std::{path::Path, time::Duration};
 
-use gpui::{geometry::vector::vec2f, AppContext, ModelHandle, ReadModelWith, TestAppContext};
+use gpui::{
+    geometry::vector::vec2f, AppContext, ModelHandle, ReadModelWith, TestAppContext, ViewHandle,
+};
 use itertools::Itertools;
+use project::{Entry, Project, ProjectPath, Worktree};
+use workspace::{AppState, Workspace};
 
 use crate::{
     connection::{Terminal, TerminalBuilder},
@@ -11,11 +15,11 @@ use crate::{
 
 pub struct TerminalTestContext<'a> {
     pub cx: &'a mut TestAppContext,
-    pub connection: ModelHandle<Terminal>,
+    pub connection: Option<ModelHandle<Terminal>>,
 }
 
 impl<'a> TerminalTestContext<'a> {
-    pub fn new(cx: &'a mut TestAppContext) -> Self {
+    pub fn new(cx: &'a mut TestAppContext, term: bool) -> Self {
         cx.set_condition_duration(Some(Duration::from_secs(5)));
 
         let size_info = TerminalDimensions::new(
@@ -24,10 +28,12 @@ impl<'a> TerminalTestContext<'a> {
             vec2f(DEBUG_TERMINAL_WIDTH, DEBUG_TERMINAL_HEIGHT),
         );
 
-        let connection = cx.add_model(|cx| {
-            TerminalBuilder::new(None, None, None, size_info)
-                .unwrap()
-                .subscribe(cx)
+        let connection = term.then(|| {
+            cx.add_model(|cx| {
+                TerminalBuilder::new(None, None, None, size_info)
+                    .unwrap()
+                    .subscribe(cx)
+            })
         });
 
         TerminalTestContext { cx, connection }
@@ -37,23 +43,101 @@ impl<'a> TerminalTestContext<'a> {
     where
         F: Fn(String, &AppContext) -> bool,
     {
+        let connection = self.connection.take().unwrap();
+
         let command = command.to_string();
-        self.connection.update(self.cx, |connection, _| {
+        connection.update(self.cx, |connection, _| {
             connection.write_to_pty(command);
             connection.write_to_pty("\r".to_string());
         });
 
-        self.connection
+        connection
             .condition(self.cx, |conn, cx| {
                 let content = Self::grid_as_str(conn);
                 f(content, cx)
             })
             .await;
 
-        self.cx
-            .read_model_with(&self.connection, &mut |conn, _: &AppContext| {
+        let res = self
+            .cx
+            .read_model_with(&connection, &mut |conn, _: &AppContext| {
                 Self::grid_as_str(conn)
+            });
+
+        self.connection = Some(connection);
+
+        res
+    }
+
+    ///Creates a worktree with 1 file: /root.txt
+    pub async fn blank_workspace(&mut self) -> (ModelHandle<Project>, ViewHandle<Workspace>) {
+        let params = self.cx.update(AppState::test);
+
+        let project = Project::test(params.fs.clone(), [], self.cx).await;
+        let (_, workspace) = self.cx.add_window(|cx| Workspace::new(project.clone(), cx));
+
+        (project, workspace)
+    }
+
+    ///Creates a worktree with 1 folder: /root{suffix}/
+    pub async fn create_folder_wt(
+        &mut self,
+        project: ModelHandle<Project>,
+        path: impl AsRef<Path>,
+    ) -> (ModelHandle<Worktree>, Entry) {
+        self.create_wt(project, true, path).await
+    }
+
+    ///Creates a worktree with 1 file: /root{suffix}.txt
+    pub async fn create_file_wt(
+        &mut self,
+        project: ModelHandle<Project>,
+        path: impl AsRef<Path>,
+    ) -> (ModelHandle<Worktree>, Entry) {
+        self.create_wt(project, false, path).await
+    }
+
+    async fn create_wt(
+        &mut self,
+        project: ModelHandle<Project>,
+        is_dir: bool,
+        path: impl AsRef<Path>,
+    ) -> (ModelHandle<Worktree>, Entry) {
+        let (wt, _) = project
+            .update(self.cx, |project, cx| {
+                project.find_or_create_local_worktree(path, true, cx)
+            })
+            .await
+            .unwrap();
+
+        let entry = self
+            .cx
+            .update(|cx| {
+                wt.update(cx, |wt, cx| {
+                    wt.as_local()
+                        .unwrap()
+                        .create_entry(Path::new(""), is_dir, cx)
+                })
             })
+            .await
+            .unwrap();
+
+        (wt, entry)
+    }
+
+    pub fn insert_active_entry_for(
+        &mut self,
+        wt: ModelHandle<Worktree>,
+        entry: Entry,
+        project: ModelHandle<Project>,
+    ) {
+        self.cx.update(|cx| {
+            let p = ProjectPath {
+                worktree_id: wt.read(cx).id(),
+                path: entry.path,
+            };
+            project.update(cx, |project, cx| project.set_active_path(Some(p), cx));
+        });
     }
 
     fn grid_as_str(connection: &Terminal) -> String {