382 lines · 12.9 KB · Rust
RawDownload
use super::*;use editor::Editor;use gpui::{TestAppContext, VisualTestContext};use menu::SelectPrevious;use project::{Project, ProjectPath};use serde_json::json;use std::path::Path;use util::path;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_open_with_prev_tab_selected_and_cycle_on_toggle_action(    cx: &mut gpui::TestAppContext,) {    let app_state = init_test(cx);     app_state        .fs        .as_fake()        .insert_tree(            path!("/root"),            json!({                "1.txt": "First file",                "2.txt": "Second file",                "3.txt": "Third file",                "4.txt": "Fourth file",            }),        )        .await;     let project = Project::test(app_state.fs.clone(), [path!("/root").as_ref()], cx).await;    let (workspace, cx) =        cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));     let tab_1 = open_buffer("1.txt", &workspace, cx).await;    let tab_2 = open_buffer("2.txt", &workspace, cx).await;    let tab_3 = open_buffer("3.txt", &workspace, cx).await;    let tab_4 = open_buffer("4.txt", &workspace, cx).await;     // Starts with the previously opened item selected    let tab_switcher = open_tab_switcher(false, &workspace, cx);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 4);        assert_match_at_position(tab_switcher, 0, tab_4.boxed_clone());        assert_match_selection(tab_switcher, 1, tab_3.boxed_clone());        assert_match_at_position(tab_switcher, 2, tab_2.boxed_clone());        assert_match_at_position(tab_switcher, 3, tab_1.boxed_clone());    });     cx.dispatch_action(Toggle { select_last: false });    cx.dispatch_action(Toggle { select_last: false });    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 4);        assert_match_at_position(tab_switcher, 0, tab_4.boxed_clone());        assert_match_at_position(tab_switcher, 1, tab_3.boxed_clone());        assert_match_at_position(tab_switcher, 2, tab_2.boxed_clone());        assert_match_selection(tab_switcher, 3, tab_1.boxed_clone());    });     cx.dispatch_action(SelectPrevious);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 4);        assert_match_at_position(tab_switcher, 0, tab_4.boxed_clone());        assert_match_at_position(tab_switcher, 1, tab_3.boxed_clone());        assert_match_selection(tab_switcher, 2, tab_2.boxed_clone());        assert_match_at_position(tab_switcher, 3, tab_1.boxed_clone());    });} #[gpui::test]async fn test_open_with_last_tab_selected(cx: &mut gpui::TestAppContext) {    let app_state = init_test(cx);     app_state        .fs        .as_fake()        .insert_tree(            path!("/root"),            json!({                "1.txt": "First file",                "2.txt": "Second file",                "3.txt": "Third file",            }),        )        .await;     let project = Project::test(app_state.fs.clone(), [path!("/root").as_ref()], cx).await;    let (workspace, cx) =        cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));     let tab_1 = open_buffer("1.txt", &workspace, cx).await;    let tab_2 = open_buffer("2.txt", &workspace, cx).await;    let tab_3 = open_buffer("3.txt", &workspace, cx).await;     // Starts with the last item selected    let tab_switcher = open_tab_switcher(true, &workspace, cx);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 3);        assert_match_at_position(tab_switcher, 0, tab_3);        assert_match_at_position(tab_switcher, 1, tab_2);        assert_match_selection(tab_switcher, 2, tab_1);    });} #[gpui::test]async fn test_open_item_on_modifiers_release(cx: &mut gpui::TestAppContext) {    let app_state = init_test(cx);     app_state        .fs        .as_fake()        .insert_tree(            path!("/root"),            json!({                "1.txt": "First file",                "2.txt": "Second file",            }),        )        .await;     let project = Project::test(app_state.fs.clone(), [path!("/root").as_ref()], cx).await;    let (workspace, cx) =        cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));     let tab_1 = open_buffer("1.txt", &workspace, cx).await;    let tab_2 = open_buffer("2.txt", &workspace, cx).await;     cx.simulate_modifiers_change(Modifiers::control());    let tab_switcher = open_tab_switcher(false, &workspace, cx);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 2);        assert_match_at_position(tab_switcher, 0, tab_2.boxed_clone());        assert_match_selection(tab_switcher, 1, tab_1.boxed_clone());    });     cx.simulate_modifiers_change(Modifiers::none());    cx.read(|cx| {        let active_editor = workspace.read(cx).active_item_as::<Editor>(cx).unwrap();        assert_eq!(active_editor.read(cx).title(cx), "1.txt");    });    assert_tab_switcher_is_closed(workspace, cx);} #[gpui::test]async fn test_open_on_empty_pane(cx: &mut gpui::TestAppContext) {    let app_state = init_test(cx);    app_state.fs.as_fake().insert_tree("/root", json!({})).await;     let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;    let (workspace, cx) =        cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));     cx.simulate_modifiers_change(Modifiers::control());    let tab_switcher = open_tab_switcher(false, &workspace, cx);    tab_switcher.update(cx, |tab_switcher, _| {        assert!(tab_switcher.delegate.matches.is_empty());    });     cx.simulate_modifiers_change(Modifiers::none());    assert_tab_switcher_is_closed(workspace, cx);} #[gpui::test]async fn test_open_with_single_item(cx: &mut gpui::TestAppContext) {    let app_state = init_test(cx);    app_state        .fs        .as_fake()        .insert_tree(path!("/root"), json!({"1.txt": "Single file"}))        .await;     let project = Project::test(app_state.fs.clone(), [path!("/root").as_ref()], cx).await;    let (workspace, cx) =        cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));     let tab = open_buffer("1.txt", &workspace, cx).await;     let tab_switcher = open_tab_switcher(false, &workspace, cx);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 1);        assert_match_selection(tab_switcher, 0, tab);    });} #[gpui::test]async fn test_close_selected_item(cx: &mut gpui::TestAppContext) {    let app_state = init_test(cx);    app_state        .fs        .as_fake()        .insert_tree(            path!("/root"),            json!({                "1.txt": "First file",                "2.txt": "Second file",            }),        )        .await;     let project = Project::test(app_state.fs.clone(), [path!("/root").as_ref()], cx).await;    let (workspace, cx) =        cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));     let tab_1 = open_buffer("1.txt", &workspace, cx).await;    let tab_2 = open_buffer("2.txt", &workspace, cx).await;     cx.simulate_modifiers_change(Modifiers::control());    let tab_switcher = open_tab_switcher(false, &workspace, cx);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 2);        assert_match_at_position(tab_switcher, 0, tab_2.boxed_clone());        assert_match_selection(tab_switcher, 1, tab_1.boxed_clone());    });     cx.simulate_modifiers_change(Modifiers::control());    cx.dispatch_action(CloseSelectedItem);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 1);        assert_match_selection(tab_switcher, 0, tab_2);    });     // Still switches tab on modifiers release    cx.simulate_modifiers_change(Modifiers::none());    cx.read(|cx| {        let active_editor = workspace.read(cx).active_item_as::<Editor>(cx).unwrap();        assert_eq!(active_editor.read(cx).title(cx), "2.txt");    });    assert_tab_switcher_is_closed(workspace, cx);} #[gpui::test]async fn test_close_preserves_selected_position(cx: &mut gpui::TestAppContext) {    let app_state = init_test(cx);    app_state        .fs        .as_fake()        .insert_tree(            path!("/root"),            json!({                "1.txt": "First file",                "2.txt": "Second file",                "3.txt": "Third file",            }),        )        .await;     let project = Project::test(app_state.fs.clone(), [path!("/root").as_ref()], cx).await;    let (workspace, cx) =        cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));     let tab_1 = open_buffer("1.txt", &workspace, cx).await;    let tab_2 = open_buffer("2.txt", &workspace, cx).await;    let tab_3 = open_buffer("3.txt", &workspace, cx).await;     let tab_switcher = open_tab_switcher(false, &workspace, cx);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 3);        assert_match_at_position(tab_switcher, 0, tab_3.boxed_clone());        assert_match_selection(tab_switcher, 1, tab_2.boxed_clone());        assert_match_at_position(tab_switcher, 2, tab_1.boxed_clone());    });     // Verify that if the selected tab was closed, tab at the same position is selected.    cx.dispatch_action(CloseSelectedItem);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 2);        assert_match_at_position(tab_switcher, 0, tab_3.boxed_clone());        assert_match_selection(tab_switcher, 1, tab_1.boxed_clone());    });     // But if the position is no longer valid, fall back to the position above.    cx.dispatch_action(CloseSelectedItem);    tab_switcher.update(cx, |tab_switcher, _| {        assert_eq!(tab_switcher.delegate.matches.len(), 1);        assert_match_selection(tab_switcher, 0, tab_3.boxed_clone());    });} fn init_test(cx: &mut TestAppContext) -> Arc<AppState> {    cx.update(|cx| {        let state = AppState::test(cx);        theme::init(theme::LoadThemes::JustBase, cx);        language::init(cx);        super::init(cx);        editor::init(cx);        workspace::init_settings(cx);        Project::init_settings(cx);        state    })} #[track_caller]fn open_tab_switcher(    select_last: bool,    workspace: &Entity<Workspace>,    cx: &mut VisualTestContext,) -> Entity<Picker<TabSwitcherDelegate>> {    cx.dispatch_action(Toggle { select_last });    get_active_tab_switcher(workspace, cx)} #[track_caller]fn get_active_tab_switcher(    workspace: &Entity<Workspace>,    cx: &mut VisualTestContext,) -> Entity<Picker<TabSwitcherDelegate>> {    workspace.update(cx, |workspace, cx| {        workspace            .active_modal::<TabSwitcher>(cx)            .expect("tab switcher is not open")            .read(cx)            .picker            .clone()    })} async fn open_buffer(    file_path: &str,    workspace: &Entity<Workspace>,    cx: &mut gpui::VisualTestContext,) -> Box<dyn ItemHandle> {    let project = workspace.update(cx, |workspace, _| workspace.project().clone());    let worktree_id = project.update(cx, |project, cx| {        let worktree = project.worktrees(cx).last().expect("worktree not found");        worktree.read(cx).id()    });    let project_path = ProjectPath {        worktree_id,        path: Arc::from(Path::new(file_path)),    };    workspace        .update_in(cx, move |workspace, window, cx| {            workspace.open_path(project_path, None, true, window, cx)        })        .await        .unwrap()} #[track_caller]fn assert_match_selection(    tab_switcher: &Picker<TabSwitcherDelegate>,    expected_selection_index: usize,    expected_item: Box<dyn ItemHandle>,) {    assert_eq!(        tab_switcher.delegate.selected_index(),        expected_selection_index,        "item is not selected"    );    assert_match_at_position(tab_switcher, expected_selection_index, expected_item);} #[track_caller]fn assert_match_at_position(    tab_switcher: &Picker<TabSwitcherDelegate>,    match_index: usize,    expected_item: Box<dyn ItemHandle>,) {    let match_item = tab_switcher        .delegate        .matches        .get(match_index)        .unwrap_or_else(|| panic!("Tab Switcher has no match for index {match_index}"));    assert_eq!(match_item.item.item_id(), expected_item.item_id());} #[track_caller]fn assert_tab_switcher_is_closed(workspace: Entity<Workspace>, cx: &mut VisualTestContext) {    workspace.update(cx, |workspace, cx| {        assert!(            workspace.active_modal::<TabSwitcher>(cx).is_none(),            "tab switcher is still open"        );    });}