diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 4d93761eaeab0e..188ea2e483a65d 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -1033,6 +1033,15 @@ "enter": "menu::Cancel", }, }, + { + "context": "GitGraph", + "bindings": { + "j": "vim::MenuSelectNext", + "k": "vim::MenuSelectPrevious", + "shift-g": "menu::SelectLast", + "g g": "menu::SelectFirst" + } + }, { "context": "GitPanel && ChangesList && !GitBranchSelector", "use_key_equivalents": true, diff --git a/crates/git_graph/src/git_graph.rs b/crates/git_graph/src/git_graph.rs index 6d3d99ee2a98aa..a69da25daa9018 100644 --- a/crates/git_graph/src/git_graph.rs +++ b/crates/git_graph/src/git_graph.rs @@ -5072,4 +5072,144 @@ mod tests { ); }); } + + #[gpui::test] + async fn test_git_graph_navigation(cx: &mut TestAppContext) { + init_test(cx); + + let fs = FakeFs::new(cx.executor()); + fs.insert_tree( + Path::new("/project"), + serde_json::json!({ + ".git": {}, + "file.txt": "content", + }), + ) + .await; + + let mut rng = StdRng::seed_from_u64(42); + let commits = generate_random_commit_dag(&mut rng, 10, false); + fs.set_graph_commits(Path::new("/project/.git"), commits); + + let project = Project::test(fs.clone(), [Path::new("/project")], cx).await; + cx.run_until_parked(); + + let repository = project.read_with(cx, |project, cx| { + project + .active_repository(cx) + .expect("should have a repository") + }); + + let (multi_workspace, cx) = cx.add_window_view(|window, cx| { + workspace::MultiWorkspace::test_new(project.clone(), window, cx) + }); + + let workspace_weak = + multi_workspace.read_with(&*cx, |multi, _| multi.workspace().downgrade()); + + let git_graph = cx.new_window_entity(|window, cx| { + GitGraph::new( + repository.read(cx).id, + project.read(cx).git_store().clone(), + workspace_weak, + None, + window, + cx, + ) + }); + cx.run_until_parked(); + + git_graph.update_in(cx, |graph, window, cx| { + graph.focus_handle(cx).focus(window, cx); + }); + cx.run_until_parked(); + + cx.draw( + point(px(0.), px(0.)), + gpui::size(px(1200.), px(800.)), + |_, _| git_graph.clone().into_any_element(), + ); + cx.run_until_parked(); + + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.graph_data.commits.len(), 10); + }); + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.selected_entry_idx, None); + }); + + git_graph.update_in(cx, |graph, window, cx| { + graph.select_first(&menu::SelectFirst, window, cx); + }); + cx.run_until_parked(); + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.selected_entry_idx, Some(0)); + }); + + git_graph.update_in(cx, |graph, window, cx| { + graph.select_next(&menu::SelectNext, window, cx); + }); + cx.run_until_parked(); + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.selected_entry_idx, Some(1)); + }); + + git_graph.update_in(cx, |graph, window, cx| { + graph.select_prev(&menu::SelectPrevious, window, cx); + }); + cx.run_until_parked(); + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.selected_entry_idx, Some(0)); + }); + + git_graph.update_in(cx, |graph, window, cx| { + graph.select_last(&menu::SelectLast, window, cx); + }); + cx.run_until_parked(); + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.selected_entry_idx, Some(9)); + }); + + git_graph.update_in(cx, |graph, window, cx| { + graph.select_next(&menu::SelectNext, window, cx); + }); + cx.run_until_parked(); + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.selected_entry_idx, Some(9)); + }); + + git_graph.update_in(cx, |graph, window, cx| { + graph.select_prev(&menu::SelectPrevious, window, cx); + }); + cx.run_until_parked(); + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.selected_entry_idx, Some(8)); + }); + + git_graph.update(cx, |graph, cx| { + graph.selected_entry_idx = None; + cx.notify(); + }); + cx.run_until_parked(); + git_graph.update_in(cx, |graph, window, cx| { + graph.select_prev(&menu::SelectPrevious, window, cx); + }); + cx.run_until_parked(); + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.selected_entry_idx, Some(0)); + }); + + git_graph.update(cx, |graph, cx| { + graph.selected_entry_idx = None; + cx.notify(); + }); + cx.run_until_parked(); + git_graph.update_in(cx, |graph, window, cx| { + graph.select_next(&menu::SelectNext, window, cx); + }); + cx.run_until_parked(); + git_graph.read_with(&*cx, |graph, _| { + assert_eq!(graph.selected_entry_idx, Some(0)); + }); + } }