From 77cbb532f2a3e052d274f6aaa2e371f8d8a9dd69 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 20 Sep 2026 15:31:38 +0200 Subject: [PATCH] Add a test for the selection after a selected rename splits in two When a rename is selected in the files panel and then splits into its two halves, e.g. because it was unstaged, the selection is meant to move to the new half. This only works with gui.showRootItemInFileTree turned off. With the default setting, the selection lands on the file that follows the rename in the list instead. Co-Authored-By: Claude Fable 5.1 --- pkg/gui/filetree/file_tree_view_model_test.go | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/pkg/gui/filetree/file_tree_view_model_test.go b/pkg/gui/filetree/file_tree_view_model_test.go index c14c91ea8..9777a2e31 100644 --- a/pkg/gui/filetree/file_tree_view_model_test.go +++ b/pkg/gui/filetree/file_tree_view_model_test.go @@ -5,6 +5,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/common" + "github.com/jesseduffield/lazygit/pkg/config" "github.com/stretchr/testify/assert" ) @@ -30,3 +31,53 @@ func TestSetStatusFilterPreservingSelection(t *testing.T) { assert.Equal(t, "file3", viewModel.GetSelectedPath()) assert.False(t, viewModel.IsSelectingRange()) } + +func TestSetTreeSelectsNewFileWhenSelectedRenameSplits(t *testing.T) { + scenarios := []struct { + name string + showRootItem bool + expectedPath string + }{ + { + name: "with root item", + showRootItem: true, + /* EXPECTED: + expectedPath: "dir/new.go", + ACTUAL: */ + expectedPath: "other.go", + }, + { + name: "without root item", + showRootItem: false, + expectedPath: "dir/new.go", + }, + } + + for _, s := range scenarios { + t.Run(s.name, func(t *testing.T) { + userConfig := config.GetDefaultConfig() + userConfig.Gui.ShowRootItemInFileTree = s.showRootItem + cmn := common.NewDummyCommonWithUserConfigAndAppState(userConfig, nil) + + files := []*models.File{ + {Path: "dir/new.go", PreviousPath: "dir/old.go"}, + {Path: "other.go"}, + } + viewModel := NewFileTreeViewModel(func() []*models.File { return files }, cmn, true) + viewModel.SetTree() + idx, found := viewModel.GetIndexForPath(InternalTreePathForFilePath("dir/new.go", s.showRootItem)) + assert.True(t, found) + viewModel.SetSelection(idx) + + // the rename is split into its two halves, e.g. because it was unstaged + files = []*models.File{ + {Path: "dir/new.go"}, + {Path: "dir/old.go"}, + {Path: "other.go"}, + } + viewModel.SetTree() + + assert.Equal(t, s.expectedPath, viewModel.GetSelectedPath()) + }) + } +}