mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-08-24 10:13:41 -05:00
Add a way for integration tests to press keys in rapid succession
The test driver waits for lazygit to become idle after every keypress, so tests could never exercise what happens when a key arrives while the previous key's processing is still in flight — for example while the refresh triggered by the previous key hasn't updated the model yet. Real users type faster than that all the time. PressRapidly injects all its keys back to back and waits for idle only once at the end, so the second and later keys are queued before the first one's processing has finished. The next commit uses this to demonstrate a bug in exactly that scenario. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
2e653ceeba
commit
7a902b56cc
+18
-8
@@ -25,17 +25,27 @@ type GuiDriver struct {
|
||||
var _ integrationTypes.GuiDriver = &GuiDriver{}
|
||||
|
||||
func (self *GuiDriver) PressKey(keyStr string) {
|
||||
self.PressKeysRapidly(keyStr)
|
||||
}
|
||||
|
||||
// PressKeysRapidly presses the given keys in immediate succession, waiting for
|
||||
// lazygit to become idle only after the last one. Keys pressed this way can
|
||||
// arrive while the previous key's processing is still in flight, like a user
|
||||
// typing faster than lazygit handles the input.
|
||||
func (self *GuiDriver) PressKeysRapidly(keyStrs ...string) {
|
||||
self.CheckAllToastsAcknowledged()
|
||||
|
||||
key, ok := config.KeyFromLabel(keyStr)
|
||||
if !ok {
|
||||
self.Fail("Unrecognized key: " + keyStr)
|
||||
}
|
||||
for _, keyStr := range keyStrs {
|
||||
key, ok := config.KeyFromLabel(keyStr)
|
||||
if !ok {
|
||||
self.Fail("Unrecognized key: " + keyStr)
|
||||
}
|
||||
|
||||
self.gui.g.ReplayKeyEvent(gocui.NewTcellKeyEventWrapper(
|
||||
tcell.NewEventKey(tcell.Key(key.KeyName()), key.Str(), tcell.ModMask(key.Mod())),
|
||||
0,
|
||||
))
|
||||
self.gui.g.ReplayKeyEvent(gocui.NewTcellKeyEventWrapper(
|
||||
tcell.NewEventKey(tcell.Key(key.KeyName()), key.Str(), tcell.ModMask(key.Mod())),
|
||||
0,
|
||||
))
|
||||
}
|
||||
|
||||
self.waitTillIdle()
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package components
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
@@ -42,6 +43,15 @@ func (self *TestDriver) pressFast(keyStr string) {
|
||||
self.Wait(self.inputDelay / 5)
|
||||
}
|
||||
|
||||
// presses the keys in immediate succession, without waiting for lazygit to
|
||||
// become idle in between, to simulate a user typing faster than lazygit
|
||||
// processes the input
|
||||
func (self *TestDriver) pressRapidly(keyStrs []string) {
|
||||
self.SetCaption(fmt.Sprintf("Pressing %s", strings.Join(keyStrs, ", ")))
|
||||
self.gui.PressKeysRapidly(keyStrs...)
|
||||
self.Wait(self.inputDelay)
|
||||
}
|
||||
|
||||
func (self *TestDriver) click(x, y int) {
|
||||
self.SetCaption(fmt.Sprintf("Clicking %d, %d", x, y))
|
||||
self.gui.Click(x, y)
|
||||
|
||||
@@ -30,6 +30,10 @@ func (self *fakeGuiDriver) PressKey(key string) {
|
||||
self.pressedKeys = append(self.pressedKeys, key)
|
||||
}
|
||||
|
||||
func (self *fakeGuiDriver) PressKeysRapidly(keys ...string) {
|
||||
self.pressedKeys = append(self.pressedKeys, keys...)
|
||||
}
|
||||
|
||||
func (self *fakeGuiDriver) Click(x, y int) {
|
||||
self.clickedCoordinates = append(self.clickedCoordinates, coordinate{x: x, y: y})
|
||||
}
|
||||
|
||||
@@ -454,6 +454,19 @@ func (self *ViewDriver) PressFast(key config.Keybinding) *ViewDriver {
|
||||
return self
|
||||
}
|
||||
|
||||
// Presses the given keys in immediate succession, without waiting for lazygit
|
||||
// to become idle in between (Press waits after every key). Use this to
|
||||
// simulate a user typing faster than lazygit processes the input.
|
||||
func (self *ViewDriver) PressRapidly(keys ...config.Keybinding) *ViewDriver {
|
||||
self.IsFocused()
|
||||
|
||||
self.t.pressRapidly(lo.Map(keys, func(key config.Keybinding, _ int) string {
|
||||
return key[0]
|
||||
}))
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *ViewDriver) Click(x, y int) *ViewDriver {
|
||||
offsetX, offsetY, _, _ := self.getView().Dimensions()
|
||||
|
||||
|
||||
@@ -23,6 +23,10 @@ type IntegrationTest interface {
|
||||
// this is the interface through which our integration tests interact with the lazygit gui
|
||||
type GuiDriver interface {
|
||||
PressKey(string)
|
||||
// Like PressKey, but presses several keys in immediate succession, waiting
|
||||
// for lazygit to become idle only after the last one. Use it to simulate a
|
||||
// user typing faster than lazygit processes the input.
|
||||
PressKeysRapidly(...string)
|
||||
Click(int, int)
|
||||
// Simulate the terminal window regaining focus (which triggers a reload of
|
||||
// changed config files)
|
||||
|
||||
Reference in New Issue
Block a user