2021-04-02 01:22:00 +02:00
package main
import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"github.com/jesseduffield/gocui"
2021-11-01 00:35:54 +02:00
"github.com/jesseduffield/lazygit/pkg/gui"
2021-07-27 15:00:37 +02:00
"github.com/jesseduffield/lazygit/pkg/gui/style"
2021-04-05 14:18:36 +02:00
"github.com/jesseduffield/lazygit/pkg/integration"
2022-08-12 01:24:39 +02:00
"github.com/jesseduffield/lazygit/pkg/integration/components"
2021-04-02 01:22:00 +02:00
"github.com/jesseduffield/lazygit/pkg/secureexec"
)
2022-08-11 13:17:01 +02:00
// this program lets you manage integration tests in a TUI. See pkg/integration/README.md for more info.
2021-04-06 01:02:01 +02:00
2021-04-02 01:22:00 +02:00
type App struct {
2022-08-12 01:19:39 +02:00
tests [ ] * components . IntegrationTest
2022-08-09 13:27:12 +02:00
itemIdx int
testDir string
filtering bool
g * gocui . Gui
2021-04-02 01:22:00 +02:00
}
2022-08-12 01:19:39 +02:00
func ( app * App ) getCurrentTest ( ) * components . IntegrationTest {
2021-04-02 01:22:00 +02:00
if len ( app . tests ) > 0 {
return app . tests [ app . itemIdx ]
}
return nil
}
func ( app * App ) loadTests ( ) {
2022-08-09 13:27:12 +02:00
app . tests = integration . Tests
2021-04-02 01:22:00 +02:00
if app . itemIdx > len ( app . tests ) - 1 {
app . itemIdx = len ( app . tests ) - 1
}
}
func main ( ) {
2021-04-05 14:18:36 +02:00
rootDir := integration . GetRootDirectory ( )
2021-04-02 01:22:00 +02:00
testDir := filepath . Join ( rootDir , "test" , "integration" )
app := & App { testDir : testDir }
app . loadTests ( )
2021-11-01 00:35:54 +02:00
g , err := gocui . NewGui ( gocui . OutputTrue , false , gocui . NORMAL , false , gui . RuneReplacements )
2021-04-05 02:20:02 +02:00
if err != nil {
log . Panicln ( err )
}
2021-04-02 01:22:00 +02:00
2021-04-05 02:20:02 +02:00
g . Cursor = false
2021-04-02 01:22:00 +02:00
2021-04-05 02:20:02 +02:00
app . g = g
2021-04-02 01:22:00 +02:00
2021-04-05 02:20:02 +02:00
g . SetManagerFunc ( app . layout )
2021-04-02 01:22:00 +02:00
2022-06-13 03:01:26 +02:00
if err := g . SetKeybinding ( "list" , gocui . KeyArrowUp , gocui . ModNone , func ( * gocui . Gui , * gocui . View ) error {
2021-04-05 02:20:02 +02:00
if app . itemIdx > 0 {
app . itemIdx --
2021-04-02 01:22:00 +02:00
}
2021-10-30 09:17:32 +02:00
listView , err := g . View ( "list" )
if err != nil {
return err
}
listView . FocusPoint ( 0 , app . itemIdx )
2021-04-05 02:20:02 +02:00
return nil
} ) ; err != nil {
log . Panicln ( err )
}
2021-04-02 01:22:00 +02:00
2022-06-13 03:01:26 +02:00
if err := g . SetKeybinding ( "list" , gocui . KeyCtrlC , gocui . ModNone , quit ) ; err != nil {
2021-04-05 02:20:02 +02:00
log . Panicln ( err )
}
2021-04-02 01:22:00 +02:00
2022-06-13 03:01:26 +02:00
if err := g . SetKeybinding ( "list" , 'q' , gocui . ModNone , quit ) ; err != nil {
2021-04-05 02:20:02 +02:00
log . Panicln ( err )
}
2022-06-13 03:01:26 +02:00
if err := g . SetKeybinding ( "list" , 's' , gocui . ModNone , func ( * gocui . Gui , * gocui . View ) error {
2022-01-15 11:24:19 +02:00
currentTest := app . getCurrentTest ( )
if currentTest == nil {
return nil
}
2022-08-09 13:27:12 +02:00
cmd := secureexec . Command ( "sh" , "-c" , fmt . Sprintf ( "INCLUDE_SKIPPED=true MODE=sandbox go run pkg/integration/runner/main.go %s" , currentTest . Name ( ) ) )
2021-04-05 02:20:02 +02:00
app . runSubprocess ( cmd )
2021-04-02 01:22:00 +02:00
2021-04-05 02:20:02 +02:00
return nil
} ) ; err != nil {
log . Panicln ( err )
}
2021-04-02 01:22:00 +02:00
2022-06-13 03:01:26 +02:00
if err := g . SetKeybinding ( "list" , gocui . KeyEnter , gocui . ModNone , func ( * gocui . Gui , * gocui . View ) error {
2021-04-05 02:20:02 +02:00
currentTest := app . getCurrentTest ( )
if currentTest == nil {
return nil
2021-04-02 01:22:00 +02:00
}
2022-08-09 13:27:12 +02:00
cmd := secureexec . Command ( "sh" , "-c" , fmt . Sprintf ( "INCLUDE_SKIPPED=true go run pkg/integration/runner/main.go %s" , currentTest . Name ( ) ) )
2021-04-05 12:49:32 +02:00
app . runSubprocess ( cmd )
return nil
} ) ; err != nil {
log . Panicln ( err )
}
2022-06-13 03:01:26 +02:00
if err := g . SetKeybinding ( "list" , 't' , gocui . ModNone , func ( * gocui . Gui , * gocui . View ) error {
2022-01-26 00:07:56 +02:00
currentTest := app . getCurrentTest ( )
if currentTest == nil {
return nil
}
2022-08-09 13:27:12 +02:00
cmd := secureexec . Command ( "sh" , "-c" , fmt . Sprintf ( "INCLUDE_SKIPPED=true KEY_PRESS_DELAY=200 go run pkg/integration/runner/main.go %s" , currentTest . Name ( ) ) )
2022-01-26 00:07:56 +02:00
app . runSubprocess ( cmd )
return nil
} ) ; err != nil {
log . Panicln ( err )
}
2022-06-13 03:01:26 +02:00
if err := g . SetKeybinding ( "list" , 'o' , gocui . ModNone , func ( * gocui . Gui , * gocui . View ) error {
2021-04-05 02:20:02 +02:00
currentTest := app . getCurrentTest ( )
if currentTest == nil {
return nil
2021-04-02 01:22:00 +02:00
}
2022-08-09 13:27:12 +02:00
cmd := secureexec . Command ( "sh" , "-c" , fmt . Sprintf ( "code -r pkg/integration/tests/%s" , currentTest . Name ( ) ) )
2021-04-05 02:20:02 +02:00
if err := cmd . Run ( ) ; err != nil {
return err
}
2021-04-02 01:22:00 +02:00
2021-04-05 02:20:02 +02:00
return nil
} ) ; err != nil {
log . Panicln ( err )
}
2021-04-02 01:22:00 +02:00
2022-08-09 13:27:12 +02:00
if err := g . SetKeybinding ( "list" , 'O' , gocui . ModNone , func ( * gocui . Gui , * gocui . View ) error {
2021-04-05 02:20:02 +02:00
currentTest := app . getCurrentTest ( )
if currentTest == nil {
2021-04-02 01:22:00 +02:00
return nil
}
2022-08-09 13:27:12 +02:00
cmd := secureexec . Command ( "sh" , "-c" , fmt . Sprintf ( "code test/integration_new/%s" , currentTest . Name ( ) ) )
2021-04-05 02:20:02 +02:00
if err := cmd . Run ( ) ; err != nil {
return err
}
2021-04-02 01:22:00 +02:00
2021-04-05 02:20:02 +02:00
return nil
} ) ; err != nil {
log . Panicln ( err )
}
2021-04-02 01:22:00 +02:00
2022-08-09 13:27:12 +02:00
if err := g . SetKeybinding ( "list" , '/' , gocui . ModNone , func ( * gocui . Gui , * gocui . View ) error {
app . filtering = true
2021-04-05 02:20:02 +02:00
if _ , err := g . SetCurrentView ( "editor" ) ; err != nil {
return err
}
editorView , err := g . View ( "editor" )
if err != nil {
return err
}
editorView . Clear ( )
2021-04-02 01:22:00 +02:00
2021-04-05 02:20:02 +02:00
return nil
} ) ; err != nil {
log . Panicln ( err )
}
2021-04-02 01:22:00 +02:00
2022-08-09 13:27:12 +02:00
// not using the editor yet, but will use it to help filter the list
2022-06-13 03:01:26 +02:00
if err := g . SetKeybinding ( "editor" , gocui . KeyEsc , gocui . ModNone , func ( * gocui . Gui , * gocui . View ) error {
2022-08-09 13:27:12 +02:00
app . filtering = false
2021-04-05 02:20:02 +02:00
if _ , err := g . SetCurrentView ( "list" ) ; err != nil {
return err
2021-04-02 01:22:00 +02:00
}
2021-04-05 02:20:02 +02:00
return nil
} ) ; err != nil {
log . Panicln ( err )
}
2021-04-02 01:22:00 +02:00
2021-04-05 02:20:02 +02:00
err = g . MainLoop ( )
g . Close ( )
2022-01-15 06:18:16 +02:00
switch err {
case gocui . ErrQuit :
return
default :
log . Panicln ( err )
2021-04-05 02:20:02 +02:00
}
}
2021-04-02 01:22:00 +02:00
2021-04-05 02:20:02 +02:00
func ( app * App ) runSubprocess ( cmd * exec . Cmd ) {
2021-04-05 04:19:45 +02:00
if err := gocui . Screen . Suspend ( ) ; err != nil {
panic ( err )
}
2021-04-05 02:20:02 +02:00
cmd . Stdin = os . Stdin
cmd . Stderr = os . Stderr
cmd . Stdout = os . Stdout
if err := cmd . Run ( ) ; err != nil {
log . Println ( err . Error ( ) )
2021-04-02 01:22:00 +02:00
}
2021-04-05 02:20:02 +02:00
cmd . Stdin = nil
cmd . Stderr = nil
cmd . Stdout = nil
2021-07-27 15:00:37 +02:00
fmt . Fprintf ( os . Stdout , "\n%s" , style . FgGreen . Sprint ( "press enter to return" ) )
2021-04-05 02:20:02 +02:00
fmt . Scanln ( ) // wait for enter press
2021-04-05 04:19:45 +02:00
if err := gocui . Screen . Resume ( ) ; err != nil {
panic ( err )
}
2021-04-02 01:22:00 +02:00
}
func ( app * App ) layout ( g * gocui . Gui ) error {
maxX , maxY := g . Size ( )
descriptionViewHeight := 7
keybindingsViewHeight := 3
editorViewHeight := 3
2022-08-09 13:27:12 +02:00
if ! app . filtering {
2021-04-02 01:22:00 +02:00
editorViewHeight = 0
} else {
descriptionViewHeight = 0
keybindingsViewHeight = 0
}
2022-08-09 13:27:12 +02:00
g . Cursor = app . filtering
2021-04-02 01:22:00 +02:00
g . FgColor = gocui . ColorGreen
listView , err := g . SetView ( "list" , 0 , 0 , maxX - 1 , maxY - descriptionViewHeight - keybindingsViewHeight - editorViewHeight - 1 , 0 )
if err != nil {
if err . Error ( ) != "unknown view" {
return err
}
listView . Highlight = true
listView . Clear ( )
for _ , test := range app . tests {
2022-08-09 13:27:12 +02:00
fmt . Fprintln ( listView , test . Name ( ) )
2021-04-02 01:22:00 +02:00
}
listView . Title = "Tests"
listView . FgColor = gocui . ColorDefault
if _ , err := g . SetCurrentView ( "list" ) ; err != nil {
return err
}
}
descriptionView , err := g . SetViewBeneath ( "description" , "list" , descriptionViewHeight )
if err != nil {
if err . Error ( ) != "unknown view" {
return err
}
descriptionView . Title = "Test description"
descriptionView . Wrap = true
descriptionView . FgColor = gocui . ColorDefault
}
keybindingsView , err := g . SetViewBeneath ( "keybindings" , "description" , keybindingsViewHeight )
if err != nil {
if err . Error ( ) != "unknown view" {
return err
}
keybindingsView . Title = "Keybindings"
keybindingsView . Wrap = true
keybindingsView . FgColor = gocui . ColorDefault
2022-08-09 13:27:12 +02:00
fmt . Fprintln ( keybindingsView , "up/down: navigate, enter: run test, t: run test slow, s: sandbox, o: open test file, shift+o: open test snapshot directory, forward-slash: filter" )
2021-04-02 01:22:00 +02:00
}
editorView , err := g . SetViewBeneath ( "editor" , "keybindings" , editorViewHeight )
if err != nil {
if err . Error ( ) != "unknown view" {
return err
}
2022-08-09 13:27:12 +02:00
editorView . Title = "Filter"
2021-04-02 01:22:00 +02:00
editorView . FgColor = gocui . ColorDefault
editorView . Editable = true
}
currentTest := app . getCurrentTest ( )
if currentTest == nil {
return nil
}
descriptionView . Clear ( )
2022-08-09 13:27:12 +02:00
fmt . Fprint ( descriptionView , currentTest . Description ( ) )
2021-04-02 01:22:00 +02:00
2022-06-13 03:01:26 +02:00
if err := g . SetKeybinding ( "list" , gocui . KeyArrowDown , gocui . ModNone , func ( * gocui . Gui , * gocui . View ) error {
2021-04-02 01:22:00 +02:00
if app . itemIdx < len ( app . tests ) - 1 {
app . itemIdx ++
}
2021-10-30 09:17:32 +02:00
listView , err := g . View ( "list" )
if err != nil {
return err
}
listView . FocusPoint ( 0 , app . itemIdx )
2021-04-02 01:22:00 +02:00
return nil
} ) ; err != nil {
log . Panicln ( err )
}
return nil
}
func quit ( g * gocui . Gui , v * gocui . View ) error {
return gocui . ErrQuit
}