Add tests for the scroll-into-view regressions we fixed by hand

Since scrolling the selection into view became opt-in, five places have
had to be fixed by hand after the fact, none of them with a test. Cover
them now: making the scrolling automatic has to keep all five working,
and once it does, the hand-added scroll calls can go.

Two of them assert that the selection is visible rather than on an exact
scroll position, because the panel they look at changes height along the
way (filtering mode switches to half screen), or because what matters is
only that the commit we jumped to can be seen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller 2026-08-08 15:52:43 +02:00
parent a85d6e0349
commit 29d05e23f9
7 changed files with 225 additions and 0 deletions

View file

@ -366,6 +366,20 @@ func (self *ViewDriver) OriginY(expected int) *ViewDriver {
return self
}
// asserts that the selected line is inside the visible area of the view
func (self *ViewDriver) SelectedLineIsVisible() *ViewDriver {
self.t.assertWithRetries(func() (bool, string) {
view := self.getView()
firstVisible, lastVisible := view.OriginY(), view.OriginY()+view.InnerHeight()-1
actual := view.SelectedLineIdx()
return actual >= firstVisible && actual <= lastVisible,
fmt.Sprintf("%s: Expected the selected line (%d) to be visible, but only lines %d to %d are",
self.context, actual, firstVisible, lastVisible)
})
return self
}
func (self *ViewDriver) OriginYAtLeast(expected int) *ViewDriver {
self.t.assertEventually(func() (bool, string) {
var actual int

View file

@ -502,10 +502,14 @@ var tests = []*components.IntegrationTest{
ui.DisableSwitchTabWithPanelJumpKeys,
ui.DragBeyondViewport,
ui.EmptyMenu,
ui.FilteringScrollsSelectionIntoView,
ui.FindBaseCommitForFixupScrollsIntoView,
ui.HideSidePanel,
ui.KeybindingSuggestionsDontCrashOnDisabledBindings,
ui.KeybindingSuggestionsWhenSwitchingRepos,
ui.MenuScrollPositionIsReset,
ui.ModeSpecificKeybindingSuggestions,
ui.MoveCommitScrollsSelectionIntoView,
ui.OpenLinkFailure,
ui.PageUpAndDown,
ui.PromoteTabToSidePanel,
@ -513,6 +517,7 @@ var tests = []*components.IntegrationTest{
ui.RangeSelectWithAutoscroll,
ui.ReloadSidePanels,
ui.ReorderSidePanels,
ui.SubCommitsScrollPositionIsReset,
ui.SwitchTabFromMenu,
ui.SwitchTabWithPanelJumpKeys,
undo.UndoCheckoutAndDrop,

View file

@ -0,0 +1,62 @@
package ui
import (
"fmt"
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var FilteringScrollsSelectionIntoView = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Entering and leaving filtering mode scrolls the selected commit into view",
ExtraCmdArgs: []string{},
Skip: false,
Width: 120,
Height: 30,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
for i := range 40 {
file := "otherFile"
if i%2 == 0 {
file = "filterFile"
}
shell.UpdateFileAndAdd(file, fmt.Sprintf("content %02d", i))
shell.Commit(fmt.Sprintf("commit %02d", i))
}
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Press(keys.Universal.GotoBottom).
SelectedLine(Contains("commit 00")).
OriginYAtLeast(1).
Press(keys.Universal.FilteringMenu)
t.ExpectPopup().Menu().
Title(Equals("Filtering")).
Select(Contains("Enter path to filter by")).
Confirm()
t.ExpectPopup().Prompt().
Title(Equals("Enter path:")).
Type("filterFile").
Confirm()
// The filtered list has nothing to do with the one that was showing, so
// its scroll position doesn't either: we start at the top again
t.Views().Commits().
IsFocused().
SelectedLine(Contains("commit 38")).
SelectedLineIdx(0).
OriginY(0).
Press(keys.Universal.GotoBottom).
SelectedLine(Contains("commit 00")).
PressEscape()
// Leaving filtering mode keeps the commit selected, at its position in
// the full list, which needs scrolling to again
t.Views().Commits().
IsFocused().
SelectedLine(Contains("commit 00")).
SelectedLineIsVisible()
},
})

View file

@ -0,0 +1,35 @@
package ui
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var FindBaseCommitForFixupScrollsIntoView = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Finding the base commit for a fixup scrolls it into view",
ExtraCmdArgs: []string{},
Skip: false,
Width: 120,
Height: 30,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.NewBranch("mybranch").
EmptyCommit("1st commit").
CreateFileAndAdd("file1", "line 1\nline 2\nline 3\n").
Commit("base commit").
CreateNCommits(40).
UpdateFile("file1", "line 1\nline 2 changed\nline 3\n")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Files().
Focus().
Press(keys.Files.FindBaseCommitForFixup)
// The base commit is at the very bottom of the list, far below the
// visible area
t.Views().Commits().
IsFocused().
SelectedLine(Contains("base commit")).
SelectedLineIsVisible()
},
})

View file

@ -0,0 +1,39 @@
package ui
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var MenuScrollPositionIsReset = NewIntegrationTest(NewIntegrationTestArgs{
Description: "A menu that is opened after a scrolled down one starts at the top again",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateFile("myfile", "myfile")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Files().
IsFocused().
Press(keys.Universal.OptionMenu)
t.Views().Menu().
IsFocused().
// The first line is a section header, so the first item is at index 1
SelectedLineIdx(1).
OriginY(0).
Press(keys.Universal.GotoBottom).
OriginYAtLeast(1).
PressEscape()
t.Views().Files().
IsFocused().
Press(keys.Universal.OptionMenu)
t.Views().Menu().
IsFocused().
SelectedLineIdx(1).
OriginY(0)
},
})

View file

@ -0,0 +1,31 @@
package ui
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var MoveCommitScrollsSelectionIntoView = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Moving a commit down scrolls it into view if it isn't visible",
ExtraCmdArgs: []string{},
Skip: false,
Width: 120,
Height: 30,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateNCommits(40)
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
SelectedLine(Contains("commit-40")).
// Scroll the selected commit out of view with the mouse wheel
ScrollWheelDown().
ScrollWheelDown().
OriginY(4).
Press(keys.Commits.MoveDownCommit).
SelectedLine(Contains("commit-40")).
SelectedLineIdx(1).
SelectedLineIsVisible()
},
})

View file

@ -0,0 +1,39 @@
package ui
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var SubCommitsScrollPositionIsReset = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Viewing the commits of a branch again after scrolling down starts at the top again",
ExtraCmdArgs: []string{},
Skip: false,
Width: 120,
Height: 30,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.CreateNCommits(40)
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Branches().
Focus().
PressEnter()
t.Views().SubCommits().
IsFocused().
OriginY(0).
Press(keys.Universal.GotoBottom).
OriginYAtLeast(1).
PressEscape()
t.Views().Branches().
IsFocused().
PressEnter()
t.Views().SubCommits().
IsFocused().
SelectedLineIdx(0).
OriginY(0)
},
})