@@ -593,6 +593,7 @@ impl PickerDelegate for FileFinderDelegate {
}
fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<FileFinderDelegate>>) {
+ dbg!("CONFIRMING???");
if let Some(m) = self.matches.get(self.selected_index()) {
if let Some(workspace) = self.workspace.upgrade() {
let open_task = workspace.update(cx, move |workspace, cx| {
@@ -690,6 +691,7 @@ impl PickerDelegate for FileFinderDelegate {
.log_err();
}
}
+ dbg!("DISMISSING");
finder
.update(&mut cx, |_, cx| cx.emit(ModalEvent::Dismissed))
.ok()?;
@@ -739,1236 +741,1236 @@ impl PickerDelegate for FileFinderDelegate {
}
}
-#[cfg(test)]
-mod tests {
- use std::{assert_eq, collections::HashMap, path::Path, time::Duration};
-
- use super::*;
- use editor::Editor;
- use gpui::{Entity, TestAppContext, VisualTestContext};
- use menu::{Confirm, SelectNext};
- use serde_json::json;
- use workspace::{AppState, Workspace};
-
- #[ctor::ctor]
- fn init_logger() {
- if std::env::var("RUST_LOG").is_ok() {
- env_logger::init();
- }
- }
-
- #[gpui::test]
- async fn test_matching_paths(cx: &mut TestAppContext) {
- let app_state = init_test(cx);
- app_state
- .fs
- .as_fake()
- .insert_tree(
- "/root",
- json!({
- "a": {
- "banana": "",
- "bandana": "",
- }
- }),
- )
- .await;
-
- let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
-
- let (picker, workspace, mut cx) = build_find_picker(project, cx);
- let cx = &mut cx;
-
- picker
- .update(cx, |picker, cx| {
- picker.delegate.update_matches("bna".to_string(), cx)
- })
- .await;
-
- picker.update(cx, |picker, _| {
- assert_eq!(picker.delegate.matches.len(), 2);
- });
-
- let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
- cx.dispatch_action(SelectNext);
- cx.dispatch_action(Confirm);
- active_pane
- .condition(cx, |pane, _| pane.active_item().is_some())
- .await;
- cx.read(|cx| {
- let active_item = active_pane.read(cx).active_item().unwrap();
- assert_eq!(
- active_item
- .to_any()
- .downcast::<Editor>()
- .unwrap()
- .read(cx)
- .title(cx),
- "bandana"
- );
- });
- }
-
- #[gpui::test]
- async fn test_row_column_numbers_query_inside_file(cx: &mut TestAppContext) {
- let app_state = init_test(cx);
-
- let first_file_name = "first.rs";
- let first_file_contents = "// First Rust file";
- app_state
- .fs
- .as_fake()
- .insert_tree(
- "/src",
- json!({
- "test": {
- first_file_name: first_file_contents,
- "second.rs": "// Second Rust file",
- }
- }),
- )
- .await;
-
- let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-
- let (picker, workspace, mut cx) = build_find_picker(project, cx);
- let cx = &mut cx;
-
- let file_query = &first_file_name[..3];
- let file_row = 1;
- let file_column = 3;
- assert!(file_column <= first_file_contents.len());
- let query_inside_file = format!("{file_query}:{file_row}:{file_column}");
- picker
- .update(cx, |finder, cx| {
- finder
- .delegate
- .update_matches(query_inside_file.to_string(), cx)
- })
- .await;
- picker.update(cx, |finder, _| {
- let finder = &finder.delegate;
- assert_eq!(finder.matches.len(), 1);
- let latest_search_query = finder
- .latest_search_query
- .as_ref()
- .expect("Finder should have a query after the update_matches call");
- assert_eq!(latest_search_query.path_like.raw_query, query_inside_file);
- assert_eq!(
- latest_search_query.path_like.file_query_end,
- Some(file_query.len())
- );
- assert_eq!(latest_search_query.row, Some(file_row));
- assert_eq!(latest_search_query.column, Some(file_column as u32));
- });
-
- let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
- cx.dispatch_action(SelectNext);
- cx.dispatch_action(Confirm);
- active_pane
- .condition(cx, |pane, _| pane.active_item().is_some())
- .await;
- let editor = cx.update(|cx| {
- let active_item = active_pane.read(cx).active_item().unwrap();
- active_item.downcast::<Editor>().unwrap()
- });
- cx.executor().advance_clock(Duration::from_secs(2));
-
- editor.update(cx, |editor, cx| {
- let all_selections = editor.selections.all_adjusted(cx);
- assert_eq!(
- all_selections.len(),
- 1,
- "Expected to have 1 selection (caret) after file finder confirm, but got: {all_selections:?}"
- );
- let caret_selection = all_selections.into_iter().next().unwrap();
- assert_eq!(caret_selection.start, caret_selection.end,
- "Caret selection should have its start and end at the same position");
- assert_eq!(file_row, caret_selection.start.row + 1,
- "Query inside file should get caret with the same focus row");
- assert_eq!(file_column, caret_selection.start.column as usize + 1,
- "Query inside file should get caret with the same focus column");
- });
- }
-
- #[gpui::test]
- async fn test_row_column_numbers_query_outside_file(cx: &mut TestAppContext) {
- let app_state = init_test(cx);
-
- let first_file_name = "first.rs";
- let first_file_contents = "// First Rust file";
- app_state
- .fs
- .as_fake()
- .insert_tree(
- "/src",
- json!({
- "test": {
- first_file_name: first_file_contents,
- "second.rs": "// Second Rust file",
- }
- }),
- )
- .await;
-
- let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
-
- let (picker, workspace, mut cx) = build_find_picker(project, cx);
- let cx = &mut cx;
-
- let file_query = &first_file_name[..3];
- let file_row = 200;
- let file_column = 300;
- assert!(file_column > first_file_contents.len());
- let query_outside_file = format!("{file_query}:{file_row}:{file_column}");
- picker
- .update(cx, |picker, cx| {
- picker
- .delegate
- .update_matches(query_outside_file.to_string(), cx)
- })
- .await;
- picker.update(cx, |finder, _| {
- let delegate = &finder.delegate;
- assert_eq!(delegate.matches.len(), 1);
- let latest_search_query = delegate
- .latest_search_query
- .as_ref()
- .expect("Finder should have a query after the update_matches call");
- assert_eq!(latest_search_query.path_like.raw_query, query_outside_file);
- assert_eq!(
- latest_search_query.path_like.file_query_end,
- Some(file_query.len())
- );
- assert_eq!(latest_search_query.row, Some(file_row));
- assert_eq!(latest_search_query.column, Some(file_column as u32));
- });
-
- let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
- cx.dispatch_action(SelectNext);
- cx.dispatch_action(Confirm);
- active_pane
- .condition(cx, |pane, _| pane.active_item().is_some())
- .await;
- let editor = cx.update(|cx| {
- let active_item = active_pane.read(cx).active_item().unwrap();
- active_item.downcast::<Editor>().unwrap()
- });
- cx.executor().advance_clock(Duration::from_secs(2));
-
- editor.update(cx, |editor, cx| {
- let all_selections = editor.selections.all_adjusted(cx);
- assert_eq!(
- all_selections.len(),
- 1,
- "Expected to have 1 selection (caret) after file finder confirm, but got: {all_selections:?}"
- );
- let caret_selection = all_selections.into_iter().next().unwrap();
- assert_eq!(caret_selection.start, caret_selection.end,
- "Caret selection should have its start and end at the same position");
- assert_eq!(0, caret_selection.start.row,
- "Excessive rows (as in query outside file borders) should get trimmed to last file row");
- assert_eq!(first_file_contents.len(), caret_selection.start.column as usize,
- "Excessive columns (as in query outside file borders) should get trimmed to selected row's last column");
- });
- }
-
- #[gpui::test]
- async fn test_matching_cancellation(cx: &mut TestAppContext) {
- let app_state = init_test(cx);
- app_state
- .fs
- .as_fake()
- .insert_tree(
- "/dir",
- json!({
- "hello": "",
- "goodbye": "",
- "halogen-light": "",
- "happiness": "",
- "height": "",
- "hi": "",
- "hiccup": "",
- }),
- )
- .await;
-
- let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
-
- let (picker, _, mut cx) = build_find_picker(project, cx);
- let cx = &mut cx;
-
- let query = test_path_like("hi");
- picker
- .update(cx, |picker, cx| {
- picker.delegate.spawn_search(query.clone(), cx)
- })
- .await;
-
- picker.update(cx, |picker, _cx| {
- assert_eq!(picker.delegate.matches.len(), 5)
- });
-
- picker.update(cx, |picker, cx| {
- let delegate = &mut picker.delegate;
- assert!(
- delegate.matches.history.is_empty(),
- "Search matches expected"
- );
- let matches = delegate.matches.search.clone();
-
- // Simulate a search being cancelled after the time limit,
- // returning only a subset of the matches that would have been found.
- drop(delegate.spawn_search(query.clone(), cx));
- delegate.set_search_matches(
- delegate.latest_search_id,
- true, // did-cancel
- query.clone(),
- vec![matches[1].clone(), matches[3].clone()],
- cx,
- );
-
- // Simulate another cancellation.
- drop(delegate.spawn_search(query.clone(), cx));
- delegate.set_search_matches(
- delegate.latest_search_id,
- true, // did-cancel
- query.clone(),
- vec![matches[0].clone(), matches[2].clone(), matches[3].clone()],
- cx,
- );
-
- assert!(
- delegate.matches.history.is_empty(),
- "Search matches expected"
- );
- assert_eq!(delegate.matches.search.as_slice(), &matches[0..4]);
- });
- }
-
- #[gpui::test]
- async fn test_ignored_files(cx: &mut TestAppContext) {
- let app_state = init_test(cx);
- app_state
- .fs
- .as_fake()
- .insert_tree(
- "/ancestor",
- json!({
- ".gitignore": "ignored-root",
- "ignored-root": {
- "happiness": "",
- "height": "",
- "hi": "",
- "hiccup": "",
- },
- "tracked-root": {
- ".gitignore": "height",
- "happiness": "",
- "height": "",
- "hi": "",
- "hiccup": "",
- },
- }),
- )
- .await;
-
- let project = Project::test(
- app_state.fs.clone(),
- [
- "/ancestor/tracked-root".as_ref(),
- "/ancestor/ignored-root".as_ref(),
- ],
- cx,
- )
- .await;
-
- let (picker, _, mut cx) = build_find_picker(project, cx);
- let cx = &mut cx;
-
- picker
- .update(cx, |picker, cx| {
- picker.delegate.spawn_search(test_path_like("hi"), cx)
- })
- .await;
- picker.update(cx, |picker, _| assert_eq!(picker.delegate.matches.len(), 7));
- }
-
- // #[gpui::test]
- // async fn test_single_file_worktrees(cx: &mut TestAppContext) {
- // let app_state = init_test(cx);
- // app_state
- // .fs
- // .as_fake()
- // .insert_tree("/root", json!({ "the-parent-dir": { "the-file": "" } }))
- // .await;
-
- // let project = Project::test(
- // app_state.fs.clone(),
- // ["/root/the-parent-dir/the-file".as_ref()],
- // cx,
- // )
- // .await;
-
- // let (picker, _, mut cx) = build_find_picker(project, cx);
- // let cx = &mut cx;
-
- // // Even though there is only one worktree, that worktree's filename
- // // is included in the matching, because the worktree is a single file.
- // picker
- // .update(cx, |picker, cx| {
- // picker.delegate.spawn_search(test_path_like("thf"), cx)
- // })
- // .await;
- // cx.read(|cx| {
- // let picker = picker.read(cx);
- // let delegate = &picker.delegate;
- // assert!(
- // delegate.matches.history.is_empty(),
- // "Search matches expected"
- // );
- // let matches = delegate.matches.search.clone();
- // assert_eq!(matches.len(), 1);
-
- // let (file_name, file_name_positions, full_path, full_path_positions) =
- // delegate.labels_for_path_match(&matches[0]);
- // assert_eq!(file_name, "the-file");
- // assert_eq!(file_name_positions, &[0, 1, 4]);
- // assert_eq!(full_path, "the-file");
- // assert_eq!(full_path_positions, &[0, 1, 4]);
- // });
-
- // // Since the worktree root is a file, searching for its name followed by a slash does
- // // not match anything.
- // picker
- // .update(cx, |f, cx| {
- // f.delegate.spawn_search(test_path_like("thf/"), cx)
- // })
- // .await;
- // picker.update(cx, |f, _| assert_eq!(f.delegate.matches.len(), 0));
- // }
-
- // #[gpui::test]
- // async fn test_path_distance_ordering(cx: &mut TestAppContext) {
- // let app_state = init_test(cx);
- // app_state
- // .fs
- // .as_fake()
- // .insert_tree(
- // "/root",
- // json!({
- // "dir1": { "a.txt": "" },
- // "dir2": {
- // "a.txt": "",
- // "b.txt": ""
- // }
- // }),
- // )
- // .await;
-
- // let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- // let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
- // let cx = &mut cx;
-
- // let worktree_id = cx.read(|cx| {
- // let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
- // assert_eq!(worktrees.len(), 1);
- // WorktreeId::from_usize(worktrees[0].id())
- // });
-
- // // When workspace has an active item, sort items which are closer to that item
- // // first when they have the same name. In this case, b.txt is closer to dir2's a.txt
- // // so that one should be sorted earlier
- // let b_path = Some(dummy_found_path(ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("/root/dir2/b.txt")),
- // }));
- // cx.dispatch_action(Toggle);
-
- // let finder = cx
- // .add_window(|cx| {
- // Picker::new(
- // FileFinderDelegate::new(
- // workspace.downgrade(),
- // workspace.read(cx).project().clone(),
- // b_path,
- // Vec::new(),
- // cx,
- // ),
- // cx,
- // )
- // })
- // .root(cx);
-
- // finder
- // .update(cx, |f, cx| {
- // f.delegate.spawn_search(test_path_like("a.txt"), cx)
- // })
- // .await;
-
- // finder.read_with(cx, |f, _| {
- // let delegate = &f.delegate;
- // assert!(
- // delegate.matches.history.is_empty(),
- // "Search matches expected"
- // );
- // let matches = delegate.matches.search.clone();
- // assert_eq!(matches[0].path.as_ref(), Path::new("dir2/a.txt"));
- // assert_eq!(matches[1].path.as_ref(), Path::new("dir1/a.txt"));
- // });
- // }
-
- // #[gpui::test]
- // async fn test_search_worktree_without_files(cx: &mut TestAppContext) {
- // let app_state = init_test(cx);
- // app_state
- // .fs
- // .as_fake()
- // .insert_tree(
- // "/root",
- // json!({
- // "dir1": {},
- // "dir2": {
- // "dir3": {}
- // }
- // }),
- // )
- // .await;
-
- // let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
- // let workspace = cx
- // .add_window(|cx| Workspace::test_new(project, cx))
- // .root(cx);
- // let finder = cx
- // .add_window(|cx| {
- // Picker::new(
- // FileFinderDelegate::new(
- // workspace.downgrade(),
- // workspace.read(cx).project().clone(),
- // None,
- // Vec::new(),
- // cx,
- // ),
- // cx,
- // )
- // })
- // .root(cx);
- // finder
- // .update(cx, |f, cx| {
- // f.delegate.spawn_search(test_path_like("dir"), cx)
- // })
- // .await;
- // cx.read(|cx| {
- // let finder = finder.read(cx);
- // assert_eq!(finder.delegate.matches.len(), 0);
- // });
- // }
-
- // #[gpui::test]
- // async fn test_query_history(cx: &mut gpui::TestAppContext) {
- // let app_state = init_test(cx);
-
- // app_state
- // .fs
- // .as_fake()
- // .insert_tree(
- // "/src",
- // json!({
- // "test": {
- // "first.rs": "// First Rust file",
- // "second.rs": "// Second Rust file",
- // "third.rs": "// Third Rust file",
- // }
- // }),
- // )
- // .await;
-
- // let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- // let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
- // let cx = &mut cx;
- // let worktree_id = cx.read(|cx| {
- // let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
- // assert_eq!(worktrees.len(), 1);
- // WorktreeId::from_usize(worktrees[0].id())
- // });
-
- // // Open and close panels, getting their history items afterwards.
- // // Ensure history items get populated with opened items, and items are kept in a certain order.
- // // The history lags one opened buffer behind, since it's updated in the search panel only on its reopen.
- // //
- // // TODO: without closing, the opened items do not propagate their history changes for some reason
- // // it does work in real app though, only tests do not propagate.
-
- // let initial_history = open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
- // assert!(
- // initial_history.is_empty(),
- // "Should have no history before opening any files"
- // );
-
- // let history_after_first =
- // open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
- // assert_eq!(
- // history_after_first,
- // vec![FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/first.rs")),
- // },
- // Some(PathBuf::from("/src/test/first.rs"))
- // )],
- // "Should show 1st opened item in the history when opening the 2nd item"
- // );
-
- // let history_after_second =
- // open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
- // assert_eq!(
- // history_after_second,
- // vec![
- // FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/second.rs")),
- // },
- // Some(PathBuf::from("/src/test/second.rs"))
- // ),
- // FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/first.rs")),
- // },
- // Some(PathBuf::from("/src/test/first.rs"))
- // ),
- // ],
- // "Should show 1st and 2nd opened items in the history when opening the 3rd item. \
- // 2nd item should be the first in the history, as the last opened."
- // );
-
- // let history_after_third =
- // open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
- // assert_eq!(
- // history_after_third,
- // vec![
- // FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/third.rs")),
- // },
- // Some(PathBuf::from("/src/test/third.rs"))
- // ),
- // FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/second.rs")),
- // },
- // Some(PathBuf::from("/src/test/second.rs"))
- // ),
- // FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/first.rs")),
- // },
- // Some(PathBuf::from("/src/test/first.rs"))
- // ),
- // ],
- // "Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
- // 3rd item should be the first in the history, as the last opened."
- // );
-
- // let history_after_second_again =
- // open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
- // assert_eq!(
- // history_after_second_again,
- // vec![
- // FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/second.rs")),
- // },
- // Some(PathBuf::from("/src/test/second.rs"))
- // ),
- // FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/third.rs")),
- // },
- // Some(PathBuf::from("/src/test/third.rs"))
- // ),
- // FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/first.rs")),
- // },
- // Some(PathBuf::from("/src/test/first.rs"))
- // ),
- // ],
- // "Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
- // 2nd item, as the last opened, 3rd item should go next as it was opened right before."
- // );
- // }
-
- // #[gpui::test]
- // async fn test_external_files_history(cx: &mut gpui::TestAppContext) {
- // let app_state = init_test(cx);
-
- // app_state
- // .fs
- // .as_fake()
- // .insert_tree(
- // "/src",
- // json!({
- // "test": {
- // "first.rs": "// First Rust file",
- // "second.rs": "// Second Rust file",
- // }
- // }),
- // )
- // .await;
-
- // app_state
- // .fs
- // .as_fake()
- // .insert_tree(
- // "/external-src",
- // json!({
- // "test": {
- // "third.rs": "// Third Rust file",
- // "fourth.rs": "// Fourth Rust file",
- // }
- // }),
- // )
- // .await;
-
- // let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- // cx.update(|cx| {
- // project.update(cx, |project, cx| {
- // project.find_or_create_local_worktree("/external-src", false, cx)
- // })
- // })
- // .detach();
- // cx.background_executor.run_until_parked();
-
- // let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
- // let cx = &mut cx;
- // let worktree_id = cx.read(|cx| {
- // let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
- // assert_eq!(worktrees.len(), 1,);
-
- // WorktreeId::from_usize(worktrees[0].id())
- // });
- // workspace
- // .update(cx, |workspace, cx| {
- // workspace.open_abs_path(PathBuf::from("/external-src/test/third.rs"), false, cx)
- // })
- // .detach();
- // cx.background_executor.run_until_parked();
- // let external_worktree_id = cx.read(|cx| {
- // let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
- // assert_eq!(
- // worktrees.len(),
- // 2,
- // "External file should get opened in a new worktree"
- // );
-
- // WorktreeId::from_usize(
- // worktrees
- // .into_iter()
- // .find(|worktree| worktree.entity_id() != worktree_id.to_usize())
- // .expect("New worktree should have a different id")
- // .id(),
- // )
- // });
- // close_active_item(&workspace, cx).await;
-
- // let initial_history_items =
- // open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
- // assert_eq!(
- // initial_history_items,
- // vec![FoundPath::new(
- // ProjectPath {
- // worktree_id: external_worktree_id,
- // path: Arc::from(Path::new("")),
- // },
- // Some(PathBuf::from("/external-src/test/third.rs"))
- // )],
- // "Should show external file with its full path in the history after it was open"
- // );
-
- // let updated_history_items =
- // open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
- // assert_eq!(
- // updated_history_items,
- // vec![
- // FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/second.rs")),
- // },
- // Some(PathBuf::from("/src/test/second.rs"))
- // ),
- // FoundPath::new(
- // ProjectPath {
- // worktree_id: external_worktree_id,
- // path: Arc::from(Path::new("")),
- // },
- // Some(PathBuf::from("/external-src/test/third.rs"))
- // ),
- // ],
- // "Should keep external file with history updates",
- // );
- // }
-
- #[gpui::test]
- async fn test_toggle_panel_new_selections(cx: &mut gpui::TestAppContext) {
- let app_state = init_test(cx);
-
- app_state
- .fs
- .as_fake()
- .insert_tree(
- "/src",
- json!({
- "test": {
- "first.rs": "// First Rust file",
- "second.rs": "// Second Rust file",
- "third.rs": "// Third Rust file",
- }
- }),
- )
- .await;
-
- let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
- let cx = &mut cx;
-
- // generate some history to select from
- open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
- open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
- open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
- let current_history =
- open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
-
- for expected_selected_index in 0..current_history.len() {
- cx.dispatch_action(Toggle);
- let selected_index = workspace.update(cx, |workspace, cx| {
- workspace
- .current_modal::<FileFinder>(cx)
- .unwrap()
- .read(cx)
- .picker
- .read(cx)
- .delegate
- .selected_index()
- });
- assert_eq!(
- selected_index, expected_selected_index,
- "Should select the next item in the history"
- );
- }
-
- cx.dispatch_action(Toggle);
- let selected_index = workspace.update(cx, |workspace, cx| {
- workspace
- .current_modal::<FileFinder>(cx)
- .unwrap()
- .read(cx)
- .picker
- .read(cx)
- .delegate
- .selected_index()
- });
- assert_eq!(
- selected_index, 0,
- "Should wrap around the history and start all over"
- );
- }
-
- // #[gpui::test]
- // async fn test_search_preserves_history_items(cx: &mut gpui::TestAppContext) {
- // let app_state = init_test(cx);
-
- // app_state
- // .fs
- // .as_fake()
- // .insert_tree(
- // "/src",
- // json!({
- // "test": {
- // "first.rs": "// First Rust file",
- // "second.rs": "// Second Rust file",
- // "third.rs": "// Third Rust file",
- // "fourth.rs": "// Fourth Rust file",
- // }
- // }),
- // )
- // .await;
-
- // let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- // let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
- // let cx = &mut cx;
- // let worktree_id = cx.read(|cx| {
- // let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
- // assert_eq!(worktrees.len(), 1,);
-
- // WorktreeId::from_usize(worktrees[0].entity_id())
- // });
-
- // // generate some history to select from
- // open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
- // open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
- // open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
- // open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
-
- // cx.dispatch_action(Toggle);
- // let first_query = "f";
- // let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
- // finder
- // .update(cx, |finder, cx| {
- // finder.delegate.update_matches(first_query.to_string(), cx)
- // })
- // .await;
- // finder.read_with(cx, |finder, _| {
- // let delegate = &finder.delegate;
- // assert_eq!(delegate.matches.history.len(), 1, "Only one history item contains {first_query}, it should be present and others should be filtered out");
- // let history_match = delegate.matches.history.first().unwrap();
- // assert!(history_match.1.is_some(), "Should have path matches for history items after querying");
- // assert_eq!(history_match.0, FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/first.rs")),
- // },
- // Some(PathBuf::from("/src/test/first.rs"))
- // ));
- // assert_eq!(delegate.matches.search.len(), 1, "Only one non-history item contains {first_query}, it should be present");
- // assert_eq!(delegate.matches.search.first().unwrap().path.as_ref(), Path::new("test/fourth.rs"));
- // });
-
- // let second_query = "fsdasdsa";
- // let finder = workspace.update(cx, |workspace, cx| {
- // workspace
- // .current_modal::<FileFinder>(cx)
- // .unwrap()
- // .read(cx)
- // .picker
- // });
- // finder
- // .update(cx, |finder, cx| {
- // finder.delegate.update_matches(second_query.to_string(), cx)
- // })
- // .await;
- // finder.update(cx, |finder, _| {
- // let delegate = &finder.delegate;
- // assert!(
- // delegate.matches.history.is_empty(),
- // "No history entries should match {second_query}"
- // );
- // assert!(
- // delegate.matches.search.is_empty(),
- // "No search entries should match {second_query}"
- // );
- // });
-
- // let first_query_again = first_query;
-
- // let finder = workspace.update(cx, |workspace, cx| {
- // workspace
- // .current_modal::<FileFinder>(cx)
- // .unwrap()
- // .read(cx)
- // .picker
- // });
- // finder
- // .update(cx, |finder, cx| {
- // finder
- // .delegate
- // .update_matches(first_query_again.to_string(), cx)
- // })
- // .await;
- // finder.read_with(cx, |finder, _| {
- // let delegate = &finder.delegate;
- // assert_eq!(delegate.matches.history.len(), 1, "Only one history item contains {first_query_again}, it should be present and others should be filtered out, even after non-matching query");
- // let history_match = delegate.matches.history.first().unwrap();
- // assert!(history_match.1.is_some(), "Should have path matches for history items after querying");
- // assert_eq!(history_match.0, FoundPath::new(
- // ProjectPath {
- // worktree_id,
- // path: Arc::from(Path::new("test/first.rs")),
- // },
- // Some(PathBuf::from("/src/test/first.rs"))
- // ));
- // assert_eq!(delegate.matches.search.len(), 1, "Only one non-history item contains {first_query_again}, it should be present, even after non-matching query");
- // assert_eq!(delegate.matches.search.first().unwrap().path.as_ref(), Path::new("test/fourth.rs"));
- // });
- // }
-
- // #[gpui::test]
- // async fn test_history_items_vs_very_good_external_match(cx: &mut gpui::TestAppContext) {
- // let app_state = init_test(cx);
-
- // app_state
- // .fs
- // .as_fake()
- // .insert_tree(
- // "/src",
- // json!({
- // "collab_ui": {
- // "first.rs": "// First Rust file",
- // "second.rs": "// Second Rust file",
- // "third.rs": "// Third Rust file",
- // "collab_ui.rs": "// Fourth Rust file",
- // }
- // }),
- // )
- // .await;
-
- // let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- // let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
- // let cx = &mut cx;
- // // generate some history to select from
- // open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
- // open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
- // open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
- // open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
-
- // cx.dispatch_action(Toggle);
- // let query = "collab_ui";
- // let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
- // finder
- // .update(cx, |finder, cx| {
- // finder.delegate.update_matches(query.to_string(), cx)
- // })
- // .await;
- // finder.read_with(cx, |finder, _| {
- // let delegate = &finder.delegate;
- // assert!(
- // delegate.matches.history.is_empty(),
- // "History items should not math query {query}, they should be matched by name only"
- // );
-
- // let search_entries = delegate
- // .matches
- // .search
- // .iter()
- // .map(|path_match| path_match.path.to_path_buf())
- // .collect::<Vec<_>>();
- // assert_eq!(
- // search_entries,
- // vec![
- // PathBuf::from("collab_ui/collab_ui.rs"),
- // PathBuf::from("collab_ui/third.rs"),
- // PathBuf::from("collab_ui/first.rs"),
- // PathBuf::from("collab_ui/second.rs"),
- // ],
- // "Despite all search results having the same directory name, the most matching one should be on top"
- // );
- // });
- // }
-
- // #[gpui::test]
- // async fn test_nonexistent_history_items_not_shown(cx: &mut gpui::TestAppContext) {
- // let app_state = init_test(cx);
-
- // app_state
- // .fs
- // .as_fake()
- // .insert_tree(
- // "/src",
- // json!({
- // "test": {
- // "first.rs": "// First Rust file",
- // "nonexistent.rs": "// Second Rust file",
- // "third.rs": "// Third Rust file",
- // }
- // }),
- // )
- // .await;
-
- // let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
- // let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
- // let cx = &mut cx;
- // // generate some history to select from
- // open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
- // open_close_queried_buffer("non", 1, "nonexistent.rs", &workspace, cx).await;
- // open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
- // open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
-
- // cx.dispatch_action(Toggle);
- // let query = "rs";
- // let finder = cx.read(|cx| workspace.read(cx).current_modal::<FileFinder>().unwrap());
- // finder
- // .update(cx, |finder, cx| {
- // finder.picker.update(cx, |picker, cx| {
- // picker.delegate.update_matches(query.to_string(), cx)
- // })
- // })
- // .await;
- // finder.update(cx, |finder, _| {
- // let history_entries = finder.delegate
- // .matches
- // .history
- // .iter()
- // .map(|(_, path_match)| path_match.as_ref().expect("should have a path match").path.to_path_buf())
- // .collect::<Vec<_>>();
- // assert_eq!(
- // history_entries,
- // vec![
- // PathBuf::from("test/first.rs"),
- // PathBuf::from("test/third.rs"),
- // ],
- // "Should have all opened files in the history, except the ones that do not exist on disk"
- // );
- // });
- // }
-
- async fn open_close_queried_buffer(
- input: &str,
- expected_matches: usize,
- expected_editor_title: &str,
- workspace: &View<Workspace>,
- cx: &mut gpui::VisualTestContext<'_>,
- ) -> Vec<FoundPath> {
- cx.dispatch_action(Toggle);
- let picker = workspace.update(cx, |workspace, cx| {
- workspace
- .current_modal::<FileFinder>(cx)
- .unwrap()
- .read(cx)
- .picker
- .clone()
- });
- picker
- .update(cx, |finder, cx| {
- finder.delegate.update_matches(input.to_string(), cx)
- })
- .await;
- let history_items = picker.update(cx, |finder, _| {
- assert_eq!(
- finder.delegate.matches.len(),
- expected_matches,
- "Unexpected number of matches found for query {input}"
- );
- finder.delegate.history_items.clone()
- });
-
- let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
- cx.dispatch_action(SelectNext);
- cx.dispatch_action(Confirm);
- cx.background_executor.run_until_parked();
- active_pane
- .condition(cx, |pane, _| pane.active_item().is_some())
- .await;
- cx.read(|cx| {
- let active_item = active_pane.read(cx).active_item().unwrap();
- let active_editor_title = active_item
- .to_any()
- .downcast::<Editor>()
- .unwrap()
- .read(cx)
- .title(cx);
- assert_eq!(
- expected_editor_title, active_editor_title,
- "Unexpected editor title for query {input}"
- );
- });
-
- close_active_item(workspace, cx).await;
-
- history_items
- }
-
- async fn close_active_item(workspace: &View<Workspace>, cx: &mut VisualTestContext<'_>) {
- let mut original_items = HashMap::new();
- cx.read(|cx| {
- for pane in workspace.read(cx).panes() {
- let pane_id = pane.entity_id();
- let pane = pane.read(cx);
- let insertion_result = original_items.insert(pane_id, pane.items().count());
- assert!(insertion_result.is_none(), "Pane id {pane_id} collision");
- }
- });
-
- let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
- active_pane
- .update(cx, |pane, cx| {
- pane.close_active_item(&workspace::CloseActiveItem { save_intent: None }, cx)
- .unwrap()
- })
- .await
- .unwrap();
- cx.background_executor.run_until_parked();
- cx.read(|cx| {
- for pane in workspace.read(cx).panes() {
- let pane_id = pane.entity_id();
- let pane = pane.read(cx);
- match original_items.remove(&pane_id) {
- Some(original_items) => {
- assert_eq!(
- pane.items().count(),
- original_items.saturating_sub(1),
- "Pane id {pane_id} should have item closed"
- );
- }
- None => panic!("Pane id {pane_id} not found in original items"),
- }
- }
- });
- assert!(
- original_items.len() <= 1,
- "At most one panel should got closed"
- );
- }
-
- fn init_test(cx: &mut TestAppContext) -> Arc<AppState> {
- cx.update(|cx| {
- let state = AppState::test(cx);
- theme::init(cx);
- language::init(cx);
- super::init(cx);
- editor::init(cx);
- workspace::init_settings(cx);
- Project::init_settings(cx);
- state
- })
- }
-
- fn test_path_like(test_str: &str) -> PathLikeWithPosition<FileSearchQuery> {
- PathLikeWithPosition::parse_str(test_str, |path_like_str| {
- Ok::<_, std::convert::Infallible>(FileSearchQuery {
- raw_query: test_str.to_owned(),
- file_query_end: if path_like_str == test_str {
- None
- } else {
- Some(path_like_str.len())
- },
- })
- })
- .unwrap()
- }
-
- fn dummy_found_path(project_path: ProjectPath) -> FoundPath {
- FoundPath {
- project: project_path,
- absolute: None,
- }
- }
-
- fn build_find_picker(
- project: Model<Project>,
- cx: &mut TestAppContext,
- ) -> (
- View<Picker<FileFinderDelegate>>,
- View<Workspace>,
- VisualTestContext,
- ) {
- let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
- cx.dispatch_action(Toggle);
- let picker = workspace.update(&mut cx, |workspace, cx| {
- workspace
- .current_modal::<FileFinder>(cx)
- .unwrap()
- .read(cx)
- .picker
- .clone()
- });
- (picker, workspace, cx)
- }
-}
+// #[cfg(test)]
+// mod tests {
+// use std::{assert_eq, collections::HashMap, path::Path, time::Duration};
+
+// use super::*;
+// use editor::Editor;
+// use gpui::{Entity, TestAppContext, VisualTestContext};
+// use menu::{Confirm, SelectNext};
+// use serde_json::json;
+// use workspace::{AppState, Workspace};
+
+// #[ctor::ctor]
+// fn init_logger() {
+// if std::env::var("RUST_LOG").is_ok() {
+// env_logger::init();
+// }
+// }
+
+// #[gpui::test]
+// async fn test_matching_paths(cx: &mut TestAppContext) {
+// let app_state = init_test(cx);
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/root",
+// json!({
+// "a": {
+// "banana": "",
+// "bandana": "",
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
+
+// let (picker, workspace, mut cx) = build_find_picker(project, cx);
+// let cx = &mut cx;
+
+// picker
+// .update(cx, |picker, cx| {
+// picker.delegate.update_matches("bna".to_string(), cx)
+// })
+// .await;
+
+// picker.update(cx, |picker, _| {
+// assert_eq!(picker.delegate.matches.len(), 2);
+// });
+
+// let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+// cx.dispatch_action(SelectNext);
+// cx.dispatch_action(Confirm);
+// active_pane
+// .condition(cx, |pane, _| pane.active_item().is_some())
+// .await;
+// cx.read(|cx| {
+// let active_item = active_pane.read(cx).active_item().unwrap();
+// assert_eq!(
+// active_item
+// .to_any()
+// .downcast::<Editor>()
+// .unwrap()
+// .read(cx)
+// .title(cx),
+// "bandana"
+// );
+// });
+// }
+
+// #[gpui::test]
+// async fn test_row_column_numbers_query_inside_file(cx: &mut TestAppContext) {
+// let app_state = init_test(cx);
+
+// let first_file_name = "first.rs";
+// let first_file_contents = "// First Rust file";
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/src",
+// json!({
+// "test": {
+// first_file_name: first_file_contents,
+// "second.rs": "// Second Rust file",
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+
+// let (picker, workspace, mut cx) = build_find_picker(project, cx);
+// let cx = &mut cx;
+
+// let file_query = &first_file_name[..3];
+// let file_row = 1;
+// let file_column = 3;
+// assert!(file_column <= first_file_contents.len());
+// let query_inside_file = format!("{file_query}:{file_row}:{file_column}");
+// picker
+// .update(cx, |finder, cx| {
+// finder
+// .delegate
+// .update_matches(query_inside_file.to_string(), cx)
+// })
+// .await;
+// picker.update(cx, |finder, _| {
+// let finder = &finder.delegate;
+// assert_eq!(finder.matches.len(), 1);
+// let latest_search_query = finder
+// .latest_search_query
+// .as_ref()
+// .expect("Finder should have a query after the update_matches call");
+// assert_eq!(latest_search_query.path_like.raw_query, query_inside_file);
+// assert_eq!(
+// latest_search_query.path_like.file_query_end,
+// Some(file_query.len())
+// );
+// assert_eq!(latest_search_query.row, Some(file_row));
+// assert_eq!(latest_search_query.column, Some(file_column as u32));
+// });
+
+// let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+// cx.dispatch_action(SelectNext);
+// cx.dispatch_action(Confirm);
+// active_pane
+// .condition(cx, |pane, _| pane.active_item().is_some())
+// .await;
+// let editor = cx.update(|cx| {
+// let active_item = active_pane.read(cx).active_item().unwrap();
+// active_item.downcast::<Editor>().unwrap()
+// });
+// cx.executor().advance_clock(Duration::from_secs(2));
+
+// editor.update(cx, |editor, cx| {
+// let all_selections = editor.selections.all_adjusted(cx);
+// assert_eq!(
+// all_selections.len(),
+// 1,
+// "Expected to have 1 selection (caret) after file finder confirm, but got: {all_selections:?}"
+// );
+// let caret_selection = all_selections.into_iter().next().unwrap();
+// assert_eq!(caret_selection.start, caret_selection.end,
+// "Caret selection should have its start and end at the same position");
+// assert_eq!(file_row, caret_selection.start.row + 1,
+// "Query inside file should get caret with the same focus row");
+// assert_eq!(file_column, caret_selection.start.column as usize + 1,
+// "Query inside file should get caret with the same focus column");
+// });
+// }
+
+// #[gpui::test]
+// async fn test_row_column_numbers_query_outside_file(cx: &mut TestAppContext) {
+// let app_state = init_test(cx);
+
+// let first_file_name = "first.rs";
+// let first_file_contents = "// First Rust file";
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/src",
+// json!({
+// "test": {
+// first_file_name: first_file_contents,
+// "second.rs": "// Second Rust file",
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+
+// let (picker, workspace, mut cx) = build_find_picker(project, cx);
+// let cx = &mut cx;
+
+// let file_query = &first_file_name[..3];
+// let file_row = 200;
+// let file_column = 300;
+// assert!(file_column > first_file_contents.len());
+// let query_outside_file = format!("{file_query}:{file_row}:{file_column}");
+// picker
+// .update(cx, |picker, cx| {
+// picker
+// .delegate
+// .update_matches(query_outside_file.to_string(), cx)
+// })
+// .await;
+// picker.update(cx, |finder, _| {
+// let delegate = &finder.delegate;
+// assert_eq!(delegate.matches.len(), 1);
+// let latest_search_query = delegate
+// .latest_search_query
+// .as_ref()
+// .expect("Finder should have a query after the update_matches call");
+// assert_eq!(latest_search_query.path_like.raw_query, query_outside_file);
+// assert_eq!(
+// latest_search_query.path_like.file_query_end,
+// Some(file_query.len())
+// );
+// assert_eq!(latest_search_query.row, Some(file_row));
+// assert_eq!(latest_search_query.column, Some(file_column as u32));
+// });
+
+// let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+// cx.dispatch_action(SelectNext);
+// cx.dispatch_action(Confirm);
+// active_pane
+// .condition(cx, |pane, _| pane.active_item().is_some())
+// .await;
+// let editor = cx.update(|cx| {
+// let active_item = active_pane.read(cx).active_item().unwrap();
+// active_item.downcast::<Editor>().unwrap()
+// });
+// cx.executor().advance_clock(Duration::from_secs(2));
+
+// editor.update(cx, |editor, cx| {
+// let all_selections = editor.selections.all_adjusted(cx);
+// assert_eq!(
+// all_selections.len(),
+// 1,
+// "Expected to have 1 selection (caret) after file finder confirm, but got: {all_selections:?}"
+// );
+// let caret_selection = all_selections.into_iter().next().unwrap();
+// assert_eq!(caret_selection.start, caret_selection.end,
+// "Caret selection should have its start and end at the same position");
+// assert_eq!(0, caret_selection.start.row,
+// "Excessive rows (as in query outside file borders) should get trimmed to last file row");
+// assert_eq!(first_file_contents.len(), caret_selection.start.column as usize,
+// "Excessive columns (as in query outside file borders) should get trimmed to selected row's last column");
+// });
+// }
+
+// #[gpui::test]
+// async fn test_matching_cancellation(cx: &mut TestAppContext) {
+// let app_state = init_test(cx);
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/dir",
+// json!({
+// "hello": "",
+// "goodbye": "",
+// "halogen-light": "",
+// "happiness": "",
+// "height": "",
+// "hi": "",
+// "hiccup": "",
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
+
+// let (picker, _, mut cx) = build_find_picker(project, cx);
+// let cx = &mut cx;
+
+// let query = test_path_like("hi");
+// picker
+// .update(cx, |picker, cx| {
+// picker.delegate.spawn_search(query.clone(), cx)
+// })
+// .await;
+
+// picker.update(cx, |picker, _cx| {
+// assert_eq!(picker.delegate.matches.len(), 5)
+// });
+
+// picker.update(cx, |picker, cx| {
+// let delegate = &mut picker.delegate;
+// assert!(
+// delegate.matches.history.is_empty(),
+// "Search matches expected"
+// );
+// let matches = delegate.matches.search.clone();
+
+// // Simulate a search being cancelled after the time limit,
+// // returning only a subset of the matches that would have been found.
+// drop(delegate.spawn_search(query.clone(), cx));
+// delegate.set_search_matches(
+// delegate.latest_search_id,
+// true, // did-cancel
+// query.clone(),
+// vec![matches[1].clone(), matches[3].clone()],
+// cx,
+// );
+
+// // Simulate another cancellation.
+// drop(delegate.spawn_search(query.clone(), cx));
+// delegate.set_search_matches(
+// delegate.latest_search_id,
+// true, // did-cancel
+// query.clone(),
+// vec![matches[0].clone(), matches[2].clone(), matches[3].clone()],
+// cx,
+// );
+
+// assert!(
+// delegate.matches.history.is_empty(),
+// "Search matches expected"
+// );
+// assert_eq!(delegate.matches.search.as_slice(), &matches[0..4]);
+// });
+// }
+
+// #[gpui::test]
+// async fn test_ignored_files(cx: &mut TestAppContext) {
+// let app_state = init_test(cx);
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/ancestor",
+// json!({
+// ".gitignore": "ignored-root",
+// "ignored-root": {
+// "happiness": "",
+// "height": "",
+// "hi": "",
+// "hiccup": "",
+// },
+// "tracked-root": {
+// ".gitignore": "height",
+// "happiness": "",
+// "height": "",
+// "hi": "",
+// "hiccup": "",
+// },
+// }),
+// )
+// .await;
+
+// let project = Project::test(
+// app_state.fs.clone(),
+// [
+// "/ancestor/tracked-root".as_ref(),
+// "/ancestor/ignored-root".as_ref(),
+// ],
+// cx,
+// )
+// .await;
+
+// let (picker, _, mut cx) = build_find_picker(project, cx);
+// let cx = &mut cx;
+
+// picker
+// .update(cx, |picker, cx| {
+// picker.delegate.spawn_search(test_path_like("hi"), cx)
+// })
+// .await;
+// picker.update(cx, |picker, _| assert_eq!(picker.delegate.matches.len(), 7));
+// }
+
+// #[gpui::test]
+// async fn test_single_file_worktrees(cx: &mut TestAppContext) {
+// let app_state = init_test(cx);
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree("/root", json!({ "the-parent-dir": { "the-file": "" } }))
+// .await;
+
+// let project = Project::test(
+// app_state.fs.clone(),
+// ["/root/the-parent-dir/the-file".as_ref()],
+// cx,
+// )
+// .await;
+
+// let (picker, _, mut cx) = build_find_picker(project, cx);
+// let cx = &mut cx;
+
+// // Even though there is only one worktree, that worktree's filename
+// // is included in the matching, because the worktree is a single file.
+// picker
+// .update(cx, |picker, cx| {
+// picker.delegate.spawn_search(test_path_like("thf"), cx)
+// })
+// .await;
+// cx.read(|cx| {
+// let picker = picker.read(cx);
+// let delegate = &picker.delegate;
+// assert!(
+// delegate.matches.history.is_empty(),
+// "Search matches expected"
+// );
+// let matches = delegate.matches.search.clone();
+// assert_eq!(matches.len(), 1);
+
+// let (file_name, file_name_positions, full_path, full_path_positions) =
+// delegate.labels_for_path_match(&matches[0]);
+// assert_eq!(file_name, "the-file");
+// assert_eq!(file_name_positions, &[0, 1, 4]);
+// assert_eq!(full_path, "the-file");
+// assert_eq!(full_path_positions, &[0, 1, 4]);
+// });
+
+// // Since the worktree root is a file, searching for its name followed by a slash does
+// // not match anything.
+// picker
+// .update(cx, |f, cx| {
+// f.delegate.spawn_search(test_path_like("thf/"), cx)
+// })
+// .await;
+// picker.update(cx, |f, _| assert_eq!(f.delegate.matches.len(), 0));
+// }
+
+// #[gpui::test]
+// async fn test_path_distance_ordering(cx: &mut TestAppContext) {
+// let app_state = init_test(cx);
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/root",
+// json!({
+// "dir1": { "a.txt": "" },
+// "dir2": {
+// "a.txt": "",
+// "b.txt": ""
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
+// let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+// let cx = &mut cx;
+
+// let worktree_id = cx.read(|cx| {
+// let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+// assert_eq!(worktrees.len(), 1);
+// WorktreeId::from_usize(worktrees[0].id())
+// });
+
+// // When workspace has an active item, sort items which are closer to that item
+// // first when they have the same name. In this case, b.txt is closer to dir2's a.txt
+// // so that one should be sorted earlier
+// let b_path = Some(dummy_found_path(ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("/root/dir2/b.txt")),
+// }));
+// cx.dispatch_action(Toggle);
+
+// let finder = cx
+// .add_window(|cx| {
+// Picker::new(
+// FileFinderDelegate::new(
+// workspace.downgrade(),
+// workspace.read(cx).project().clone(),
+// b_path,
+// Vec::new(),
+// cx,
+// ),
+// cx,
+// )
+// })
+// .root(cx);
+
+// finder
+// .update(cx, |f, cx| {
+// f.delegate.spawn_search(test_path_like("a.txt"), cx)
+// })
+// .await;
+
+// finder.read_with(cx, |f, _| {
+// let delegate = &f.delegate;
+// assert!(
+// delegate.matches.history.is_empty(),
+// "Search matches expected"
+// );
+// let matches = delegate.matches.search.clone();
+// assert_eq!(matches[0].path.as_ref(), Path::new("dir2/a.txt"));
+// assert_eq!(matches[1].path.as_ref(), Path::new("dir1/a.txt"));
+// });
+// }
+
+// #[gpui::test]
+// async fn test_search_worktree_without_files(cx: &mut TestAppContext) {
+// let app_state = init_test(cx);
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/root",
+// json!({
+// "dir1": {},
+// "dir2": {
+// "dir3": {}
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
+// let workspace = cx
+// .add_window(|cx| Workspace::test_new(project, cx))
+// .root(cx);
+// let finder = cx
+// .add_window(|cx| {
+// Picker::new(
+// FileFinderDelegate::new(
+// workspace.downgrade(),
+// workspace.read(cx).project().clone(),
+// None,
+// Vec::new(),
+// cx,
+// ),
+// cx,
+// )
+// })
+// .root(cx);
+// finder
+// .update(cx, |f, cx| {
+// f.delegate.spawn_search(test_path_like("dir"), cx)
+// })
+// .await;
+// cx.read(|cx| {
+// let finder = finder.read(cx);
+// assert_eq!(finder.delegate.matches.len(), 0);
+// });
+// }
+
+// #[gpui::test]
+// async fn test_query_history(cx: &mut gpui::TestAppContext) {
+// let app_state = init_test(cx);
+
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/src",
+// json!({
+// "test": {
+// "first.rs": "// First Rust file",
+// "second.rs": "// Second Rust file",
+// "third.rs": "// Third Rust file",
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+// let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+// let cx = &mut cx;
+// let worktree_id = cx.read(|cx| {
+// let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+// assert_eq!(worktrees.len(), 1);
+// WorktreeId::from_usize(worktrees[0].id())
+// });
+
+// // Open and close panels, getting their history items afterwards.
+// // Ensure history items get populated with opened items, and items are kept in a certain order.
+// // The history lags one opened buffer behind, since it's updated in the search panel only on its reopen.
+// //
+// // TODO: without closing, the opened items do not propagate their history changes for some reason
+// // it does work in real app though, only tests do not propagate.
+
+// let initial_history = open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
+// assert!(
+// initial_history.is_empty(),
+// "Should have no history before opening any files"
+// );
+
+// let history_after_first =
+// open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
+// assert_eq!(
+// history_after_first,
+// vec![FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/first.rs")),
+// },
+// Some(PathBuf::from("/src/test/first.rs"))
+// )],
+// "Should show 1st opened item in the history when opening the 2nd item"
+// );
+
+// let history_after_second =
+// open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
+// assert_eq!(
+// history_after_second,
+// vec![
+// FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/second.rs")),
+// },
+// Some(PathBuf::from("/src/test/second.rs"))
+// ),
+// FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/first.rs")),
+// },
+// Some(PathBuf::from("/src/test/first.rs"))
+// ),
+// ],
+// "Should show 1st and 2nd opened items in the history when opening the 3rd item. \
+// 2nd item should be the first in the history, as the last opened."
+// );
+
+// let history_after_third =
+// open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
+// assert_eq!(
+// history_after_third,
+// vec![
+// FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/third.rs")),
+// },
+// Some(PathBuf::from("/src/test/third.rs"))
+// ),
+// FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/second.rs")),
+// },
+// Some(PathBuf::from("/src/test/second.rs"))
+// ),
+// FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/first.rs")),
+// },
+// Some(PathBuf::from("/src/test/first.rs"))
+// ),
+// ],
+// "Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
+// 3rd item should be the first in the history, as the last opened."
+// );
+
+// let history_after_second_again =
+// open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
+// assert_eq!(
+// history_after_second_again,
+// vec![
+// FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/second.rs")),
+// },
+// Some(PathBuf::from("/src/test/second.rs"))
+// ),
+// FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/third.rs")),
+// },
+// Some(PathBuf::from("/src/test/third.rs"))
+// ),
+// FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/first.rs")),
+// },
+// Some(PathBuf::from("/src/test/first.rs"))
+// ),
+// ],
+// "Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
+// 2nd item, as the last opened, 3rd item should go next as it was opened right before."
+// );
+// }
+
+// #[gpui::test]
+// async fn test_external_files_history(cx: &mut gpui::TestAppContext) {
+// let app_state = init_test(cx);
+
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/src",
+// json!({
+// "test": {
+// "first.rs": "// First Rust file",
+// "second.rs": "// Second Rust file",
+// }
+// }),
+// )
+// .await;
+
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/external-src",
+// json!({
+// "test": {
+// "third.rs": "// Third Rust file",
+// "fourth.rs": "// Fourth Rust file",
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+// cx.update(|cx| {
+// project.update(cx, |project, cx| {
+// project.find_or_create_local_worktree("/external-src", false, cx)
+// })
+// })
+// .detach();
+// cx.background_executor.run_until_parked();
+
+// let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+// let cx = &mut cx;
+// let worktree_id = cx.read(|cx| {
+// let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+// assert_eq!(worktrees.len(), 1,);
+
+// WorktreeId::from_usize(worktrees[0].id())
+// });
+// workspace
+// .update(cx, |workspace, cx| {
+// workspace.open_abs_path(PathBuf::from("/external-src/test/third.rs"), false, cx)
+// })
+// .detach();
+// cx.background_executor.run_until_parked();
+// let external_worktree_id = cx.read(|cx| {
+// let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+// assert_eq!(
+// worktrees.len(),
+// 2,
+// "External file should get opened in a new worktree"
+// );
+
+// WorktreeId::from_usize(
+// worktrees
+// .into_iter()
+// .find(|worktree| worktree.entity_id() != worktree_id.to_usize())
+// .expect("New worktree should have a different id")
+// .id(),
+// )
+// });
+// close_active_item(&workspace, cx).await;
+
+// let initial_history_items =
+// open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
+// assert_eq!(
+// initial_history_items,
+// vec![FoundPath::new(
+// ProjectPath {
+// worktree_id: external_worktree_id,
+// path: Arc::from(Path::new("")),
+// },
+// Some(PathBuf::from("/external-src/test/third.rs"))
+// )],
+// "Should show external file with its full path in the history after it was open"
+// );
+
+// let updated_history_items =
+// open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
+// assert_eq!(
+// updated_history_items,
+// vec![
+// FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/second.rs")),
+// },
+// Some(PathBuf::from("/src/test/second.rs"))
+// ),
+// FoundPath::new(
+// ProjectPath {
+// worktree_id: external_worktree_id,
+// path: Arc::from(Path::new("")),
+// },
+// Some(PathBuf::from("/external-src/test/third.rs"))
+// ),
+// ],
+// "Should keep external file with history updates",
+// );
+// }
+
+// #[gpui::test]
+// async fn test_toggle_panel_new_selections(cx: &mut gpui::TestAppContext) {
+// let app_state = init_test(cx);
+
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/src",
+// json!({
+// "test": {
+// "first.rs": "// First Rust file",
+// "second.rs": "// Second Rust file",
+// "third.rs": "// Third Rust file",
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+// let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+// let cx = &mut cx;
+
+// // generate some history to select from
+// open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
+// cx.executor().run_until_parked();
+// open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
+// open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
+// let current_history = open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
+
+// for expected_selected_index in 0..current_history.len() {
+// cx.dispatch_action(Toggle);
+// let selected_index = workspace.update(cx, |workspace, cx| {
+// workspace
+// .current_modal::<FileFinder>(cx)
+// .unwrap()
+// .read(cx)
+// .picker
+// .read(cx)
+// .delegate
+// .selected_index()
+// });
+// assert_eq!(
+// selected_index, expected_selected_index,
+// "Should select the next item in the history"
+// );
+// }
+
+// cx.dispatch_action(Toggle);
+// let selected_index = workspace.update(cx, |workspace, cx| {
+// workspace
+// .current_modal::<FileFinder>(cx)
+// .unwrap()
+// .read(cx)
+// .picker
+// .read(cx)
+// .delegate
+// .selected_index()
+// });
+// assert_eq!(
+// selected_index, 0,
+// "Should wrap around the history and start all over"
+// );
+// }
+
+// #[gpui::test]
+// async fn test_search_preserves_history_items(cx: &mut gpui::TestAppContext) {
+// let app_state = init_test(cx);
+
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/src",
+// json!({
+// "test": {
+// "first.rs": "// First Rust file",
+// "second.rs": "// Second Rust file",
+// "third.rs": "// Third Rust file",
+// "fourth.rs": "// Fourth Rust file",
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+// let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+// let cx = &mut cx;
+// let worktree_id = cx.read(|cx| {
+// let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
+// assert_eq!(worktrees.len(), 1,);
+
+// WorktreeId::from_usize(worktrees[0].entity_id())
+// });
+
+// // generate some history to select from
+// open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
+// open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
+// open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
+// open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
+
+// cx.dispatch_action(Toggle);
+// let first_query = "f";
+// let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+// finder
+// .update(cx, |finder, cx| {
+// finder.delegate.update_matches(first_query.to_string(), cx)
+// })
+// .await;
+// finder.read_with(cx, |finder, _| {
+// let delegate = &finder.delegate;
+// assert_eq!(delegate.matches.history.len(), 1, "Only one history item contains {first_query}, it should be present and others should be filtered out");
+// let history_match = delegate.matches.history.first().unwrap();
+// assert!(history_match.1.is_some(), "Should have path matches for history items after querying");
+// assert_eq!(history_match.0, FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/first.rs")),
+// },
+// Some(PathBuf::from("/src/test/first.rs"))
+// ));
+// assert_eq!(delegate.matches.search.len(), 1, "Only one non-history item contains {first_query}, it should be present");
+// assert_eq!(delegate.matches.search.first().unwrap().path.as_ref(), Path::new("test/fourth.rs"));
+// });
+
+// let second_query = "fsdasdsa";
+// let finder = workspace.update(cx, |workspace, cx| {
+// workspace
+// .current_modal::<FileFinder>(cx)
+// .unwrap()
+// .read(cx)
+// .picker
+// });
+// finder
+// .update(cx, |finder, cx| {
+// finder.delegate.update_matches(second_query.to_string(), cx)
+// })
+// .await;
+// finder.update(cx, |finder, _| {
+// let delegate = &finder.delegate;
+// assert!(
+// delegate.matches.history.is_empty(),
+// "No history entries should match {second_query}"
+// );
+// assert!(
+// delegate.matches.search.is_empty(),
+// "No search entries should match {second_query}"
+// );
+// });
+
+// let first_query_again = first_query;
+
+// let finder = workspace.update(cx, |workspace, cx| {
+// workspace
+// .current_modal::<FileFinder>(cx)
+// .unwrap()
+// .read(cx)
+// .picker
+// });
+// finder
+// .update(cx, |finder, cx| {
+// finder
+// .delegate
+// .update_matches(first_query_again.to_string(), cx)
+// })
+// .await;
+// finder.read_with(cx, |finder, _| {
+// let delegate = &finder.delegate;
+// assert_eq!(delegate.matches.history.len(), 1, "Only one history item contains {first_query_again}, it should be present and others should be filtered out, even after non-matching query");
+// let history_match = delegate.matches.history.first().unwrap();
+// assert!(history_match.1.is_some(), "Should have path matches for history items after querying");
+// assert_eq!(history_match.0, FoundPath::new(
+// ProjectPath {
+// worktree_id,
+// path: Arc::from(Path::new("test/first.rs")),
+// },
+// Some(PathBuf::from("/src/test/first.rs"))
+// ));
+// assert_eq!(delegate.matches.search.len(), 1, "Only one non-history item contains {first_query_again}, it should be present, even after non-matching query");
+// assert_eq!(delegate.matches.search.first().unwrap().path.as_ref(), Path::new("test/fourth.rs"));
+// });
+// }
+
+// #[gpui::test]
+// async fn test_history_items_vs_very_good_external_match(cx: &mut gpui::TestAppContext) {
+// let app_state = init_test(cx);
+
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/src",
+// json!({
+// "collab_ui": {
+// "first.rs": "// First Rust file",
+// "second.rs": "// Second Rust file",
+// "third.rs": "// Third Rust file",
+// "collab_ui.rs": "// Fourth Rust file",
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+// let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+// let cx = &mut cx;
+// // generate some history to select from
+// open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
+// open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
+// open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
+// open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
+
+// cx.dispatch_action(Toggle);
+// let query = "collab_ui";
+// let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
+// finder
+// .update(cx, |finder, cx| {
+// finder.delegate.update_matches(query.to_string(), cx)
+// })
+// .await;
+// finder.read_with(cx, |finder, _| {
+// let delegate = &finder.delegate;
+// assert!(
+// delegate.matches.history.is_empty(),
+// "History items should not math query {query}, they should be matched by name only"
+// );
+
+// let search_entries = delegate
+// .matches
+// .search
+// .iter()
+// .map(|path_match| path_match.path.to_path_buf())
+// .collect::<Vec<_>>();
+// assert_eq!(
+// search_entries,
+// vec![
+// PathBuf::from("collab_ui/collab_ui.rs"),
+// PathBuf::from("collab_ui/third.rs"),
+// PathBuf::from("collab_ui/first.rs"),
+// PathBuf::from("collab_ui/second.rs"),
+// ],
+// "Despite all search results having the same directory name, the most matching one should be on top"
+// );
+// });
+// }
+
+// #[gpui::test]
+// async fn test_nonexistent_history_items_not_shown(cx: &mut gpui::TestAppContext) {
+// let app_state = init_test(cx);
+
+// app_state
+// .fs
+// .as_fake()
+// .insert_tree(
+// "/src",
+// json!({
+// "test": {
+// "first.rs": "// First Rust file",
+// "nonexistent.rs": "// Second Rust file",
+// "third.rs": "// Third Rust file",
+// }
+// }),
+// )
+// .await;
+
+// let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
+// let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+// let cx = &mut cx;
+// // generate some history to select from
+// open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
+// open_close_queried_buffer("non", 1, "nonexistent.rs", &workspace, cx).await;
+// open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
+// open_close_queried_buffer("fir", 1, "first.rs", &workspace, cx).await;
+
+// cx.dispatch_action(Toggle);
+// let query = "rs";
+// let finder = cx.read(|cx| workspace.read(cx).current_modal::<FileFinder>().unwrap());
+// finder
+// .update(cx, |finder, cx| {
+// finder.picker.update(cx, |picker, cx| {
+// picker.delegate.update_matches(query.to_string(), cx)
+// })
+// })
+// .await;
+// finder.update(cx, |finder, _| {
+// let history_entries = finder.delegate
+// .matches
+// .history
+// .iter()
+// .map(|(_, path_match)| path_match.as_ref().expect("should have a path match").path.to_path_buf())
+// .collect::<Vec<_>>();
+// assert_eq!(
+// history_entries,
+// vec![
+// PathBuf::from("test/first.rs"),
+// PathBuf::from("test/third.rs"),
+// ],
+// "Should have all opened files in the history, except the ones that do not exist on disk"
+// );
+// });
+// }
+
+// async fn open_close_queried_buffer(
+// input: &str,
+// expected_matches: usize,
+// expected_editor_title: &str,
+// workspace: &View<Workspace>,
+// cx: &mut gpui::VisualTestContext<'_>,
+// ) -> Vec<FoundPath> {
+// cx.dispatch_action(Toggle);
+// let picker = workspace.update(cx, |workspace, cx| {
+// workspace
+// .current_modal::<FileFinder>(cx)
+// .unwrap()
+// .read(cx)
+// .picker
+// .clone()
+// });
+// picker
+// .update(cx, |finder, cx| {
+// finder.delegate.update_matches(input.to_string(), cx)
+// })
+// .await;
+// let history_items = picker.update(cx, |finder, _| {
+// assert_eq!(
+// finder.delegate.matches.len(),
+// expected_matches,
+// "Unexpected number of matches found for query {input}"
+// );
+// finder.delegate.history_items.clone()
+// });
+
+// let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+// cx.dispatch_action(SelectNext);
+// cx.dispatch_action(Confirm);
+// cx.background_executor.run_until_parked();
+// active_pane
+// .condition(cx, |pane, _| pane.active_item().is_some())
+// .await;
+// cx.read(|cx| {
+// let active_item = active_pane.read(cx).active_item().unwrap();
+// let active_editor_title = active_item
+// .to_any()
+// .downcast::<Editor>()
+// .unwrap()
+// .read(cx)
+// .title(cx);
+// assert_eq!(
+// expected_editor_title, active_editor_title,
+// "Unexpected editor title for query {input}"
+// );
+// });
+
+// close_active_item(workspace, cx).await;
+
+// history_items
+// }
+
+// async fn close_active_item(workspace: &View<Workspace>, cx: &mut VisualTestContext<'_>) {
+// let mut original_items = HashMap::new();
+// cx.read(|cx| {
+// for pane in workspace.read(cx).panes() {
+// let pane_id = pane.entity_id();
+// let pane = pane.read(cx);
+// let insertion_result = original_items.insert(pane_id, pane.items().count());
+// assert!(insertion_result.is_none(), "Pane id {pane_id} collision");
+// }
+// });
+
+// let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
+// active_pane
+// .update(cx, |pane, cx| {
+// pane.close_active_item(&workspace::CloseActiveItem { save_intent: None }, cx)
+// .unwrap()
+// })
+// .await
+// .unwrap();
+// cx.background_executor.run_until_parked();
+// cx.read(|cx| {
+// for pane in workspace.read(cx).panes() {
+// let pane_id = pane.entity_id();
+// let pane = pane.read(cx);
+// match original_items.remove(&pane_id) {
+// Some(original_items) => {
+// assert_eq!(
+// pane.items().count(),
+// original_items.saturating_sub(1),
+// "Pane id {pane_id} should have item closed"
+// );
+// }
+// None => panic!("Pane id {pane_id} not found in original items"),
+// }
+// }
+// });
+// assert!(
+// original_items.len() <= 1,
+// "At most one panel should got closed"
+// );
+// }
+
+// fn init_test(cx: &mut TestAppContext) -> Arc<AppState> {
+// cx.update(|cx| {
+// let state = AppState::test(cx);
+// theme::init(cx);
+// language::init(cx);
+// super::init(cx);
+// editor::init(cx);
+// workspace::init_settings(cx);
+// Project::init_settings(cx);
+// state
+// })
+// }
+
+// fn test_path_like(test_str: &str) -> PathLikeWithPosition<FileSearchQuery> {
+// PathLikeWithPosition::parse_str(test_str, |path_like_str| {
+// Ok::<_, std::convert::Infallible>(FileSearchQuery {
+// raw_query: test_str.to_owned(),
+// file_query_end: if path_like_str == test_str {
+// None
+// } else {
+// Some(path_like_str.len())
+// },
+// })
+// })
+// .unwrap()
+// }
+
+// fn dummy_found_path(project_path: ProjectPath) -> FoundPath {
+// FoundPath {
+// project: project_path,
+// absolute: None,
+// }
+// }
+
+// fn build_find_picker(
+// project: Model<Project>,
+// cx: &mut TestAppContext,
+// ) -> (
+// View<Picker<FileFinderDelegate>>,
+// View<Workspace>,
+// VisualTestContext,
+// ) {
+// let (workspace, mut cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx));
+// cx.dispatch_action(Toggle);
+// let picker = workspace.update(&mut cx, |workspace, cx| {
+// workspace
+// .current_modal::<FileFinder>(cx)
+// .unwrap()
+// .read(cx)
+// .picker
+// .clone()
+// });
+// (picker, workspace, cx)
+// }
+// }