mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-12 11:15:00 +02:00
e33fe37a99
We've been sometimes using lo and sometimes using my slices package, and we need to pick one for consistency. Lo is more extensive and better maintained so we're going with that. My slices package was a superset of go's own slices package so in some places I've just used the official one (the methods were just wrappers anyway). I've also moved the remaining methods into the utils package.
226 lines
5.8 KiB
Go
226 lines
5.8 KiB
Go
package components
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
|
"github.com/jesseduffield/lazygit/pkg/config"
|
|
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
// IntegrationTest describes an integration test that will be run against the lazygit gui.
|
|
|
|
// our unit tests will use this description to avoid a panic caused by attempting
|
|
// to get the test's name via it's file's path.
|
|
const unitTestDescription = "test test"
|
|
|
|
const (
|
|
defaultWidth = 100
|
|
defaultHeight = 100
|
|
)
|
|
|
|
type IntegrationTest struct {
|
|
name string
|
|
description string
|
|
extraCmdArgs []string
|
|
extraEnvVars map[string]string
|
|
skip bool
|
|
setupRepo func(shell *Shell)
|
|
setupConfig func(config *config.AppConfig)
|
|
run func(
|
|
testDriver *TestDriver,
|
|
keys config.KeybindingConfig,
|
|
)
|
|
gitVersion GitVersionRestriction
|
|
width int
|
|
height int
|
|
}
|
|
|
|
var _ integrationTypes.IntegrationTest = &IntegrationTest{}
|
|
|
|
type NewIntegrationTestArgs struct {
|
|
// Briefly describes what happens in the test and what it's testing for
|
|
Description string
|
|
// prepares a repo for testing
|
|
SetupRepo func(shell *Shell)
|
|
// takes a config and mutates. The mutated context will end up being passed to the gui
|
|
SetupConfig func(config *config.AppConfig)
|
|
// runs the test
|
|
Run func(t *TestDriver, keys config.KeybindingConfig)
|
|
// additional args passed to lazygit
|
|
ExtraCmdArgs []string
|
|
// for when a test is flakey
|
|
ExtraEnvVars map[string]string
|
|
Skip bool
|
|
// to run a test only on certain git versions
|
|
GitVersion GitVersionRestriction
|
|
// width and height when running in headless mode, for testing
|
|
// the UI in different sizes.
|
|
// If these are set, the test must be run in headless mode
|
|
Width int
|
|
Height int
|
|
}
|
|
|
|
type GitVersionRestriction struct {
|
|
// Only one of these fields can be non-empty; use functions below to construct
|
|
from string
|
|
before string
|
|
includes []string
|
|
}
|
|
|
|
// Verifies the version is at least the given version (inclusive)
|
|
func AtLeast(version string) GitVersionRestriction {
|
|
return GitVersionRestriction{from: version}
|
|
}
|
|
|
|
// Verifies the version is before the given version (exclusive)
|
|
func Before(version string) GitVersionRestriction {
|
|
return GitVersionRestriction{before: version}
|
|
}
|
|
|
|
func Includes(versions ...string) GitVersionRestriction {
|
|
return GitVersionRestriction{includes: versions}
|
|
}
|
|
|
|
func (self GitVersionRestriction) shouldRunOnVersion(version *git_commands.GitVersion) bool {
|
|
if self.from != "" {
|
|
from, err := git_commands.ParseGitVersion(self.from)
|
|
if err != nil {
|
|
panic("Invalid git version string: " + self.from)
|
|
}
|
|
return !version.IsOlderThanVersion(from)
|
|
}
|
|
if self.before != "" {
|
|
before, err := git_commands.ParseGitVersion(self.before)
|
|
if err != nil {
|
|
panic("Invalid git version string: " + self.before)
|
|
}
|
|
return version.IsOlderThanVersion(before)
|
|
}
|
|
if len(self.includes) != 0 {
|
|
return lo.SomeBy(self.includes, func(str string) bool {
|
|
v, err := git_commands.ParseGitVersion(str)
|
|
if err != nil {
|
|
panic("Invalid git version string: " + str)
|
|
}
|
|
return version.Major == v.Major && version.Minor == v.Minor && version.Patch == v.Patch
|
|
})
|
|
}
|
|
return true
|
|
}
|
|
|
|
func NewIntegrationTest(args NewIntegrationTestArgs) *IntegrationTest {
|
|
name := ""
|
|
if args.Description != unitTestDescription {
|
|
// this panics if we're in a unit test for our integration tests,
|
|
// so we're using "test test" as a sentinel value
|
|
name = testNameFromCurrentFilePath()
|
|
}
|
|
|
|
return &IntegrationTest{
|
|
name: name,
|
|
description: args.Description,
|
|
extraCmdArgs: args.ExtraCmdArgs,
|
|
extraEnvVars: args.ExtraEnvVars,
|
|
skip: args.Skip,
|
|
setupRepo: args.SetupRepo,
|
|
setupConfig: args.SetupConfig,
|
|
run: args.Run,
|
|
gitVersion: args.GitVersion,
|
|
width: args.Width,
|
|
height: args.Height,
|
|
}
|
|
}
|
|
|
|
func (self *IntegrationTest) Name() string {
|
|
return self.name
|
|
}
|
|
|
|
func (self *IntegrationTest) Description() string {
|
|
return self.description
|
|
}
|
|
|
|
func (self *IntegrationTest) ExtraCmdArgs() []string {
|
|
return self.extraCmdArgs
|
|
}
|
|
|
|
func (self *IntegrationTest) ExtraEnvVars() map[string]string {
|
|
return self.extraEnvVars
|
|
}
|
|
|
|
func (self *IntegrationTest) Skip() bool {
|
|
return self.skip
|
|
}
|
|
|
|
func (self *IntegrationTest) ShouldRunForGitVersion(version *git_commands.GitVersion) bool {
|
|
return self.gitVersion.shouldRunOnVersion(version)
|
|
}
|
|
|
|
func (self *IntegrationTest) SetupConfig(config *config.AppConfig) {
|
|
self.setupConfig(config)
|
|
}
|
|
|
|
func (self *IntegrationTest) SetupRepo(shell *Shell) {
|
|
self.setupRepo(shell)
|
|
}
|
|
|
|
func (self *IntegrationTest) Run(gui integrationTypes.GuiDriver) {
|
|
pwd, err := os.Getwd()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
shell := NewShell(pwd, func(errorMsg string) { gui.Fail(errorMsg) })
|
|
keys := gui.Keys()
|
|
testDriver := NewTestDriver(gui, shell, keys, KeyPressDelay())
|
|
|
|
self.run(testDriver, keys)
|
|
|
|
if KeyPressDelay() > 0 {
|
|
// the dev would want to see the final state if they're running in slow mode
|
|
testDriver.Wait(2000)
|
|
}
|
|
}
|
|
|
|
func (self *IntegrationTest) HeadlessDimensions() (int, int) {
|
|
if self.width == 0 && self.height == 0 {
|
|
return defaultWidth, defaultHeight
|
|
}
|
|
|
|
return self.width, self.height
|
|
}
|
|
|
|
func (self *IntegrationTest) RequiresHeadless() bool {
|
|
return self.width != 0 && self.height != 0
|
|
}
|
|
|
|
func testNameFromCurrentFilePath() string {
|
|
path := utils.FilePath(3)
|
|
return TestNameFromFilePath(path)
|
|
}
|
|
|
|
func TestNameFromFilePath(path string) string {
|
|
name := strings.Split(path, "integration/tests/")[1]
|
|
|
|
return name[:len(name)-len(".go")]
|
|
}
|
|
|
|
// this is the delay in milliseconds between keypresses
|
|
// defaults to zero
|
|
func KeyPressDelay() int {
|
|
delayStr := os.Getenv("KEY_PRESS_DELAY")
|
|
if delayStr == "" {
|
|
return 0
|
|
}
|
|
|
|
delay, err := strconv.Atoi(delayStr)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return delay
|
|
}
|