mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-15 18:16:25 -04:00
Merge branch 'master' into gh-integration
This commit is contained in:
commit
c06974b879
10
.github/pull_request_template.md
vendored
Normal file
10
.github/pull_request_template.md
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
- **PR Description**
|
||||
|
||||
- **Please check if the PR fulfills these requirements**
|
||||
|
||||
* [ ] Cheatsheets are up-to-date (run `go run scripts/cheatsheet/main.go generate`)
|
||||
* [ ] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting))
|
||||
* [ ] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide)
|
||||
* [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation))
|
||||
* [ ] Docs (specifically `docs/Config.md`) have been updated if necessary
|
||||
* [ ] You've read through your own file changes for silly mistakes etc
|
||||
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
|
|
@ -135,7 +135,7 @@ jobs:
|
|||
- name: Build integration test injector
|
||||
run: |
|
||||
GOOS=linux go build pkg/integration/clients/injector/main.go
|
||||
check-cheatsheet:
|
||||
check-codebase:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GOFLAGS: -mod=vendor
|
||||
|
|
@ -159,6 +159,10 @@ jobs:
|
|||
- name: Check Cheatsheet
|
||||
run: |
|
||||
go run scripts/cheatsheet/main.go check
|
||||
- name: Check Vendor Directory
|
||||
# ensure our vendor directory matches up with our go modules
|
||||
run: |
|
||||
go mod vendor && git diff --exit-code || (echo "Unexpected change to vendor directory. Run 'go mod vendor' locally and commit the changes" && exit 1)
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
|
|
@ -183,12 +187,6 @@ jobs:
|
|||
uses: golangci/golangci-lint-action@v3.1.0
|
||||
with:
|
||||
version: latest
|
||||
- name: Format code
|
||||
run: |
|
||||
if [ $(find . ! -path "./vendor/*" -name "*.go" -exec gofmt -s -d {} \;|wc -l) -gt 0 ]; then
|
||||
find . ! -path "./vendor/*" -name "*.go" -exec gofmt -s -d {} \;
|
||||
exit 1
|
||||
fi
|
||||
- name: errors
|
||||
run: golangci-lint run
|
||||
if: ${{ failure() }}
|
||||
|
|
|
|||
|
|
@ -69,9 +69,15 @@ by setting [`formatting.gofumpt`](https://github.com/golang/tools/blob/master/go
|
|||
}
|
||||
```
|
||||
|
||||
To run gofumpt from your terminal go:
|
||||
|
||||
```
|
||||
go install mvdan.cc/gofumpt@latest && gofumpt -l -w .
|
||||
```
|
||||
|
||||
## Internationalisation
|
||||
|
||||
Boy that's a hard word to spell. Anyway, lazygit is translated into several languages within the pkg/i18n package. If you need to render text to the user, you should add a new field to the TranslationSet struct in `pkg/i18n/english.go` and add the actual content within the `EnglishTranslationSet()` method in the same file. Although it is appreciated if you translate the text into other languages, it's not expected of you (google translate will likely do a bad job anyway!).
|
||||
Boy that's a hard word to spell. Anyway, lazygit is translated into several languages within the pkg/i18n package. If you need to render text to the user, you should add a new field to the TranslationSet struct in `pkg/i18n/english.go` and add the actual content within the `EnglishTranslationSet()` method in the same file. Then you can access via `gui.Tr.YourNewText` (or `app.Tr.YourNewText`, etc). Although it is appreciated if you translate the text into other languages, it's not expected of you (google translate will likely do a bad job anyway!).
|
||||
|
||||
## Debugging
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Usage:
|
|||
See https://github.com/jesseduffield/lazygit/tree/master/pkg/integration/README.md
|
||||
|
||||
CLI mode:
|
||||
> go run cmd/integration_test/main.go cli <test1> <test2> ...
|
||||
> go run cmd/integration_test/main.go cli [--slow] <test1> <test2> ...
|
||||
If you pass no test names, it runs all tests
|
||||
Accepted environment variables:
|
||||
KEY_PRESS_DELAY (e.g. 200): the number of milliseconds to wait between keypresses
|
||||
|
|
@ -40,7 +40,14 @@ func main() {
|
|||
case "help":
|
||||
fmt.Println(usage)
|
||||
case "cli":
|
||||
clients.RunCLI(os.Args[2:])
|
||||
testNames := os.Args[2:]
|
||||
slow := false
|
||||
// get the next arg if it's --slow
|
||||
if len(os.Args) > 2 && (os.Args[2] == "--slow" || os.Args[2] == "-slow") {
|
||||
testNames = os.Args[3:]
|
||||
slow = true
|
||||
}
|
||||
clients.RunCLI(testNames, slow)
|
||||
case "tui":
|
||||
clients.RunTUI()
|
||||
default:
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -18,7 +18,7 @@ require (
|
|||
github.com/integrii/flaggy v1.4.0
|
||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20220813101052-3a3ab26faa15
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20220815095708-156fda5e0419
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
|
||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
|
||||
github.com/jesseduffield/yaml v2.1.0+incompatible
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -72,8 +72,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
|
|||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4 h1:GOQrmaE8i+KEdB8NzAegKYd4tPn/inM0I1uo0NXFerg=
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20220813101052-3a3ab26faa15 h1:DTVj8aCmINqLj5AXBEGmpWwfN1HJ3EWtUiYfcyIaSxs=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20220813101052-3a3ab26faa15/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20220815095708-156fda5e0419 h1:p3Ix7RUcy4X16Lk5jTSfTxecJT7ryqYHclfRbo/Svzs=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20220815095708-156fda5e0419/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU=
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
|
||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e h1:uw/oo+kg7t/oeMs6sqlAwr85ND/9cpO3up3VxphxY0U=
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/jesseduffield/generics/slices"
|
||||
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_config"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
|
|
@ -200,6 +201,18 @@ func isDirectoryAGitRepository(dir string) (bool, error) {
|
|||
return info != nil, err
|
||||
}
|
||||
|
||||
func openRecentRepo(app *App) bool {
|
||||
for _, repoDir := range app.Config.GetAppState().RecentRepos {
|
||||
if isRepo, _ := isDirectoryAGitRepository(repoDir); isRepo {
|
||||
if err := os.Chdir(repoDir); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (app *App) setupRepo() (bool, error) {
|
||||
if err := app.validateGitVersion(); err != nil {
|
||||
return false, err
|
||||
|
|
@ -216,6 +229,7 @@ func (app *App) setupRepo() (bool, error) {
|
|||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if isRepo, err := isDirectoryAGitRepository(cwd); isRepo {
|
||||
return false, err
|
||||
}
|
||||
|
|
@ -268,6 +282,28 @@ func (app *App) setupRepo() (bool, error) {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Run this afterward so that the previous repo creation steps can run without this interfering
|
||||
if isBare, err := git_commands.IsBareRepo(app.OSCommand); isBare {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
fmt.Print(app.Tr.BareRepo)
|
||||
|
||||
response, _ := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
|
||||
if shouldOpenRecent := strings.Trim(response, " \r\n") == "y"; !shouldOpenRecent {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if didOpenRepo := openRecentRepo(app); didOpenRepo {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
fmt.Println(app.Tr.NoRecentRepositories)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@ package git_commands
|
|||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
gogit "github.com/jesseduffield/go-git/v5"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
)
|
||||
|
||||
|
|
@ -49,13 +51,21 @@ func (self *StatusCommands) WorkingTreeState() enums.RebaseMode {
|
|||
return enums.REBASE_MODE_NONE
|
||||
}
|
||||
|
||||
func (self *StatusCommands) IsBareRepo() (bool, error) {
|
||||
return IsBareRepo(self.os)
|
||||
}
|
||||
|
||||
func IsBareRepo(osCommand *oscommands.OSCommand) (bool, error) {
|
||||
res, err := osCommand.Cmd.New("git rev-parse --is-bare-repository").DontLog().RunWithOutput()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// The command returns output with a newline, so we need to strip
|
||||
return strconv.ParseBool(strings.TrimSpace(res))
|
||||
}
|
||||
|
||||
// IsInMergeState states whether we are still mid-merge
|
||||
func (self *StatusCommands) IsInMergeState() (bool, error) {
|
||||
return self.os.FileExists(filepath.Join(self.dotGitDir, "MERGE_HEAD"))
|
||||
}
|
||||
|
||||
func (self *StatusCommands) IsBareRepo() bool {
|
||||
// note: could use `git rev-parse --is-bare-repository` if we wanna drop go-git
|
||||
_, err := self.repo.Worktree()
|
||||
return err == gogit.ErrIsBareRepository
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,7 +315,9 @@ type CustomCommand struct {
|
|||
}
|
||||
|
||||
type CustomCommandPrompt struct {
|
||||
Type string `yaml:"type"` // one of 'input', 'menu', or 'confirm'
|
||||
// one of 'input', 'menu', 'confirm', or 'menuFromCommand'
|
||||
Type string `yaml:"type"`
|
||||
|
||||
Title string `yaml:"title"`
|
||||
|
||||
// this only apply to input prompts
|
||||
|
|
|
|||
|
|
@ -71,3 +71,11 @@ func (self *GuiDriver) LogUI(message string) {
|
|||
func (self *GuiDriver) CheckedOutRef() *models.Branch {
|
||||
return self.gui.helpers.Refs.GetCheckedOutRef()
|
||||
}
|
||||
|
||||
func (self *GuiDriver) MainView() *gocui.View {
|
||||
return self.gui.mainView()
|
||||
}
|
||||
|
||||
func (self *GuiDriver) SecondaryView() *gocui.View {
|
||||
return self.gui.secondaryView()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,12 @@ func (gui *Gui) dispatchSwitchToRepo(path string, reuse bool) error {
|
|||
// updateRecentRepoList registers the fact that we opened lazygit in this repo,
|
||||
// so that we can open the same repo via the 'recent repos' menu
|
||||
func (gui *Gui) updateRecentRepoList() error {
|
||||
if gui.git.Status.IsBareRepo() {
|
||||
isBareRepo, err := gui.git.Status.IsBareRepo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isBareRepo {
|
||||
// we could totally do this but it would require storing both the git-dir and the
|
||||
// worktree in our recent repos list, which is a change that would need to be
|
||||
// backwards compatible
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ type TranslationSet struct {
|
|||
DiscardFileChangesPrompt string
|
||||
DisabledForGPG string
|
||||
CreateRepo string
|
||||
BareRepo string
|
||||
InitialBranch string
|
||||
NoRecentRepositories string
|
||||
IncorrectNotARepository string
|
||||
|
|
@ -901,6 +902,7 @@ func EnglishTranslationSet() TranslationSet {
|
|||
DiscardFileChangesPrompt: "Are you sure you want to discard this commit's changes to this file? If this file was created in this commit, it will be deleted",
|
||||
DisabledForGPG: "Feature not available for users using GPG",
|
||||
CreateRepo: "Not in a git repository. Create a new git repository? (y/n): ",
|
||||
BareRepo: "You've attempted to open Lazygit in a bare repo but Lazygit does not yet support bare repos. Open most recent repo? (y/n) ",
|
||||
InitialBranch: "Branch name? (leave empty for git's default): ",
|
||||
NoRecentRepositories: "Must open lazygit in a git repository. No valid recent repositories. Exiting.",
|
||||
IncorrectNotARepository: "The value of 'notARepository' is incorrect. It should be one of 'prompt', 'create', 'skip', or 'quit'.",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,18 @@
|
|||
# Integration Tests
|
||||
|
||||
The pkg/integration pacakge is for integration testing: that is, actually running a real lazygit session and having a robot pretend to be a human user and then making assertions that everything works as expected.
|
||||
The pkg/integration package is for integration testing: that is, actually running a real lazygit session and having a robot pretend to be a human user and then making assertions that everything works as expected.
|
||||
|
||||
TL;DR: integration tests live in pkg/integration/tests. Run integration tests with:
|
||||
|
||||
```sh
|
||||
go run cmd/integration_test/main.go tui
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
go run cmd/integration_test/main.go cli [--slow] [testname or testpath...]
|
||||
```
|
||||
|
||||
## Writing tests
|
||||
|
||||
|
|
@ -37,7 +49,7 @@ If you find yourself doing something frequently in a test, consider making it a
|
|||
|
||||
There are three ways to invoke a test:
|
||||
|
||||
1. go run cmd/integration_test/main.go cli [<testname>...]
|
||||
1. go run cmd/integration_test/main.go cli [--slow] [testname or testpath...]
|
||||
2. go run cmd/integration_test/main.go tui
|
||||
3. go test pkg/integration/clients/go_test.go
|
||||
|
||||
|
|
@ -47,7 +59,7 @@ The third, the go-test command, intended only for use in CI, to be run along wit
|
|||
|
||||
The name of a test is based on its path, so the name of the test at `pkg/integration/tests/commit/new_branch.go` is commit/new_branch. So to run it with our test runner you would run `go run cmd/integration_test/main.go cli commit/new_branch`.
|
||||
|
||||
You can pass the KEY_PRESS_DELAY env var to the test runner in order to set a delay in milliseconds between keypresses, which helps for watching a test at a realistic speed to understand what it's doing. Or in the tui you can press 't' to run the test with a pre-set delay.
|
||||
You can pass the KEY_PRESS_DELAY env var to the test runner in order to set a delay in milliseconds between keypresses, which helps for watching a test at a realistic speed to understand what it's doing. Or you can pass the '--slow' flag which sets a pre-set 'slow' key delay. In the tui you can press 't' to run the test in slow mode.
|
||||
|
||||
### Snapshots
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/generics/slices"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests"
|
||||
)
|
||||
|
|
@ -20,14 +23,19 @@ import (
|
|||
|
||||
// If invoked directly, you can specify tests to run by passing their names as positional arguments
|
||||
|
||||
func RunCLI(testNames []string) {
|
||||
func RunCLI(testNames []string, slow bool) {
|
||||
keyPressDelay := tryConvert(os.Getenv("KEY_PRESS_DELAY"), 0)
|
||||
if slow {
|
||||
keyPressDelay = SLOW_KEY_PRESS_DELAY
|
||||
}
|
||||
|
||||
err := components.RunTests(
|
||||
getTestsToRun(testNames),
|
||||
log.Printf,
|
||||
runCmdInTerminal,
|
||||
runAndPrintError,
|
||||
getModeFromEnv(),
|
||||
tryConvert(os.Getenv("KEY_PRESS_DELAY"), 0),
|
||||
keyPressDelay,
|
||||
)
|
||||
if err != nil {
|
||||
log.Print(err.Error())
|
||||
|
|
@ -36,21 +44,30 @@ func RunCLI(testNames []string) {
|
|||
|
||||
func runAndPrintError(test *components.IntegrationTest, f func() error) {
|
||||
if err := f(); err != nil {
|
||||
log.Print(err.Error())
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func getTestsToRun(testNames []string) []*components.IntegrationTest {
|
||||
allIntegrationTests := tests.GetTests()
|
||||
var testsToRun []*components.IntegrationTest
|
||||
|
||||
if len(testNames) == 0 {
|
||||
return tests.Tests
|
||||
return allIntegrationTests
|
||||
}
|
||||
|
||||
testNames = slices.Map(testNames, func(name string) string {
|
||||
// allowing full test paths to be passed for convenience
|
||||
return strings.TrimSuffix(
|
||||
regexp.MustCompile(`.*pkg/integration/tests/`).ReplaceAllString(name, ""),
|
||||
".go",
|
||||
)
|
||||
})
|
||||
|
||||
outer:
|
||||
for _, testName := range testNames {
|
||||
// check if our given test name actually exists
|
||||
for _, test := range tests.Tests {
|
||||
for _, test := range allIntegrationTests {
|
||||
if test.Name() == testName {
|
||||
testsToRun = append(testsToRun, test)
|
||||
continue outer
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ func TestIntegration(t *testing.T) {
|
|||
testNumber := 0
|
||||
|
||||
err := components.RunTests(
|
||||
tests.Tests,
|
||||
tests.GetTests(),
|
||||
t.Logf,
|
||||
runCmdHeadless,
|
||||
func(test *components.IntegrationTest, f func() error) {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ func getIntegrationTest() integrationTypes.IntegrationTest {
|
|||
))
|
||||
}
|
||||
|
||||
for _, candidateTest := range tests.Tests {
|
||||
allTests := tests.GetTests()
|
||||
for _, candidateTest := range allTests {
|
||||
if candidateTest.Name() == integrationTestName {
|
||||
return candidateTest
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import (
|
|||
|
||||
// This program lets you run integration tests from a TUI. See pkg/integration/README.md for more info.
|
||||
|
||||
var SLOW_KEY_PRESS_DELAY = 300
|
||||
|
||||
func RunTUI() {
|
||||
rootDir := utils.GetLazygitRootDirectory()
|
||||
testDir := filepath.Join(rootDir, "test", "integration")
|
||||
|
|
@ -106,7 +108,7 @@ func RunTUI() {
|
|||
return nil
|
||||
}
|
||||
|
||||
suspendAndRunTest(currentTest, components.ASK_TO_UPDATE_SNAPSHOT, 200)
|
||||
suspendAndRunTest(currentTest, components.ASK_TO_UPDATE_SNAPSHOT, SLOW_KEY_PRESS_DELAY)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
|
|
@ -168,7 +170,7 @@ func RunTUI() {
|
|||
return err
|
||||
}
|
||||
|
||||
app.filteredTests = tests.Tests
|
||||
app.filteredTests = app.allTests
|
||||
app.renderTests()
|
||||
app.editorView.TextArea.Clear()
|
||||
app.editorView.Clear()
|
||||
|
|
@ -204,6 +206,7 @@ func RunTUI() {
|
|||
}
|
||||
|
||||
type app struct {
|
||||
allTests []*components.IntegrationTest
|
||||
filteredTests []*components.IntegrationTest
|
||||
itemIdx int
|
||||
testDir string
|
||||
|
|
@ -214,7 +217,7 @@ type app struct {
|
|||
}
|
||||
|
||||
func newApp(testDir string) *app {
|
||||
return &app{testDir: testDir}
|
||||
return &app{testDir: testDir, allTests: tests.GetTests()}
|
||||
}
|
||||
|
||||
func (self *app) getCurrentTest() *components.IntegrationTest {
|
||||
|
|
@ -226,7 +229,7 @@ func (self *app) getCurrentTest() *components.IntegrationTest {
|
|||
}
|
||||
|
||||
func (self *app) loadTests() {
|
||||
self.filteredTests = tests.Tests
|
||||
self.filteredTests = self.allTests
|
||||
|
||||
self.adjustCursor()
|
||||
}
|
||||
|
|
@ -237,9 +240,9 @@ func (self *app) adjustCursor() {
|
|||
|
||||
func (self *app) filterWithString(needle string) {
|
||||
if needle == "" {
|
||||
self.filteredTests = tests.Tests
|
||||
self.filteredTests = self.allTests
|
||||
} else {
|
||||
self.filteredTests = slices.Filter(tests.Tests, func(test *components.IntegrationTest) bool {
|
||||
self.filteredTests = slices.Filter(self.allTests, func(test *components.IntegrationTest) bool {
|
||||
return strings.Contains(test.Name(), needle)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,43 @@ func NewAssert(gui integrationTypes.GuiDriver) *Assert {
|
|||
return &Assert{gui: gui}
|
||||
}
|
||||
|
||||
// for making assertions on string values
|
||||
type matcher struct {
|
||||
testFn func(string) (bool, string)
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (self *matcher) test(value string) (bool, string) {
|
||||
ok, message := self.testFn(value)
|
||||
if ok {
|
||||
return true, ""
|
||||
}
|
||||
|
||||
if self.prefix != "" {
|
||||
return false, self.prefix + " " + message
|
||||
}
|
||||
|
||||
return false, message
|
||||
}
|
||||
|
||||
func (self *matcher) context(prefix string) *matcher {
|
||||
self.prefix = prefix
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func Contains(target string) *matcher {
|
||||
return &matcher{testFn: func(value string) (bool, string) {
|
||||
return strings.Contains(value, target), fmt.Sprintf("Expected '%s' to contain '%s'", value, target)
|
||||
}}
|
||||
}
|
||||
|
||||
func Equals(target string) *matcher {
|
||||
return &matcher{testFn: func(value string) (bool, string) {
|
||||
return target == value, fmt.Sprintf("Expected '%s' to equal '%s'", value, target)
|
||||
}}
|
||||
}
|
||||
|
||||
func (self *Assert) WorkingTreeFileCount(expectedCount int) {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
actualCount := len(self.gui.Model().Files)
|
||||
|
|
@ -41,22 +78,16 @@ func (self *Assert) CommitCount(expectedCount int) {
|
|||
})
|
||||
}
|
||||
|
||||
func (self *Assert) HeadCommitMessage(expectedMessage string) {
|
||||
func (self *Assert) MatchHeadCommitMessage(matcher *matcher) {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
if len(self.gui.Model().Commits) == 0 {
|
||||
return false, "Expected at least one commit to be present"
|
||||
}
|
||||
|
||||
headCommit := self.gui.Model().Commits[0]
|
||||
if headCommit.Name != expectedMessage {
|
||||
return false, fmt.Sprintf(
|
||||
"Expected commit message to be '%s', but got '%s'",
|
||||
expectedMessage, headCommit.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return true, ""
|
||||
return len(self.gui.Model().Commits) > 0, "Expected at least one commit to be present"
|
||||
})
|
||||
|
||||
self.matchString(matcher, "Unexpected commit message.",
|
||||
func() string {
|
||||
return self.gui.Model().Commits[0].Name
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) CurrentViewName(expectedViewName string) {
|
||||
|
|
@ -81,10 +112,70 @@ func (self *Assert) InListContext() {
|
|||
})
|
||||
}
|
||||
|
||||
func (self *Assert) SelectedLineContains(text string) {
|
||||
func (self *Assert) MatchSelectedLine(matcher *matcher) {
|
||||
self.matchString(matcher, "Unexpected selected line.",
|
||||
func() string {
|
||||
return self.gui.CurrentContext().GetView().SelectedLine()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) InPrompt() {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
line := self.gui.CurrentContext().GetView().SelectedLine()
|
||||
return strings.Contains(line, text), fmt.Sprintf("Expected selected line to contain '%s', but got '%s'", text, line)
|
||||
currentView := self.gui.CurrentContext().GetView()
|
||||
return currentView.Name() == "confirmation" && currentView.Editable, "Expected prompt popup to be focused"
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) InConfirm() {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
currentView := self.gui.CurrentContext().GetView()
|
||||
return currentView.Name() == "confirmation" && !currentView.Editable, "Expected confirmation popup to be focused"
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) InAlert() {
|
||||
// basically the same thing as a confirmation popup with the current implementation
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
currentView := self.gui.CurrentContext().GetView()
|
||||
return currentView.Name() == "confirmation" && !currentView.Editable, "Expected alert popup to be focused"
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) InMenu() {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
return self.gui.CurrentContext().GetView().Name() == "menu", "Expected popup menu to be focused"
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) MatchCurrentViewTitle(matcher *matcher) {
|
||||
self.matchString(matcher, "Unexpected current view title.",
|
||||
func() string {
|
||||
return self.gui.CurrentContext().GetView().Title
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) MatchMainViewContent(matcher *matcher) {
|
||||
self.matchString(matcher, "Unexpected main view content.",
|
||||
func() string {
|
||||
return self.gui.MainView().Buffer()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) MatchSecondaryViewContent(matcher *matcher) {
|
||||
self.matchString(matcher, "Unexpected secondary view title.",
|
||||
func() string {
|
||||
return self.gui.SecondaryView().Buffer()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) matchString(matcher *matcher, context string, getValue func() string) {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
value := getValue()
|
||||
return matcher.context(context).test(value)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ func (self *Input) Cancel() {
|
|||
}
|
||||
|
||||
// i.e. pressing space
|
||||
func (self *Input) Select() {
|
||||
func (self *Input) PrimaryAction() {
|
||||
self.pressKey(self.keys.Universal.Select)
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ func (self *Input) PreviousItem() {
|
|||
|
||||
func (self *Input) ContinueMerge() {
|
||||
self.PressKeys(self.keys.Universal.CreateRebaseOptionsMenu)
|
||||
self.assert.SelectedLineContains("continue")
|
||||
self.assert.MatchSelectedLine(Contains("continue"))
|
||||
self.Confirm()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,9 +136,10 @@ func createFixture(test *IntegrationTest, paths Paths) error {
|
|||
}
|
||||
|
||||
shell := NewShell()
|
||||
shell.RunCommand("git init")
|
||||
shell.RunCommand("git init -b master")
|
||||
shell.RunCommand(`git config user.email "CI@example.com"`)
|
||||
shell.RunCommand(`git config user.name "CI"`)
|
||||
shell.RunCommand(`git config commit.gpgSign false`)
|
||||
|
||||
test.SetupRepo(shell)
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ func NewIntegrationTest(args NewIntegrationTestArgs) *IntegrationTest {
|
|||
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 = testNameFromFilePath()
|
||||
name = testNameFromCurrentFilePath()
|
||||
}
|
||||
|
||||
return &IntegrationTest{
|
||||
|
|
@ -106,8 +106,12 @@ func (self *IntegrationTest) Run(gui integrationTypes.GuiDriver) {
|
|||
}
|
||||
}
|
||||
|
||||
func testNameFromFilePath() string {
|
||||
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")]
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package components
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
|
|
@ -47,6 +48,14 @@ func (self *fakeGuiDriver) CheckedOutRef() *models.Branch {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (self *fakeGuiDriver) MainView() *gocui.View {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *fakeGuiDriver) SecondaryView() *gocui.View {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestAssertionFailure(t *testing.T) {
|
||||
test := NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: unitTestDescription,
|
||||
|
|
|
|||
|
|
@ -2,24 +2,24 @@ package commit
|
|||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var Commit = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
||||
var Commit = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Staging a couple files and committing",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *components.Shell) {
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateFile("myfile", "myfile content")
|
||||
shell.CreateFile("myfile2", "myfile2 content")
|
||||
},
|
||||
Run: func(shell *components.Shell, input *components.Input, assert *components.Assert, keys config.KeybindingConfig) {
|
||||
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
|
||||
assert.CommitCount(0)
|
||||
|
||||
input.Select()
|
||||
input.PrimaryAction()
|
||||
input.NextItem()
|
||||
input.Select()
|
||||
input.PrimaryAction()
|
||||
input.PressKeys(keys.Files.CommitChanges)
|
||||
|
||||
commitMessage := "my commit message"
|
||||
|
|
@ -27,6 +27,6 @@ var Commit = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
|||
input.Confirm()
|
||||
|
||||
assert.CommitCount(1)
|
||||
assert.HeadCommitMessage(commitMessage)
|
||||
assert.MatchHeadCommitMessage(Equals(commitMessage))
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,21 +2,21 @@ package commit
|
|||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var NewBranch = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
||||
var NewBranch = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Creating a new branch from a commit",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *components.Shell) {
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
EmptyCommit("commit 1").
|
||||
EmptyCommit("commit 2").
|
||||
EmptyCommit("commit 3")
|
||||
},
|
||||
Run: func(shell *components.Shell, input *components.Input, assert *components.Assert, keys config.KeybindingConfig) {
|
||||
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
|
||||
assert.CommitCount(3)
|
||||
|
||||
input.SwitchToCommitsWindow()
|
||||
|
|
@ -32,7 +32,7 @@ var NewBranch = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
|||
input.Confirm()
|
||||
|
||||
assert.CommitCount(2)
|
||||
assert.HeadCommitMessage("commit 2")
|
||||
assert.MatchHeadCommitMessage(Contains("commit 2"))
|
||||
assert.CurrentBranchName(branchName)
|
||||
},
|
||||
})
|
||||
|
|
|
|||
36
pkg/integration/tests/custom_commands/basic.go
Normal file
36
pkg/integration/tests/custom_commands/basic.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var Basic = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Using a custom command to create a new file",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.EmptyCommit("blah")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "a",
|
||||
Context: "files",
|
||||
Command: "touch myfile",
|
||||
},
|
||||
}
|
||||
},
|
||||
Run: func(
|
||||
shell *Shell,
|
||||
input *Input,
|
||||
assert *Assert,
|
||||
keys config.KeybindingConfig,
|
||||
) {
|
||||
assert.WorkingTreeFileCount(0)
|
||||
|
||||
input.PressKeys("a")
|
||||
assert.WorkingTreeFileCount(1)
|
||||
assert.MatchSelectedLine(Contains("myfile"))
|
||||
},
|
||||
})
|
||||
74
pkg/integration/tests/custom_commands/menu_from_command.go
Normal file
74
pkg/integration/tests/custom_commands/menu_from_command.go
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
// NOTE: we're getting a weird offset in the popup prompt for some reason. Not sure what's behind that.
|
||||
|
||||
var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Using menuFromCommand prompt type",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
EmptyCommit("foo").
|
||||
EmptyCommit("bar").
|
||||
EmptyCommit("baz").
|
||||
NewBranch("feature/foo")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "a",
|
||||
Context: "localBranches",
|
||||
Command: `echo "{{index .PromptResponses 0}} {{index .PromptResponses 1}} {{ .SelectedLocalBranch.Name }}" > output.txt`,
|
||||
Prompts: []config.CustomCommandPrompt{
|
||||
{
|
||||
Type: "menuFromCommand",
|
||||
Title: "Choose commit message",
|
||||
Command: `git log --oneline --pretty=%B`,
|
||||
Filter: `(?P<commit_message>.*)`,
|
||||
ValueFormat: `{{ .commit_message }}`,
|
||||
LabelFormat: `{{ .commit_message | yellow }}`,
|
||||
},
|
||||
{
|
||||
Type: "input",
|
||||
Title: "Description",
|
||||
InitialValue: `{{ if .SelectedLocalBranch.Name }}Branch: #{{ .SelectedLocalBranch.Name }}{{end}}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
Run: func(
|
||||
shell *Shell,
|
||||
input *Input,
|
||||
assert *Assert,
|
||||
keys config.KeybindingConfig,
|
||||
) {
|
||||
assert.WorkingTreeFileCount(0)
|
||||
input.SwitchToBranchesWindow()
|
||||
|
||||
input.PressKeys("a")
|
||||
|
||||
assert.InMenu()
|
||||
assert.MatchCurrentViewTitle(Equals("Choose commit message"))
|
||||
assert.MatchSelectedLine(Equals("baz"))
|
||||
input.NextItem()
|
||||
assert.MatchSelectedLine(Equals("bar"))
|
||||
input.Confirm()
|
||||
|
||||
assert.InPrompt()
|
||||
assert.MatchCurrentViewTitle(Equals("Description"))
|
||||
input.Type(" my branch")
|
||||
input.Confirm()
|
||||
|
||||
input.SwitchToFilesWindow()
|
||||
|
||||
assert.WorkingTreeFileCount(1)
|
||||
assert.MatchSelectedLine(Contains("output.txt"))
|
||||
assert.MatchMainViewContent(Contains("bar Branch: #feature/foo my branch feature/foo"))
|
||||
},
|
||||
})
|
||||
86
pkg/integration/tests/custom_commands/multiple_prompts.go
Normal file
86
pkg/integration/tests/custom_commands/multiple_prompts.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var MultiplePrompts = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Using a custom command with multiple prompts",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.EmptyCommit("blah")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "a",
|
||||
Context: "files",
|
||||
Command: `echo "{{index .PromptResponses 1}}" > {{index .PromptResponses 0}}`,
|
||||
Prompts: []config.CustomCommandPrompt{
|
||||
{
|
||||
Type: "input",
|
||||
Title: "Enter a file name",
|
||||
},
|
||||
{
|
||||
Type: "menu",
|
||||
Title: "Choose file content",
|
||||
Options: []config.CustomCommandMenuOption{
|
||||
{
|
||||
Name: "foo",
|
||||
Description: "Foo",
|
||||
Value: "FOO",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Description: "Bar",
|
||||
Value: "BAR",
|
||||
},
|
||||
{
|
||||
Name: "baz",
|
||||
Description: "Baz",
|
||||
Value: "BAZ",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "confirm",
|
||||
Title: "Are you sure?",
|
||||
Body: "Are you REALLY sure you want to make this file? Up to you buddy.",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
Run: func(
|
||||
shell *Shell,
|
||||
input *Input,
|
||||
assert *Assert,
|
||||
keys config.KeybindingConfig,
|
||||
) {
|
||||
assert.WorkingTreeFileCount(0)
|
||||
|
||||
input.PressKeys("a")
|
||||
|
||||
assert.InPrompt()
|
||||
assert.MatchCurrentViewTitle(Equals("Enter a file name"))
|
||||
input.Type("myfile")
|
||||
input.Confirm()
|
||||
|
||||
assert.InMenu()
|
||||
assert.MatchCurrentViewTitle(Equals("Choose file content"))
|
||||
assert.MatchSelectedLine(Contains("foo"))
|
||||
input.NextItem()
|
||||
assert.MatchSelectedLine(Contains("bar"))
|
||||
input.Confirm()
|
||||
|
||||
assert.InConfirm()
|
||||
assert.MatchCurrentViewTitle(Equals("Are you sure?"))
|
||||
input.Confirm()
|
||||
|
||||
assert.WorkingTreeFileCount(1)
|
||||
assert.MatchSelectedLine(Contains("myfile"))
|
||||
assert.MatchMainViewContent(Contains("BAR"))
|
||||
},
|
||||
})
|
||||
|
|
@ -2,37 +2,37 @@ package interactive_rebase
|
|||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var One = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
||||
var One = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Begins an interactive rebase, then fixups, drops, and squashes some commits",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *components.Shell) {
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
CreateNCommits(5) // these will appears at commit 05, 04, 04, down to 01
|
||||
},
|
||||
Run: func(shell *components.Shell, input *components.Input, assert *components.Assert, keys config.KeybindingConfig) {
|
||||
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
|
||||
input.SwitchToCommitsWindow()
|
||||
assert.CurrentViewName("commits")
|
||||
|
||||
input.NavigateToListItemContainingText("commit 02")
|
||||
input.PressKeys(keys.Universal.Edit)
|
||||
assert.SelectedLineContains("YOU ARE HERE")
|
||||
assert.MatchSelectedLine(Contains("YOU ARE HERE"))
|
||||
|
||||
input.PreviousItem()
|
||||
input.PressKeys(keys.Commits.MarkCommitAsFixup)
|
||||
assert.SelectedLineContains("fixup")
|
||||
assert.MatchSelectedLine(Contains("fixup"))
|
||||
|
||||
input.PreviousItem()
|
||||
input.PressKeys(keys.Universal.Remove)
|
||||
assert.SelectedLineContains("drop")
|
||||
assert.MatchSelectedLine(Contains("drop"))
|
||||
|
||||
input.PreviousItem()
|
||||
input.PressKeys(keys.Commits.SquashDown)
|
||||
assert.SelectedLineContains("squash")
|
||||
assert.MatchSelectedLine(Contains("squash"))
|
||||
|
||||
input.ContinueRebase()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,74 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/generics/set"
|
||||
"github.com/jesseduffield/generics/slices"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests/branch"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests/commit"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests/custom_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests/interactive_rebase"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
// Here is where we lists the actual tests that will run. When you create a new test,
|
||||
// be sure to add it to this list.
|
||||
|
||||
var Tests = []*components.IntegrationTest{
|
||||
var tests = []*components.IntegrationTest{
|
||||
commit.Commit,
|
||||
commit.NewBranch,
|
||||
branch.Suggestions,
|
||||
interactive_rebase.One,
|
||||
custom_commands.Basic,
|
||||
custom_commands.MultiplePrompts,
|
||||
custom_commands.MenuFromCommand,
|
||||
}
|
||||
|
||||
func GetTests() []*components.IntegrationTest {
|
||||
// first we ensure that each test in this directory has actually been added to the above list.
|
||||
testCount := 0
|
||||
|
||||
testNamesSet := set.NewFromSlice(slices.Map(
|
||||
tests,
|
||||
func(test *components.IntegrationTest) string {
|
||||
return test.Name()
|
||||
},
|
||||
))
|
||||
|
||||
missingTestNames := []string{}
|
||||
|
||||
if err := filepath.Walk(filepath.Join(utils.GetLazygitRootDirectory(), "pkg/integration/tests"), func(path string, info os.FileInfo, err error) error {
|
||||
if !info.IsDir() && strings.HasSuffix(path, ".go") {
|
||||
// ignoring this current file
|
||||
if filepath.Base(path) == "tests.go" {
|
||||
return nil
|
||||
}
|
||||
|
||||
nameFromPath := components.TestNameFromFilePath(path)
|
||||
if !testNamesSet.Includes(nameFromPath) {
|
||||
missingTestNames = append(missingTestNames, nameFromPath)
|
||||
}
|
||||
testCount++
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(fmt.Sprintf("failed to walk tests: %v", err))
|
||||
}
|
||||
|
||||
if len(missingTestNames) > 0 {
|
||||
panic(fmt.Sprintf("The following tests are missing from the list of tests: %s. You need to add them to `pkg/integration/tests/tests.go`.", strings.Join(missingTestNames, ", ")))
|
||||
}
|
||||
|
||||
if testCount > len(tests) {
|
||||
panic("you have not added all of the tests to the tests list in `pkg/integration/tests/tests.go`")
|
||||
} else if testCount < len(tests) {
|
||||
panic("There are more tests in `pkg/integration/tests/tests.go` than there are test files in the tests directory. Ensure that you only have one test per file and you haven't included the same test twice in the tests list.")
|
||||
}
|
||||
|
||||
return tests
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
|
|
@ -28,4 +29,9 @@ type GuiDriver interface {
|
|||
// logs in the actual UI (in the commands panel)
|
||||
LogUI(message string)
|
||||
CheckedOutRef() *models.Branch
|
||||
// the view that appears to the right of the side panel
|
||||
MainView() *gocui.View
|
||||
// the other view that sometimes appears to the right of the side panel
|
||||
// e.g. when we're showing both staged and unstaged changes
|
||||
SecondaryView() *gocui.View
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
disableStartupPopups: true
|
||||
customCommands:
|
||||
- key : 'N'
|
||||
description: 'Add file'
|
||||
command: "echo {{index .PromptResponses 0}} > {{index .PromptResponses 1}}"
|
||||
context: 'files'
|
||||
prompts:
|
||||
- type: 'input'
|
||||
title: 'File name:'
|
||||
- type: 'input'
|
||||
title: 'File content:'
|
||||
gui:
|
||||
theme:
|
||||
activeBorderColor:
|
||||
- green
|
||||
- bold
|
||||
SelectedRangeBgcolor:
|
||||
- reverse
|
||||
|
|
@ -1 +0,0 @@
|
|||
test
|
||||
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
0000000000000000000000000000000000000000 15bdb2c31c825116ad5af06ee25517d90b24f13b CI <CI@example.com> 1617684452 +1000 commit (initial): test
|
||||
|
|
@ -1 +0,0 @@
|
|||
0000000000000000000000000000000000000000 15bdb2c31c825116ad5af06ee25517d90b24f13b CI <CI@example.com> 1617684452 +1000 commit (initial): test
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
15bdb2c31c825116ad5af06ee25517d90b24f13b
|
||||
|
|
@ -1 +0,0 @@
|
|||
myfile
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"KeyEvents":[{"Timestamp":837,"Mod":0,"Key":256,"Ch":78},{"Timestamp":1622,"Mod":0,"Key":256,"Ch":109},{"Timestamp":1798,"Mod":0,"Key":256,"Ch":121},{"Timestamp":1918,"Mod":0,"Key":256,"Ch":102},{"Timestamp":2006,"Mod":0,"Key":256,"Ch":105},{"Timestamp":2078,"Mod":0,"Key":256,"Ch":108},{"Timestamp":2174,"Mod":0,"Key":256,"Ch":101},{"Timestamp":2431,"Mod":0,"Key":13,"Ch":13},{"Timestamp":3246,"Mod":0,"Key":256,"Ch":98},{"Timestamp":3294,"Mod":0,"Key":256,"Ch":108},{"Timestamp":3398,"Mod":0,"Key":256,"Ch":97},{"Timestamp":3462,"Mod":0,"Key":256,"Ch":104},{"Timestamp":3735,"Mod":0,"Key":13,"Ch":13},{"Timestamp":4206,"Mod":0,"Key":256,"Ch":32},{"Timestamp":4421,"Mod":0,"Key":256,"Ch":99},{"Timestamp":4646,"Mod":0,"Key":256,"Ch":116},{"Timestamp":4726,"Mod":0,"Key":256,"Ch":101},{"Timestamp":4886,"Mod":0,"Key":256,"Ch":115},{"Timestamp":4918,"Mod":0,"Key":256,"Ch":116},{"Timestamp":5190,"Mod":0,"Key":13,"Ch":13},{"Timestamp":5550,"Mod":0,"Key":256,"Ch":113}],"ResizeEvents":[{"Timestamp":0,"Width":272,"Height":74}]}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
cd $1
|
||||
|
||||
git init
|
||||
|
||||
git config user.email "CI@example.com"
|
||||
git config user.name "CI"
|
||||
|
|
@ -1 +0,0 @@
|
|||
{ "description": "Invoke a custom command that creates a file, and then stage and commit that file", "speed": 5 }
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
disableStartupPopups: true
|
||||
customCommands:
|
||||
- key: 'N'
|
||||
description: 'Add file'
|
||||
context: 'localBranches'
|
||||
command: 'echo "{{index .PromptResponses 0}} {{index .PromptResponses 1}} {{index .PromptResponses 2}} {{ .SelectedLocalBranch.Name }}" > output.txt'
|
||||
loadingText: 'Running custom command...'
|
||||
prompts:
|
||||
- type: 'menuFromCommand'
|
||||
title: 'Title'
|
||||
command: 'git log --oneline --pretty=%B'
|
||||
filter: '(?P<commit_message>.*)'
|
||||
valueFormat: '{{ .commit_message }}'
|
||||
labelFormat: '{{ .commit_message | yellow }}'
|
||||
- type: 'input'
|
||||
title: 'Description'
|
||||
initialValue: "{{ if .SelectedLocalBranch.Name }}Branch: #{{ .SelectedLocalBranch.Name }}{{end}}"
|
||||
- type: 'menu'
|
||||
title: 'yes or no'
|
||||
options:
|
||||
- name: 'no'
|
||||
value: 'false'
|
||||
- name: 'yes'
|
||||
value: 'true'
|
||||
gui:
|
||||
theme:
|
||||
activeBorderColor:
|
||||
- green
|
||||
- bold
|
||||
SelectedRangeBgcolor:
|
||||
- reverse
|
||||
|
|
@ -1 +0,0 @@
|
|||
test
|
||||
Binary file not shown.
|
|
@ -1,5 +0,0 @@
|
|||
0000000000000000000000000000000000000000 ab38b1ca116f77648925d952e731f419db360cdb CI <CI@example.com> 1642201096 +1100 commit (initial): myfile1
|
||||
ab38b1ca116f77648925d952e731f419db360cdb 4fdfedfd9d406506be8b02f5b863dbc08d43cc9f CI <CI@example.com> 1642201096 +1100 commit: myfile2
|
||||
4fdfedfd9d406506be8b02f5b863dbc08d43cc9f 7dd93a4be3d27d40fbe791d6d77e0d2fedc4d785 CI <CI@example.com> 1642201096 +1100 commit: myfile3
|
||||
7dd93a4be3d27d40fbe791d6d77e0d2fedc4d785 f708d3e3819470a69f6c8562ff1e68eef02f8cac CI <CI@example.com> 1642201096 +1100 commit: myfile4
|
||||
f708d3e3819470a69f6c8562ff1e68eef02f8cac 5428838691c97ac192c8b8e1c3f573d8541a94b6 CI <CI@example.com> 1642201104 +1100 commit: test
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
0000000000000000000000000000000000000000 ab38b1ca116f77648925d952e731f419db360cdb CI <CI@example.com> 1642201096 +1100 commit (initial): myfile1
|
||||
ab38b1ca116f77648925d952e731f419db360cdb 4fdfedfd9d406506be8b02f5b863dbc08d43cc9f CI <CI@example.com> 1642201096 +1100 commit: myfile2
|
||||
4fdfedfd9d406506be8b02f5b863dbc08d43cc9f 7dd93a4be3d27d40fbe791d6d77e0d2fedc4d785 CI <CI@example.com> 1642201096 +1100 commit: myfile3
|
||||
7dd93a4be3d27d40fbe791d6d77e0d2fedc4d785 f708d3e3819470a69f6c8562ff1e68eef02f8cac CI <CI@example.com> 1642201096 +1100 commit: myfile4
|
||||
f708d3e3819470a69f6c8562ff1e68eef02f8cac 5428838691c97ac192c8b8e1c3f573d8541a94b6 CI <CI@example.com> 1642201104 +1100 commit: test
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,2 +0,0 @@
|
|||
x<01>ÍA
|
||||
ƒ0@Ñ®sŠÙÊL:#)¸ò1™PÁ!")ØÛ×#tûyðS5[Ë¥íª€*©`”¹ë5df¥ 9<><39>T:žùž…KLïâ§½ëãÏqzém[õ–ª
@ÂÞ#a/p%Btg='MÿäξeY•Ü.,,·
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,2 +0,0 @@
|
|||
x<01>ЮA
|
||||
Т0@Qз9Eі<45>Ь$<24>I"BW=F<><46>`СиR"шээм~от<D0BE>ЕЕЅ[LtъЛЊu<D08A>1№<03>*в<>ЬaШ>АFvфCЩ!ЁйђЎЏnЃHђ<48>fѕтЂдYcBa<42>QA\U)$q&Пћcнэ8йы8нѕ<D0BD>лідKYлЭ"<22>s<EFBFBD><73>и<EFBFBD>ЬQ<D0AC>ЉЎrгОuy*<2A>3н9<D0BD>
|
||||
|
|
@ -1 +0,0 @@
|
|||
5428838691c97ac192c8b8e1c3f573d8541a94b6
|
||||
|
|
@ -1 +0,0 @@
|
|||
test1
|
||||
|
|
@ -1 +0,0 @@
|
|||
test2
|
||||
|
|
@ -1 +0,0 @@
|
|||
test3
|
||||
|
|
@ -1 +0,0 @@
|
|||
test4
|
||||
|
|
@ -1 +0,0 @@
|
|||
myfile2 Branch: #master haha true master
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"KeyEvents":[{"Timestamp":623,"Mod":0,"Key":259,"Ch":0},{"Timestamp":1369,"Mod":0,"Key":256,"Ch":78},{"Timestamp":1904,"Mod":0,"Key":258,"Ch":0},{"Timestamp":2033,"Mod":0,"Key":258,"Ch":0},{"Timestamp":2328,"Mod":0,"Key":13,"Ch":13},{"Timestamp":2848,"Mod":0,"Key":256,"Ch":32},{"Timestamp":3296,"Mod":0,"Key":256,"Ch":97},{"Timestamp":3616,"Mod":0,"Key":127,"Ch":127},{"Timestamp":3824,"Mod":0,"Key":256,"Ch":104},{"Timestamp":3879,"Mod":0,"Key":256,"Ch":97},{"Timestamp":3927,"Mod":0,"Key":256,"Ch":104},{"Timestamp":4000,"Mod":0,"Key":256,"Ch":97},{"Timestamp":4239,"Mod":0,"Key":13,"Ch":13},{"Timestamp":4809,"Mod":0,"Key":258,"Ch":0},{"Timestamp":5024,"Mod":0,"Key":13,"Ch":13},{"Timestamp":5824,"Mod":0,"Key":260,"Ch":0},{"Timestamp":6079,"Mod":0,"Key":256,"Ch":32},{"Timestamp":6376,"Mod":0,"Key":256,"Ch":99},{"Timestamp":6591,"Mod":0,"Key":256,"Ch":116},{"Timestamp":6640,"Mod":0,"Key":256,"Ch":101},{"Timestamp":6816,"Mod":0,"Key":256,"Ch":115},{"Timestamp":6856,"Mod":0,"Key":256,"Ch":116},{"Timestamp":7136,"Mod":0,"Key":13,"Ch":13},{"Timestamp":7487,"Mod":0,"Key":256,"Ch":113}],"ResizeEvents":[{"Timestamp":0,"Width":272,"Height":36}]}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
cd $1
|
||||
|
||||
git init
|
||||
|
||||
git config user.email "CI@example.com"
|
||||
git config user.name "CI"
|
||||
|
||||
echo test1 > myfile1
|
||||
git add .
|
||||
git commit -am "myfile1"
|
||||
echo test2 > myfile2
|
||||
git add .
|
||||
git commit -am "myfile2"
|
||||
echo test3 > myfile3
|
||||
git add .
|
||||
git commit -am "myfile3"
|
||||
echo test4 > myfile4
|
||||
git add .
|
||||
git commit -am "myfile4"
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"description": "Invoke a custom command that creates a file, and then stage and commit that file. In this case we're using a more customised flow",
|
||||
"speed": 5
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
blah
|
||||
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
0000000000000000000000000000000000000000 fe47c0cf0521f8864cd0531ddf35d2f741c14abf CI <CI@example.com> 1660476851 +1000 commit (initial): blah
|
||||
|
|
@ -0,0 +1 @@
|
|||
0000000000000000000000000000000000000000 fe47c0cf0521f8864cd0531ddf35d2f741c14abf CI <CI@example.com> 1660476851 +1000 commit (initial): blah
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
fe47c0cf0521f8864cd0531ddf35d2f741c14abf
|
||||
|
|
@ -0,0 +1 @@
|
|||
baz
|
||||
|
|
@ -0,0 +1 @@
|
|||
ref: refs/heads/feature/foo
|
||||
Binary file not shown.
|
|
@ -0,0 +1,4 @@
|
|||
0000000000000000000000000000000000000000 d50975554a574b9c66e109927fdb4edfb6bbadb3 CI <CI@example.com> 1660476303 +1000 commit (initial): foo
|
||||
d50975554a574b9c66e109927fdb4edfb6bbadb3 af550d3777f20bf024ad55c9c796e7e85ef32ccb CI <CI@example.com> 1660476303 +1000 commit: bar
|
||||
af550d3777f20bf024ad55c9c796e7e85ef32ccb 16919871d6b442beac07e1573c557ca433cff356 CI <CI@example.com> 1660476303 +1000 commit: baz
|
||||
16919871d6b442beac07e1573c557ca433cff356 16919871d6b442beac07e1573c557ca433cff356 CI <CI@example.com> 1660476303 +1000 checkout: moving from master to feature/foo
|
||||
|
|
@ -0,0 +1 @@
|
|||
0000000000000000000000000000000000000000 16919871d6b442beac07e1573c557ca433cff356 CI <CI@example.com> 1660476303 +1000 branch: Created from HEAD
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
0000000000000000000000000000000000000000 d50975554a574b9c66e109927fdb4edfb6bbadb3 CI <CI@example.com> 1660476303 +1000 commit (initial): foo
|
||||
d50975554a574b9c66e109927fdb4edfb6bbadb3 af550d3777f20bf024ad55c9c796e7e85ef32ccb CI <CI@example.com> 1660476303 +1000 commit: bar
|
||||
af550d3777f20bf024ad55c9c796e7e85ef32ccb 16919871d6b442beac07e1573c557ca433cff356 CI <CI@example.com> 1660476303 +1000 commit: baz
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
x<01>ֽA
|
||||
ֲ0@Q׳9ֵל™₪׃1)BW=F&<26> `˜R"פרצn?~±ײ<C2B1><…K<E280A6>U<EFBFBD>$†q-L¡«₪<C2AB><E282AA>:’װ¸r
|
||||
1VQ¥„הע·¿l‡y<EFBFBD>ַ¼<ץָm<D6B8>טX›ְ3#<23>yְ®<11>YֿI׳?¹«fמ~<7E>+T
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue