Skip to content

Commit

Permalink
some ui tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rusq committed Dec 11, 2022
1 parent 559aa7e commit 998175b
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 23 deletions.
10 changes: 7 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ require (
github.com/AlecAivazis/survey/v2 v2.3.6
github.com/MercuryEngineering/CookieMonster v0.0.0-20180304172713-1584578b3403
github.com/MichaelMure/go-term-markdown v0.1.4
github.com/denisbrodbeck/machineid v1.0.1
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2
github.com/fatih/color v1.13.0
github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0
github.com/go-playground/validator/v10 v10.4.1
github.com/goccy/go-yaml v1.9.6
github.com/golang/mock v1.6.0
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec
github.com/joho/godotenv v1.4.0
github.com/kr/pty v1.1.8
github.com/playwright-community/playwright-go v0.2000.1
github.com/rusq/dlog v1.3.3
github.com/rusq/encio v0.1.0
github.com/rusq/osenv/v2 v2.0.1
github.com/rusq/secure v0.0.4
github.com/rusq/tracer v1.0.1
github.com/schollz/progressbar/v3 v3.8.6
github.com/slack-go/slack v0.11.0
Expand All @@ -31,8 +33,10 @@ require (
require (
github.com/MichaelMure/go-term-text v0.3.1 // indirect
github.com/alecthomas/chroma v0.7.1 // indirect
github.com/creack/pty v1.1.17 // indirect
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denisbrodbeck/machineid v1.0.1 // indirect
github.com/disintegration/imaging v1.6.2 // indirect
github.com/dlclark/regexp2 v1.1.6 // indirect
github.com/eliukblau/pixterm/pkg/ansimage v0.0.0-20191210081756-9fb6cf8c2f75 // indirect
Expand All @@ -50,7 +54,7 @@ require (
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.3.1 // indirect
github.com/rusq/encio v0.1.0 // indirect
github.com/rusq/secure v0.0.4 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/image v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBo
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
Expand Down Expand Up @@ -67,6 +68,8 @@ github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwA
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE=
github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
Expand Down
6 changes: 4 additions & 2 deletions internal/app/ui/confirm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ package ui

import "github.com/AlecAivazis/survey/v2"

func Confirm(msg string, defavlt bool) (bool, error) {
func Confirm(msg string, defavlt bool, opt ...Option) (bool, error) {
var opts = defaultOpts().apply(opt...)

q := &survey.Confirm{
Message: msg,
Default: defavlt,
}

var b bool
if err := survey.AskOne(q, &b); err != nil {
if err := survey.AskOne(q, &b, opts.surveyOpts()...); err != nil {
return false, err
}
return b, nil
Expand Down
59 changes: 41 additions & 18 deletions internal/app/ui/filesystem.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,67 @@
package ui

import (
"errors"
"fmt"
"os"
"path/filepath"

"github.com/AlecAivazis/survey/v2"
)

func FileSelector(msg, descr string) (string, error) {
var q = &survey.Input{
Message: msg,
Suggest: func(partname string) []string {
// thanks to AlecAivazis the for great example of this.
files, _ := filepath.Glob(partname + "*")
return files
type fileSelectorOpt struct {
emptyFilename string // if set, the empty filename will be replaced to this value
}

func WithEmptyFilename(s string) Option {
return func(so *inputOptions) {
so.fileSelectorOpt.emptyFilename = s
}
}

func FileSelector(msg, descr string, opt ...Option) (string, error) {
var opts = defaultOpts().apply(opt...)

var q = []*survey.Question{
{
Name: "filename",
Prompt: &survey.Input{
Message: msg,
Suggest: func(partname string) []string {
files, _ := filepath.Glob(partname + "*")
return files
},
Help: descr,
},
Validate: func(ans interface{}) error {
if ans.(string) != "" || opts.emptyFilename != "" {
return nil
}
return errors.New("empty filename")
},
},
Help: descr,
}

var (
output string
)
var resp struct {
Filename string
}
for {
if err := survey.AskOne(q, &output); err != nil {
if err := survey.Ask(q, &resp, opts.surveyOpts()...); err != nil {
return "", err
}
if _, err := os.Stat(output); err != nil {
if resp.Filename == "" && opts.emptyFilename != "" {
resp.Filename = opts.emptyFilename
}
if _, err := os.Stat(resp.Filename); err != nil {
break
}
overwrite, err := Confirm(fmt.Sprintf("File %q exists. Overwrite?", output), false)
overwrite, err := Confirm(fmt.Sprintf("File %q exists. Overwrite?", resp.Filename), false, opt...)
if err != nil {
return "", err
}
if overwrite {
break
}
}
if output == "" {
output = "-"
}
return output, nil
return resp.Filename, nil
}
67 changes: 67 additions & 0 deletions internal/app/ui/filesystem_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package ui

import (
"testing"
"time"

"github.com/AlecAivazis/survey/v2/core"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/Netflix/go-expect"
"github.com/stretchr/testify/assert"
)

func init() {
// disable color output for all prompts to simplify testing
core.DisableColor = true
}

func TestFileselector(t *testing.T) {
t.Run("default", func(t *testing.T) {
var filename string
testFn := func(stdio terminal.Stdio) error {
var err error
filename, err = FileSelector("xxx", "help", WithOutput(stdio))
return err
}
procedure := func(t *testing.T, console *expect.Console) {
console.ExpectString("xxx")
console.SendLine("test.txt")
console.ExpectEOF()
}
RunTest(t, procedure, testFn)
assert.Equal(t, "test.txt", filename)
})
t.Run("empty with no override", func(t *testing.T) {
var filename string
testFn := func(stdio terminal.Stdio) error {
var err error
filename, err = FileSelector("xxx", "help", WithOutput(stdio))
return err
}
procedure := func(t *testing.T, console *expect.Console) {
console.ExpectString("xxx")
console.SendLine("")
time.Sleep(10 * time.Millisecond)
console.ExpectString("xxx")
console.SendLine(":wq!")
console.ExpectEOF()
}
RunTest(t, procedure, testFn)
assert.Equal(t, ":wq!", filename)
})
t.Run("empty with the override", func(t *testing.T) {
var filename string
testFn := func(stdio terminal.Stdio) error {
var err error
filename, err = FileSelector("xxx", "help", WithOutput(stdio), WithEmptyFilename("override"))
return err
}
procedure := func(t *testing.T, console *expect.Console) {
console.ExpectString("xxx")
console.SendLine("")
console.ExpectEOF()
}
RunTest(t, procedure, testFn)
assert.Equal(t, "override", filename)
})
}
44 changes: 44 additions & 0 deletions internal/app/ui/ui.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,46 @@
// Package ui contains some common UI elements, that use Survey library.
package ui

import (
"os"

"github.com/AlecAivazis/survey/v2"
"github.com/AlecAivazis/survey/v2/terminal"
)

type inputOptions struct {
stdio terminal.Stdio
fileSelectorOpt
}

// surveyOpts returns the survey options.
func (io *inputOptions) surveyOpts() []survey.AskOpt {
return []survey.AskOpt{
survey.WithStdio(io.stdio.In, io.stdio.Out, io.stdio.Err),
}
}

func (io *inputOptions) apply(opt ...Option) *inputOptions {
for _, fn := range opt {
fn(io)
}
return io
}

type Option func(*inputOptions)

func defaultOpts() *inputOptions {
return &inputOptions{
stdio: terminal.Stdio{
In: os.Stdin,
Out: os.Stdout,
Err: os.Stderr,
},
}
}

func WithOutput(stdio terminal.Stdio) Option {
return func(io *inputOptions) {
io.stdio = stdio
}
}
49 changes: 49 additions & 0 deletions internal/app/ui/ui_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package ui

import (
"testing"

"github.com/AlecAivazis/survey/v2/terminal"
"github.com/Netflix/go-expect"
"github.com/hinshun/vt10x"
"github.com/kr/pty"
)

type (
procedureFunc func(*testing.T, *expect.Console)
testFunc func(terminal.Stdio) error
)

// RunTest is the helper function to execute the UI tests.
//
// it's a simplified copy/paste from the survey lib:
//
// https://github.com/go-survey/survey/blob/master/survey_posix_test.go
func RunTest(t *testing.T, procedure func(*testing.T, *expect.Console), test func(terminal.Stdio) error) {
t.Helper()

pty, tty, err := pty.Open()
if err != nil {
t.Fatal(err)
}
term := vt10x.New(vt10x.WithWriter(tty))
console, err := expect.NewConsole(expect.WithStdin(pty), expect.WithStdout(term), expect.WithCloser(pty, tty))
if err != nil {
t.Fatal(err)
}
defer console.Close()

done := make(chan struct{})
go func() {
defer close(done)
procedure(t, console)
}()
stdio := terminal.Stdio{In: console.Tty(), Out: console.Tty(), Err: console.Tty()}
if err := test(stdio); err != nil {
t.Error(err)
}
if err := console.Tty().Close(); err != nil {
t.Errorf("error closing tty: %s", err)
}
<-done
}

0 comments on commit 998175b

Please sign in to comment.