From a985ccdf4622d86a55ab987c9730197abdd5ebb7 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Wed, 26 Jul 2023 19:38:08 -0400 Subject: [PATCH] feat: test ssh ui output Still wip wip feat(tests): run against ssh ui --- cmd/soft/browse/browse.go | 3 +- cmd/soft/main.go | 7 ++++ pkg/ssh/session.go | 3 +- pkg/ui/common/common.go | 5 ++- testscript/script_test.go | 64 +++++++++++++++++++++++++++++ testscript/testdata/repo-blob.txtar | 2 +- testscript/testdata/ui-home.txtar | 53 ++++++++++++++++++++++++ 7 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 testscript/testdata/ui-home.txtar diff --git a/cmd/soft/browse/browse.go b/cmd/soft/browse/browse.go index ff1a1d061..c430630cf 100644 --- a/cmd/soft/browse/browse.go +++ b/cmd/soft/browse/browse.go @@ -13,7 +13,6 @@ import ( "github.com/charmbracelet/soft-serve/pkg/ui/common" "github.com/charmbracelet/soft-serve/pkg/ui/components/footer" "github.com/charmbracelet/soft-serve/pkg/ui/pages/repo" - "github.com/muesli/termenv" "github.com/spf13/cobra" ) @@ -40,7 +39,7 @@ var Command = &cobra.Command{ // Bubble Tea uses Termenv default output so we have to use the same // thing here. - output := termenv.DefaultOutput() + output := lipgloss.DefaultRenderer() ctx := cmd.Context() c := common.NewCommon(ctx, output, 0, 0) c.HideCloneCmd = true diff --git a/cmd/soft/main.go b/cmd/soft/main.go index 8264abee8..9849e8a26 100644 --- a/cmd/soft/main.go +++ b/cmd/soft/main.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "runtime/debug" + "strconv" "github.com/charmbracelet/log" "github.com/charmbracelet/soft-serve/cmd/soft/admin" @@ -13,9 +14,11 @@ import ( "github.com/charmbracelet/soft-serve/cmd/soft/serve" "github.com/charmbracelet/soft-serve/pkg/config" logr "github.com/charmbracelet/soft-serve/pkg/log" + "github.com/charmbracelet/soft-serve/pkg/ui/common" "github.com/charmbracelet/soft-serve/pkg/version" mcobra "github.com/muesli/mango-cobra" "github.com/muesli/roff" + "github.com/muesli/termenv" "github.com/spf13/cobra" "go.uber.org/automaxprocs/maxprocs" ) @@ -63,6 +66,10 @@ var ( ) func init() { + if noColor, _ := strconv.ParseBool(os.Getenv("SOFT_SERVE_NO_COLOR")); noColor { + common.DefaultColorProfile = termenv.Ascii + } + rootCmd.AddCommand( manCmd, serve.Command, diff --git a/pkg/ssh/session.go b/pkg/ssh/session.go index 5ccd9062b..99c8489ef 100644 --- a/pkg/ssh/session.go +++ b/pkg/ssh/session.go @@ -5,6 +5,7 @@ import ( "time" tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/soft-serve/pkg/access" "github.com/charmbracelet/soft-serve/pkg/backend" "github.com/charmbracelet/soft-serve/pkg/config" @@ -54,7 +55,7 @@ func SessionHandler(s ssh.Session) *tea.Program { } envs := &sessionEnv{s} - output := termenv.NewOutput(s, termenv.WithColorCache(true), termenv.WithEnvironment(envs)) + output := lipgloss.NewRenderer(s, termenv.WithColorCache(true), termenv.WithEnvironment(envs)) c := common.NewCommon(ctx, output, pty.Window.Width, pty.Window.Height) c.SetValue(common.ConfigKey, cfg) m := NewUI(c, initialRepo) diff --git a/pkg/ui/common/common.go b/pkg/ui/common/common.go index ceee1f58e..3c3eddd30 100644 --- a/pkg/ui/common/common.go +++ b/pkg/ui/common/common.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/log" "github.com/charmbracelet/soft-serve/git" "github.com/charmbracelet/soft-serve/pkg/backend" @@ -38,7 +39,7 @@ type Common struct { } // NewCommon returns a new Common struct. -func NewCommon(ctx context.Context, out *termenv.Output, width, height int) Common { +func NewCommon(ctx context.Context, out *lipgloss.Renderer, width, height int) Common { if ctx == nil { ctx = context.TODO() } @@ -46,7 +47,7 @@ func NewCommon(ctx context.Context, out *termenv.Output, width, height int) Comm ctx: ctx, Width: width, Height: height, - Output: out, + Output: out.Output(), Styles: styles.DefaultStyles(), KeyMap: keymap.DefaultKeyMap(), Zone: zone.New(), diff --git a/testscript/script_test.go b/testscript/script_test.go index f7dd22eec..0b1b619e2 100644 --- a/testscript/script_test.go +++ b/testscript/script_test.go @@ -15,6 +15,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strconv" "strings" "testing" "time" @@ -92,6 +93,8 @@ func TestScript(t *testing.T) { "new-webhook": cmdNewWebhook, "waitforserver": cmdWaitforserver, "stopserver": cmdStopserver, + "ui": cmdUI(admin1.Signer()), + "uui": cmdUI(user1.Signer()), }, Setup: func(e *testscript.Env) error { // Add binPath to PATH @@ -120,6 +123,9 @@ func TestScript(t *testing.T) { // This is used to set up test specific configuration and http endpoints e.Setenv("SOFT_SERVE_TESTRUN", "1") + // This will disable the default lipgloss renderer colors + e.Setenv("SOFT_SERVE_NO_COLOR", "1") + // Soft Serve debug environment variables for _, env := range []string{ "SOFT_SERVE_DEBUG", @@ -199,6 +205,64 @@ func cmdSoft(key ssh.Signer) func(ts *testscript.TestScript, neg bool, args []st } } +func cmdUI(key ssh.Signer) func(ts *testscript.TestScript, neg bool, args []string) { + return func(ts *testscript.TestScript, neg bool, args []string) { + if len(args) < 1 { + ts.Fatalf("usage: ui ") + return + } + + cli, err := ssh.Dial( + "tcp", + net.JoinHostPort("localhost", ts.Getenv("SSH_PORT")), + &ssh.ClientConfig{ + User: "git", + Auth: []ssh.AuthMethod{ssh.PublicKeys(key)}, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + }, + ) + check(ts, err, neg) + defer cli.Close() + + sess, err := cli.NewSession() + check(ts, err, neg) + defer sess.Close() + + // XXX: this is a hack to make the UI tests work + // cmp command always complains about an extra newline + // in the output + defer ts.Stdout().Write([]byte("\n")) + + sess.Stdout = ts.Stdout() + sess.Stderr = ts.Stderr() + + stdin, err := sess.StdinPipe() + check(ts, err, neg) + + in, err := strconv.Unquote(args[0]) + check(ts, err, neg) + reader := strings.NewReader(in) + go func() { + defer stdin.Close() + for { + r, _, err := reader.ReadRune() + if err == io.EOF { + break + } + check(ts, err, neg) + stdin.Write([]byte(string(r))) // nolint: errcheck + + // Wait for the UI to process the input + time.Sleep(100 * time.Millisecond) + } + }() + + err = sess.RequestPty("dumb", 40, 80, ssh.TerminalModes{}) + check(ts, err, neg) + check(ts, sess.Run(""), neg) + } +} + // P.S. Windows sucks! func cmdDos2Unix(ts *testscript.TestScript, neg bool, args []string) { if neg { diff --git a/testscript/testdata/repo-blob.txtar b/testscript/testdata/repo-blob.txtar index 040160b17..e2712acfe 100644 --- a/testscript/testdata/repo-blob.txtar +++ b/testscript/testdata/repo-blob.txtar @@ -54,6 +54,6 @@ stderr 'revision does not exist' -- blob1.txt -- # Hello\n\nwelcome -- blob2.txt -- - 1 │ package main\nconst foo = 2\n + 1 │ package main\nconst foo = 2\n -- blob3.txt -- 1 │ //#include diff --git a/testscript/testdata/ui-home.txtar b/testscript/testdata/ui-home.txtar new file mode 100644 index 000000000..e7203fb0d --- /dev/null +++ b/testscript/testdata/ui-home.txtar @@ -0,0 +1,53 @@ +# vi: set ft=conf + +# start soft serve +exec soft serve & +# wait for server to start +waitforserver + +# test repositories tab +ui '" q"' +cp stdout home.txt +grep 'Test Soft Serve' home.txt +grep '• Repositories' home.txt +grep 'No items found' home.txt + +# test about tab +ui '"\t q"' +cp stdout about.txt +grep 'Create a `.soft-serve` repository and add a `README.md` file' about.txt + +# add a new repo +soft repo create .soft-serve -n 'Config' -d '"Test Soft Serve"' +soft repo description .soft-serve +stdout 'Test Soft Serve' +soft repo project-name .soft-serve +stdout 'Config' + +# clone repo +git clone ssh://localhost:$SSH_PORT/.soft-serve config + +# create readme file +mkfile ./config/README.md '# Hello World\nTest Soft Serve' +git -C config add -A +git -C config commit -m 'Initial commit' +git -C config push origin HEAD + +# test repositories tab +ui '" q"' +cp stdout home2.txt +grep 'Config' home2.txt +grep 'Test Soft Serve' home2.txt +grep 'git clone ssh://localhost:.*/.soft-serve' home2.txt + +# test about tab +ui '"\t q"' +cp stdout about2.txt +grep '• About' about2.txt +grep 'Hello World' about2.txt +grep 'Test Soft Serve' about2.txt + +# stop the server +[windows] stopserver +[windows] ! stderr . +