711 lines
19 KiB
Go
711 lines
19 KiB
Go
package wmenu
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
wlog "gopkg.in/dixonwille/wlog.v2"
|
|
)
|
|
|
|
var newMenuCases = []string{"Testing this menu.", "", "!@#$%^&*()"}
|
|
var setSeperatorCases = []string{"", ".", ",", "~"}
|
|
var defaultIconCases = []string{"", ",", "*", "~", "!", "@"}
|
|
var setTriesCases = []int{0, -4, 5}
|
|
var optionCases = []struct {
|
|
name string
|
|
value interface{}
|
|
def bool
|
|
function func(Opt) error
|
|
}{
|
|
{"Options", "Options", true, func(Opt) error { fmt.Println("testing option"); return nil }},
|
|
{"", "Options", true, func(Opt) error { fmt.Println("testing option"); return nil }},
|
|
{"Options", "", false, func(Opt) error { fmt.Println("testing option"); return nil }},
|
|
{"", "", false, nil},
|
|
{"", nil, false, nil},
|
|
}
|
|
var actionCases = []func([]Opt) error{
|
|
func(opts []Opt) error { fmt.Println(opts); return nil },
|
|
nil,
|
|
}
|
|
var addColorCases = []struct {
|
|
opt wlog.Color
|
|
que wlog.Color
|
|
res wlog.Color
|
|
err wlog.Color
|
|
}{
|
|
{wlog.None, wlog.None, wlog.None, wlog.None},
|
|
{wlog.Red, wlog.Green, wlog.Blue, wlog.Black},
|
|
{wlog.Yellow, wlog.White, wlog.Cyan, wlog.Magenta},
|
|
{wlog.BrightBlack, wlog.BrightBlue, wlog.BrightCyan, wlog.BrightGreen},
|
|
{wlog.BrightRed, wlog.BrightWhite, wlog.BrightYellow, wlog.BrightMagenta},
|
|
}
|
|
var errorCases = []struct {
|
|
input string
|
|
optFunction func(option Opt) error
|
|
defFunction func([]Opt) error
|
|
expected string
|
|
singDef bool
|
|
multiDef bool
|
|
}{
|
|
{"0\r\n", func(option Opt) error { return errors.New("Oops") }, nil, "Oops", false, false},
|
|
{"0\r\n", nil, func(opts []Opt) error { return errors.New("Oops") }, "Oops", false, false},
|
|
{"0 1\r\n", nil, func(opts []Opt) error { return errors.New("Oops") }, "Too many responses", false, false},
|
|
{"\r\n", func(option Opt) error { return errors.New("Oops") }, nil, "Oops", true, false},
|
|
{"\r\n", nil, func(opts []Opt) error { return errors.New("Oops") }, "Oops", true, false},
|
|
{"\r\n", nil, func(opts []Opt) error { return errors.New("Oops") }, "Oops", false, false},
|
|
{"\r\n", nil, func(opts []Opt) error { return errors.New("Oops") }, "Oops", true, true},
|
|
}
|
|
var ynCases = []struct {
|
|
input string
|
|
defFunc func([]Opt) error
|
|
expected string
|
|
def int
|
|
}{
|
|
{"\r\n", func(opts []Opt) error { return errors.New(opts[0].Text) }, "y", 0},
|
|
{"\r\n", func(opts []Opt) error { return errors.New(opts[0].Text) }, "n", 1},
|
|
{"YES\r\n", func(opts []Opt) error { return errors.New(opts[0].Text) }, "y", 0},
|
|
{"n\r\n", func(opts []Opt) error { return errors.New(opts[0].Text) }, "n", 0},
|
|
{" Yes \r\n", func(opts []Opt) error { return errors.New(opts[0].Text) }, "y", 0},
|
|
{"ahh\r\n", func(opts []Opt) error { return errors.New(opts[0].Text) }, "Invalid response: ahh", 0},
|
|
{"boo ahh\r\n", func(opts []Opt) error { return errors.New(opts[0].Text) }, "Too many responses", 0},
|
|
}
|
|
var trimCases = []struct {
|
|
input string
|
|
del string
|
|
expected string
|
|
}{
|
|
{"0 \r\n", " ", "0\r\n"},
|
|
{" 0\r\n", " ", "0\r\n"},
|
|
{" 0 \r\n", " ", "0\r\n"},
|
|
{"0 1 \r\n", " ", "0 1\r\n"},
|
|
{" 0 1\r\n", " ", "0 1\r\n"},
|
|
{" 0 1 \r\n", " ", "0 1\r\n"},
|
|
{" 0, 1 \r\n", ",", "0 1\r\n"},
|
|
{"0, 1,\r\n", ",", "0 1\r\n"},
|
|
{"0, 1, \r\n", ",", "0 1\r\n"},
|
|
}
|
|
|
|
func Example_optionValue() {
|
|
type NameEntity struct {
|
|
FirstName string
|
|
LastName string
|
|
}
|
|
|
|
reader := strings.NewReader("1\r\n") //Simulates the user typing "1" and hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
fmt.Println("Option 0 was chosen.")
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
name, ok := opts[0].Value.(NameEntity)
|
|
if !ok {
|
|
log.Fatal("Could not cast option's value to NameEntity")
|
|
}
|
|
fmt.Printf("%s has an id of %d.\n", opts[0].Text, opts[0].ID)
|
|
fmt.Printf("Hello, %s %s.\n", name.FirstName, name.LastName)
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, os.Stdout, os.Stderr)
|
|
menu.Action(actFunc)
|
|
menu.Option("Option 0", NameEntity{"Bill", "Bob"}, true, optFunc)
|
|
menu.Option("Option 1", NameEntity{"John", "Doe"}, false, nil)
|
|
menu.Option("Option 2", NameEntity{"Jane", "Doe"}, false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
//Output:
|
|
//0) *Option 0
|
|
//1) Option 1
|
|
//2) Option 2
|
|
//Choose an option.
|
|
//Option 1 has an id of 1.
|
|
//Hello, John Doe.
|
|
}
|
|
|
|
func Example_yesNo() {
|
|
reader := strings.NewReader("y\r\n") //Simulates the user typing "y" and hitting the [enter] key
|
|
actFunc := func(opts []Opt) error {
|
|
fmt.Printf("%s has an id of %d.\n", opts[0].Text, opts[0].ID)
|
|
fmt.Printf("But has a value of %s.\n", opts[0].Value.(string))
|
|
return nil
|
|
}
|
|
menu := NewMenu("Would you like to start?")
|
|
menu.ChangeReaderWriter(reader, os.Stdout, os.Stderr)
|
|
menu.Action(actFunc)
|
|
menu.IsYesNo(0)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
//Output:
|
|
//Would you like to start? (Y/n)
|
|
//y has an id of 0.
|
|
//But has a value of yes.
|
|
}
|
|
|
|
func Example_simpleDefault() {
|
|
reader := strings.NewReader("\r\n") //Simulates the user hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
fmt.Fprint(os.Stdout, "Option 0 was chosen.")
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, os.Stdout, os.Stderr)
|
|
menu.Option("Option 0", "0", true, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
//Output:
|
|
//0) *Option 0
|
|
//1) Option 1
|
|
//2) Option 2
|
|
//Choose an option.
|
|
//Option 0 was chosen.
|
|
}
|
|
|
|
func Example_multiple() {
|
|
reader := strings.NewReader("1,2\r\n") //Simulates the user typing "1,2" and hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
fmt.Println("Option 0 was chosen.")
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
for _, opt := range opts {
|
|
fmt.Printf("%s has an id of %d.\n", opt.Text, opt.ID)
|
|
}
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, os.Stdout, os.Stderr)
|
|
menu.Action(actFunc)
|
|
menu.AllowMultiple()
|
|
menu.SetSeparator(",")
|
|
menu.Option("Option 0", "0", true, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", true, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
//Output:
|
|
//0) *Option 0
|
|
//1) Option 1
|
|
//2) *Option 2
|
|
//Choose an option.
|
|
//Option 1 has an id of 1.
|
|
//Option 2 has an id of 2.
|
|
}
|
|
|
|
func Example_multipleDefault() {
|
|
reader := strings.NewReader("\r\n") //Simulates the user hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
fmt.Println("Option 0 was chosen.")
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
for _, opt := range opts {
|
|
fmt.Printf("%s has an id of %d.\n", opt.Text, opt.ID)
|
|
}
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, os.Stdout, os.Stderr)
|
|
menu.Action(actFunc)
|
|
menu.AllowMultiple()
|
|
menu.Option("Option 0", "0", true, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", true, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
//Output:
|
|
//0) *Option 0
|
|
//1) Option 1
|
|
//2) *Option 2
|
|
//Choose an option.
|
|
//Option 0 has an id of 0.
|
|
//Option 2 has an id of 2.
|
|
}
|
|
|
|
func Example_errorNoResponse() {
|
|
reader := strings.NewReader("\r\n") //Simulates the user hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
fmt.Println("Option 0 was chosen.")
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, os.Stdout, os.Stderr)
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
if IsNoResponseErr(err) {
|
|
fmt.Println("We caught the err: " + err.Error())
|
|
} else {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
//Output:
|
|
//0) Option 0
|
|
//1) Option 1
|
|
//2) Option 2
|
|
//Choose an option.
|
|
//We caught the err: No response
|
|
}
|
|
|
|
func Example_errorInvalid() {
|
|
reader := strings.NewReader("3\r\n") //Simulates the user typing "3" and hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
fmt.Println("Option 0 was chosen.")
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, os.Stdout, os.Stderr)
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
if IsInvalidErr(err) {
|
|
fmt.Println("We caught the err: " + err.Error())
|
|
} else {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
//Output:
|
|
//0) Option 0
|
|
//1) Option 1
|
|
//2) Option 2
|
|
//Choose an option.
|
|
//We caught the err: Invalid response: 3
|
|
}
|
|
|
|
func Example_errorTooMany() {
|
|
reader := strings.NewReader("1 2\r\n") //Simulates the user typing "1 2" and hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
fmt.Println("Option 0 was chosen.")
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, os.Stdout, os.Stderr)
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
if IsTooManyErr(err) {
|
|
fmt.Println("We caught the err: " + err.Error())
|
|
} else {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
//Output:
|
|
//0) Option 0
|
|
//1) Option 1
|
|
//2) Option 2
|
|
//Choose an option.
|
|
//We caught the err: Too many responses
|
|
}
|
|
|
|
func Example_errorDuplicate() {
|
|
reader := strings.NewReader("1 1\r\n") //Simulates the user typing "1 1" and hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
fmt.Println("Option 0 was chosen.")
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
for _, opt := range opts {
|
|
fmt.Printf("%s has an id of %d.\n", opt.Text, opt.ID)
|
|
}
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, os.Stdout, os.Stderr)
|
|
menu.Action(actFunc)
|
|
menu.AllowMultiple()
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
if IsDuplicateErr(err) {
|
|
fmt.Println("We caught the err: " + err.Error())
|
|
} else {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
//Output:
|
|
//0) Option 0
|
|
//1) Option 1
|
|
//2) Option 2
|
|
//Choose an option.
|
|
//We caught the err: Duplicated response: 1
|
|
|
|
}
|
|
|
|
func TestNewMenu(t *testing.T) {
|
|
assert := assert.New(t)
|
|
for _, c := range newMenuCases {
|
|
menu := NewMenu(c)
|
|
assert.Equal(c, menu.question)
|
|
assert.Nil(menu.function)
|
|
assert.Nil(menu.options)
|
|
assert.Equal(" ", menu.multiSeparator)
|
|
assert.False(menu.allowMultiple)
|
|
assert.False(menu.loopOnInvalid)
|
|
assert.False(menu.clear)
|
|
assert.NotNil(menu.ui)
|
|
assert.Equal(3, menu.tries)
|
|
}
|
|
}
|
|
|
|
func TestClearOnMenuRun(t *testing.T) {
|
|
menu := NewMenu("Testing")
|
|
menu.ClearOnMenuRun()
|
|
assert.True(t, menu.clear)
|
|
}
|
|
|
|
func TestSetSeperator(t *testing.T) {
|
|
menu := NewMenu("Testing")
|
|
for _, c := range setSeperatorCases {
|
|
menu.SetSeparator(c)
|
|
assert.Equal(t, c, menu.multiSeparator)
|
|
}
|
|
}
|
|
|
|
func TestSetTries(t *testing.T) {
|
|
menu := NewMenu("Testing")
|
|
for _, c := range setTriesCases {
|
|
menu.SetTries(c)
|
|
assert.Equal(t, c, menu.tries)
|
|
}
|
|
}
|
|
|
|
func TestLoopOnInvalid(t *testing.T) {
|
|
menu := NewMenu("Testing")
|
|
menu.LoopOnInvalid()
|
|
assert.True(t, menu.loopOnInvalid)
|
|
}
|
|
|
|
func TestOption(t *testing.T) {
|
|
assert := assert.New(t)
|
|
menu := NewMenu("Testing")
|
|
for i, c := range optionCases {
|
|
menu.Option(c.name, c.value, c.def, c.function)
|
|
require.Equal(t, i+1, len(menu.options))
|
|
assert.Equal(i, menu.options[i].ID)
|
|
assert.Equal(c.name, menu.options[i].Text)
|
|
assert.Equal(c.def, menu.options[i].isDefault)
|
|
assert.Equal(c.value, menu.options[i].Value)
|
|
if c.function != nil {
|
|
assert.NotNil(menu.options[i].function)
|
|
} else {
|
|
assert.Nil(menu.options[i].function)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAction(t *testing.T) {
|
|
menu := NewMenu("Testing")
|
|
for _, c := range actionCases {
|
|
menu.Action(c)
|
|
if c != nil {
|
|
assert.NotNil(t, menu.function)
|
|
} else {
|
|
assert.Nil(t, menu.function)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAllowMultiple(t *testing.T) {
|
|
menu := NewMenu("Testing")
|
|
menu.AllowMultiple()
|
|
assert.True(t, menu.allowMultiple)
|
|
}
|
|
|
|
func TestAddColor(t *testing.T) {
|
|
menu := NewMenu("Testing")
|
|
for _, c := range addColorCases {
|
|
menu.AddColor(c.opt, c.que, c.res, c.err)
|
|
//Nothing to assert on just make sure the function does not fail
|
|
}
|
|
}
|
|
|
|
func TestSetDefaultIcon(t *testing.T) {
|
|
menu := NewMenu("Testing")
|
|
for _, c := range defaultIconCases {
|
|
menu.SetDefaultIcon(c)
|
|
assert.Equal(t, c, menu.defIcon)
|
|
}
|
|
|
|
}
|
|
|
|
func TestClearInAsk(t *testing.T) {
|
|
stdOut := initTest()
|
|
reader := strings.NewReader("1\r\n") //Simulates the user typing "1" and hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
assert.Fail(t, "Should not have called Option 0's function")
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
assert.Len(t, opts, 1)
|
|
assert.Equal(t, 1, opts[0].ID)
|
|
assert.Equal(t, "Option 1", opts[0].Text)
|
|
assert.Nil(t, opts[0].function)
|
|
assert.False(t, opts[0].isDefault)
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, stdOut, stdOut)
|
|
menu.Action(actFunc)
|
|
menu.ClearOnMenuRun()
|
|
menu.Option("Option 0", "0", true, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", true, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
assert.Fail(t, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestDefaultAction(t *testing.T) {
|
|
stdOut := initTest()
|
|
reader := strings.NewReader("\r\n") //Simulates the user hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
assert.Fail(t, "Should not have called option 0's function")
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
assert.Len(t, opts, 1)
|
|
assert.Equal(t, -1, opts[0].ID)
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, stdOut, stdOut)
|
|
menu.Action(actFunc)
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
// spew.Dump(menu)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
assert.Fail(t, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestDefaultActionWithDefaultOption(t *testing.T) {
|
|
stdOut := initTest()
|
|
reader := strings.NewReader("\r\n") //Simulates the user hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
assert.Fail(t, "Should not have called option 0's function")
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
assert.Len(t, opts, 1)
|
|
assert.Equal(t, 1, opts[0].ID)
|
|
assert.Equal(t, "Option 1", opts[0].Text)
|
|
assert.Nil(t, opts[0].function)
|
|
assert.True(t, opts[0].isDefault)
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, stdOut, stdOut)
|
|
menu.Action(actFunc)
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", true, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
assert.Fail(t, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestOptionsFunction(t *testing.T) {
|
|
stdOut := initTest()
|
|
reader := strings.NewReader("0\r\n") //Simulates the user typing "0" and hitting the [enter] key
|
|
optFunc := func(option Opt) error {
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
assert.Fail(t, "Should not have called the menu's default function")
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, stdOut, stdOut)
|
|
menu.Action(actFunc)
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", true, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
assert.Fail(t, err.Error())
|
|
}
|
|
}
|
|
|
|
func TestWlogAskErr(t *testing.T) {
|
|
stdOut := initTest()
|
|
reader := strings.NewReader("1") //Simulates the user typing "1" without hitting [enter]. Can't happen when reader is os.Stdin
|
|
optFunc := func(option Opt) error {
|
|
assert.Fail(t, "Should not have called option 0's function")
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
assert.Fail(t, "Should not have called the menu's default function")
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, stdOut, stdOut)
|
|
menu.Action(actFunc)
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", true, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
assert.Equal(t, "EOF", err.Error())
|
|
} else {
|
|
assert.Fail(t, "Expected to get an error of EOF but instead got no error")
|
|
}
|
|
}
|
|
|
|
func TestLetterForResponse(t *testing.T) {
|
|
stdOut := initTest()
|
|
reader := strings.NewReader("a\r\n") //Simulates the user typing "a" and hitting [enter].
|
|
optFunc := func(option Opt) error {
|
|
assert.Fail(t, "Should not have called option 0's function")
|
|
return nil
|
|
}
|
|
actFunc := func(opts []Opt) error {
|
|
assert.Fail(t, "Should not have called the menu's default function")
|
|
return nil
|
|
}
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, stdOut, stdOut)
|
|
menu.Action(actFunc)
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", true, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
require.True(t, IsInvalidErr(err))
|
|
e := err.(*MenuError)
|
|
assert.Equal(t, "a", e.Res)
|
|
} else {
|
|
assert.Fail(t, "Expected to get an Invalid Response error but instead got no error")
|
|
}
|
|
}
|
|
|
|
func TestActionError(t *testing.T) {
|
|
stdout := initTest()
|
|
for _, c := range errorCases {
|
|
reader := strings.NewReader(c.input)
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, stdout, stdout)
|
|
menu.Action(c.defFunction)
|
|
if c.multiDef {
|
|
menu.AllowMultiple()
|
|
}
|
|
menu.Option("Option 0", "0", c.singDef, c.optFunction)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", c.multiDef, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
assert.Equal(t, c.expected, err.Error())
|
|
} else {
|
|
assert.Fail(t, "Expected an error but did not get one")
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestLoopAndTries(t *testing.T) {
|
|
stdOut := initTest()
|
|
optFunc := func(option Opt) error {
|
|
assert.Fail(t, "Should not have called option 0's function")
|
|
return nil
|
|
}
|
|
for _, c := range setTriesCases {
|
|
reader := strings.NewReader("a") //Simulates the user typing "a" and not hitting [enter].
|
|
menu := NewMenu("Choose an option.")
|
|
menu.ChangeReaderWriter(reader, stdOut, stdOut)
|
|
menu.SetTries(c)
|
|
menu.LoopOnInvalid()
|
|
menu.ClearOnMenuRun()
|
|
menu.Option("Option 0", "0", false, optFunc)
|
|
menu.Option("Option 1", "1", false, nil)
|
|
menu.Option("Option 2", "2", false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
require.True(t, IsMenuErr(err))
|
|
e := err.(*MenuError)
|
|
assert.Equal(t, 0, e.TriesLeft)
|
|
} else {
|
|
assert.Fail(t, "Expected to get a general Menu error but instead got no error")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestYesNo(t *testing.T) {
|
|
for _, c := range ynCases {
|
|
stdOut := initTest()
|
|
reader := strings.NewReader(c.input)
|
|
menu := NewMenu("Yes or No")
|
|
menu.ChangeReaderWriter(reader, stdOut, stdOut)
|
|
menu.IsYesNo(c.def)
|
|
menu.Action(c.defFunc)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
assert.Equal(t, c.expected, err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTrim(t *testing.T) {
|
|
for _, c := range trimCases {
|
|
stdOut := initTest()
|
|
actOut := initTest()
|
|
reader := strings.NewReader(c.input)
|
|
menu := NewMenu("Testing")
|
|
menu.ChangeReaderWriter(reader, stdOut, stdOut)
|
|
menu.SetSeparator(c.del)
|
|
menu.Action(func(opts []Opt) error {
|
|
var actual []string
|
|
for _, opt := range opts {
|
|
actual = append(actual, opt.Text)
|
|
}
|
|
fmt.Fprintf(actOut, "%s\r\n", strings.Join(actual, " "))
|
|
return nil
|
|
})
|
|
menu.AllowMultiple()
|
|
menu.Option("0", nil, false, nil)
|
|
menu.Option("1", nil, false, nil)
|
|
err := menu.Run()
|
|
if err != nil {
|
|
assert.Fail(t, err.Error())
|
|
}
|
|
act, err := actOut.ReadString((byte)('\n'))
|
|
if err != nil {
|
|
assert.Fail(t, err.Error())
|
|
}
|
|
assert.Equal(t, c.expected, act)
|
|
}
|
|
}
|
|
|
|
func initTest() *bytes.Buffer {
|
|
var b []byte
|
|
return bytes.NewBuffer(b)
|
|
}
|