jesseduffield.lazygit/pkg/integration/tests/ui/range_select.go
2026-09-06 17:32:48 +02:00

214 lines
5.9 KiB
Go

package ui
import (
"fmt"
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
// Here's the state machine we need to verify:
// (no range, press 'v') -> sticky range
// (no range, press arrow) -> no range
// (no range, press shift+arrow) -> nonsticky range
// (sticky range, press 'v') -> no range
// (sticky range, press 'escape') -> no range
// (sticky range, press arrow) -> sticky range
// (sticky range, press `<`/`>` or `,`/`.`) -> sticky range
// (sticky range, press shift+arrow) -> nonsticky range
// (nonsticky range, press 'v') -> no range
// (nonsticky range, press 'escape') -> no range
// (nonsticky range, press arrow) -> no range
// (nonsticky range, press shift+arrow) -> nonsticky range
// Importantly, if you press 'v' when in a nonsticky range, it clears the range,
// so no matter which mode you're in, 'v' will cancel the range.
// And, if you press shift+up/down when in a sticky range, it switches to a non-
// sticky range, meaning if you then press up/down without shift, it clears
// the range.
var RangeSelect = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Verify range select works as expected in list views",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().Gui.UseHunkModeInDiffView = false
config.GetUserConfig().Gui.ExpandFocusedSidePanel = true
},
SetupRepo: func(shell *Shell) {
// We're testing the commits view as our representative list context, with 10
// items starting from "line 1" and ending at "line 10".
fileContent := "staged\n"
total := 10
for i := 1; i <= total; i++ {
remaining := total - i + 1
// Commits are displayed in reverse order so to we need to create them in reverse to have them appear as 'line 1', 'line 2' etc.
shell.EmptyCommit(fmt.Sprintf("line %d", remaining))
fileContent = fmt.Sprintf("%sline %d\n", fileContent, i)
}
shell.CreateFileAndAdd("file1", "staged\n")
shell.UpdateFile("file1", fileContent)
shell.NewBranch("branch1").NewBranch("branch2")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
assertRangeSelectBehaviour := func(v *ViewDriver, focusOtherView func(), lineIdxOfFirstItem int) {
v.
SelectedLines(
Contains("line 1"),
).
// (no range, press 'v') -> sticky range
Press(keys.Universal.ToggleRangeSelect).
SelectedLines(
Contains("line 1"),
).
// (sticky range, press arrow) -> sticky range
SelectNextItem().
SelectedLines(
Contains("line 1"),
Contains("line 2"),
).
// (sticky range, press 'v') -> no range
Press(keys.Universal.ToggleRangeSelect).
SelectedLines(
Contains("line 2"),
).
// (no range, press arrow) -> no range
SelectPreviousItem().
SelectedLines(
Contains("line 1"),
).
// (no range, press shift+arrow) -> nonsticky range
Press(keys.Universal.RangeSelectDown).
SelectedLines(
Contains("line 1"),
Contains("line 2"),
).
// (nonsticky range, press shift+arrow) -> nonsticky range
Press(keys.Universal.RangeSelectDown).
SelectedLines(
Contains("line 1"),
Contains("line 2"),
Contains("line 3"),
).
Press(keys.Universal.RangeSelectUp).
SelectedLines(
Contains("line 1"),
Contains("line 2"),
).
// (nonsticky range, press arrow) -> no range
SelectNextItem().
SelectedLines(
Contains("line 3"),
).
Press(keys.Universal.ToggleRangeSelect).
SelectedLines(
Contains("line 3"),
).
SelectNextItem().
SelectedLines(
Contains("line 3"),
Contains("line 4"),
).
// (sticky range, press shift+arrow) -> nonsticky range
Press(keys.Universal.RangeSelectDown).
SelectedLines(
Contains("line 3"),
Contains("line 4"),
Contains("line 5"),
).
SelectNextItem().
SelectedLines(
Contains("line 6"),
).
Press(keys.Universal.RangeSelectDown).
SelectedLines(
Contains("line 6"),
Contains("line 7"),
).
// (nonsticky range, press 'v') -> no range
Press(keys.Universal.ToggleRangeSelect).
SelectedLines(
Contains("line 7"),
).
Press(keys.Universal.RangeSelectDown).
SelectedLines(
Contains("line 7"),
Contains("line 8"),
).
// (nonsticky range, press 'escape') -> no range
PressEscape().
SelectedLines(
Contains("line 8"),
).
// (sticky range, press '>') -> sticky range
Press(keys.Universal.ToggleRangeSelect).
Press(keys.Universal.GotoBottom).
SelectedLines(
Contains("line 8"),
Contains("line 9"),
Contains("line 10"),
).
// (sticky range, press 'escape') -> no range
PressEscape().
SelectedLines(
Contains("line 10"),
)
// Click in view, press shift+arrow -> nonsticky range
focusOtherView()
v.Click(1, lineIdxOfFirstItem).
SelectedLines(
Contains("line 1"),
).
Press(keys.Universal.RangeSelectDown).
SelectedLines(
Contains("line 1"),
Contains("line 2"),
)
}
assertRangeSelectBehaviour(t.Views().Commits().Focus(), func() { t.Views().Branches().Focus() }, 0)
t.Views().Branches().Focus()
t.Views().Branches().
SelectedLines(
Contains("branch2"),
)
t.Views().Commits().
ClickAndHold(1, 3).
MouseMoveToView(t.Views().Branches(), 1, 2).
SelectedLines(
Contains("line 1"),
Contains("line 2"),
Contains("line 3"),
Contains("line 4"),
).
Tap(func() {
t.Views().Branches().SelectedLines(
Contains("branch2"),
)
}).
MouseRelease()
t.Views().Branches().Focus()
t.Views().Commits().
ClickAndHold(1, 0).
SelectedLines(
Contains("line 1"),
).
RepeatMouseMove().
SelectedLines(
Contains("line 1"),
).
MouseMove(1, 3).
SelectedLines(
Contains("line 1"),
Contains("line 2"),
Contains("line 3"),
Contains("line 4"),
).
MouseRelease().
Click(1, 0)
},
})