udpate to use latest dep, update figtree

This commit is contained in:
Cory Bennett
2018-07-28 15:49:57 -07:00
parent eead13aef1
commit 462ef1c485
254 changed files with 698 additions and 43003 deletions
-23
View File
@@ -1,23 +0,0 @@
autoplay-tests:
summary: Replaying interactive tests
command: |-
cd tests
set -e
for test in autoplay/*.go; do
echo "==> Running $test"
go run $test
done
install-deps:
summary: Install all of package dependencies
command: |-
go get -t {{.files}}
# for autoplay tests
go get github.com/kr/pty
tests:
summary: Run the test suite
command: go test {{.files}}
variables:
files: '$(go list -v ./... | grep -iEv "tests|examples")'
-13
View File
@@ -1,13 +0,0 @@
language: go
go_import_path: gopkg.in/AlecAivazis/survey.v1
before_install:
- go get github.com/AlecAivazis/run
install:
- run install-deps
script:
- run tests
# - run autoplay-tests
-290
View File
@@ -1,290 +0,0 @@
# Survey
[![Build Status](https://travis-ci.org/AlecAivazis/survey.svg?branch=feature%2Fpretty)](https://travis-ci.org/AlecAivazis/survey)
[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg)](https://github.com/AlecAivazis/survey)
A library for building interactive prompts. Heavily inspired by the great [inquirer.js](https://github.com/SBoudrias/Inquirer.js/).
![](https://zippy.gfycat.com/AmusingBossyArrowworm.gif)
```go
package main
import (
"fmt"
"gopkg.in/AlecAivazis/survey.v1"
)
// the questions to ask
var qs = []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{Message: "What is your name?"},
Validate: survey.Required,
},
{
Name: "color",
Prompt: &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue", "green"},
Default: "red",
},
},
{
Name: "age",
Prompt: &survey.Input{Message: "How old are you?"},
},
}
func main() {
// the answers will be written to this struct
answers := struct {
Name string // survey will match the question and field names
FavoriteColor string `survey:"color"` // or you can tag fields to match a specific name
Age int // if the types don't match exactly, survey will try to convert for you
}{}
// perform the questions
err := survey.Ask(qs, &answers)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("%s chose %s.", answers.Name, answers.FavoriteColor)
}
```
## Table of Contents
1. [Examples](#examples)
1. [Prompts](#prompts)
1. [Input](#input)
1. [Password](#password)
1. [Confirm](#confirm)
1. [Select](#select)
1. [MultiSelect](#multiselect)
1. [Validation](#validation)
1. [Built-in Validators](#built-in-validators)
1. [Help Text](#help-text)
1. [Changing the input rune](#changing-the-input-run)
1. [Custom Types](#custom-types)
1. [Customizing Output](#customizing-output)
1. [Versioning](#versioning)
## Examples
Examples can be found in the `examples/` directory. Run them
to see basic behavior:
```bash
go get gopkg.in/AlecAivazis/survey.v1
# ... navigate to the repo in your GOPATH
go run examples/simple.go
go run examples/validation.go
```
## Prompts
### Input
<img src="https://media.giphy.com/media/3og0IxS8JsuD9Z8syA/giphy.gif" width="400px"/>
```golang
name := ""
prompt := &survey.Input{
Message: "ping",
}
survey.AskOne(prompt, &name, nil)
```
### Password
<img src="https://media.giphy.com/media/26FmQr6mUivkq71GE/giphy.gif" width="400px" />
```golang
password := ""
prompt := &survey.Password{
Message: "Please type your password",
}
survey.AskOne(prompt, &password, nil)
```
### Confirm
<img src="https://media.giphy.com/media/3oKIPgsUmTp4m3eo4E/giphy.gif" width="400px"/>
```golang
name := false
prompt := &survey.Confirm{
Message: "Do you like pie?",
}
survey.AskOne(prompt, &name, nil)
```
### Select
<img src="https://media.giphy.com/media/3oKIPxigmMu5YqpUPK/giphy.gif" width="400px"/>
```golang
color := ""
prompt := &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue", "green"},
}
survey.AskOne(prompt, &color, nil)
```
By default, the select prompt is limited to showing 7 options at a time
and will paginate lists of options longer than that. To increase, you can either
change the global `survey.PageCount`, or set the `PageSize` field on the prompt:
```golang
prompt := &survey.Select{..., PageSize: 10}
```
### MultiSelect
<img src="https://media.giphy.com/media/3oKIP8lHYFtGeQDH0c/giphy.gif" width="400px"/>
```golang
days := []string{}
prompt := &survey.MultiSelect{
Message: "What days do you prefer:",
Options: []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
}
survey.AskOne(prompt, &days, nil)
```
By default, the MultiSelect prompt is limited to showing 7 options at a time
and will paginate lists of options longer than that. To increase, you can either
change the global `survey.PageCount`, or set the `PageSize` field on the prompt:
```golang
prompt := &survey.MultiSelect{..., PageSize: 10}
```
## Validation
Validating individual responses for a particular question can be done by defining a
`Validate` field on the `survey.Question` to be validated. This function takes an
`interface{}` type and returns an error to show to the user, prompting them for another
response:
```golang
q := &survey.Question{
Prompt: &survey.Input{Message: "Hello world validation"},
Validate: func (val interface{}) error {
// since we are validating an Input, the assertion will always succeed
if str, ok := val.(string) ; ok && len(str) > 10 {
return errors.New("This response cannot be longer than 10 characters.")
}
}
}
```
### Built-in Validators
`survey` comes prepackaged with a few validators to fit common situations. Currently these
validators include:
| name | valid types | description |
|--------------|-----------------|---------------------------------------------------------------|
| Required | any | Rejects zero values of the response type |
| MinLength(n) | string | Enforces that a response is at least the given length |
| MaxLength(n) | string | Enforces that a response is no longer than the given length |
## Help Text
All of the prompts have a `Help` field which can be defined to provide more information to your users:
<img src="https://media.giphy.com/media/l1KVbc5CehW6r7pss/giphy.gif" width="400px" style="margin-top: 8px"/>
```golang
&survey.Input{
Message: "What is your phone number:",
Help: "Phone number should include the area code",
}
```
### Changing the input rune
In some situations, `?` is a perfectly valid response. To handle this, you can change the rune that survey
looks for by setting the `HelpInputRune` variable in `survey/core`:
```golang
import (
"gopkg.in/AlecAivazis/survey.v1"
surveyCore "gopkg.in/AlecAivazis/survey.v1/core"
)
number := ""
prompt := &survey.Input{
Message: "If you have this need, please give me a reasonable message.",
Help: "I couldn't come up with one.",
}
surveyCore.HelpInputRune = '^'
survey.AskOne(prompt, &number, nil)
```
## Custom Types
survey will assign prompt answers to your custom types if they implement this interface:
```golang
type settable interface {
WriteAnswer(field string, value interface{}) error
}
```
Here is an example how to use them:
```golang
type MyValue struct {
value string
}
func (my *MyValue) WriteAnswer(name string, value interface{}) error {
my.value = value.(string)
}
myval := MyValue{}
survey.AskOne(
&survey.Input{
Message: "Enter something:",
},
&myval,
nil,
)
```
## Customizing Output
Customizing the icons and various parts of survey can easily be done by setting the following variables
in `survey/core`:
| name | default | description |
|---------------------|----------------|-------------------------------------------------------------------|
| ErrorIcon | ✘ | Before an error |
| HelpIcon | ⓘ | Before help text |
| QuestionIcon | ? | Before the message of a prompt |
| SelectFocusIcon | | Marks the current focus in `Select` and `MultiSelect` prompts |
| MarkedOptionIcon | ◉ | Marks a chosen selection in a `MultiSelect` prompt |
| UnmarkedOptionIcon | ◯ | Marks an unselected option in a `MultiSelect` prompt |
## Versioning
This project tries to maintain semantic GitHub releases as closely as possible. And relies on [gopkg.in](http://labix.org/gopkg.in)
to maintain those releasees. Importing v1 of survey could look something like
```golang
package main
import "gopkg.in/AlecAivazis/survey.v1"
```
-71
View File
@@ -1,71 +0,0 @@
package survey
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
// disable color output for all prompts to simplify testing
core.DisableColor = true
}
func TestConfirmRender(t *testing.T) {
tests := []struct {
title string
prompt Confirm
data ConfirmTemplateData
expected string
}{
{
"Test Confirm question output with default true",
Confirm{Message: "Is pizza your favorite food?", Default: true},
ConfirmTemplateData{},
`? Is pizza your favorite food? (Y/n) `,
},
{
"Test Confirm question output with default false",
Confirm{Message: "Is pizza your favorite food?", Default: false},
ConfirmTemplateData{},
`? Is pizza your favorite food? (y/N) `,
},
{
"Test Confirm answer output",
Confirm{Message: "Is pizza your favorite food?"},
ConfirmTemplateData{Answer: "Yes"},
"? Is pizza your favorite food? Yes\n",
},
{
"Test Confirm with help but help message is hidden",
Confirm{Message: "Is pizza your favorite food?", Help: "This is helpful"},
ConfirmTemplateData{},
"? Is pizza your favorite food? [? for help] (y/N) ",
},
{
"Test Confirm help output with help message shown",
Confirm{Message: "Is pizza your favorite food?", Help: "This is helpful"},
ConfirmTemplateData{ShowHelp: true},
`ⓘ This is helpful
? Is pizza your favorite food? (y/N) `,
},
}
outputBuffer := bytes.NewBufferString("")
terminal.Stdout = outputBuffer
for _, test := range tests {
outputBuffer.Reset()
test.data.Confirm = test.prompt
err := test.prompt.Render(
ConfirmQuestionTemplate,
test.data,
)
assert.Nil(t, err, test.title)
assert.Equal(t, test.expected, outputBuffer.String(), test.title)
}
}
-543
View File
@@ -1,543 +0,0 @@
package core
import (
"fmt"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
)
func TestWrite_returnsErrorIfTargetNotPtr(t *testing.T) {
// try to copy a value to a non-pointer
err := WriteAnswer(true, "hello", true)
// make sure there was an error
if err == nil {
t.Error("Did not encounter error when writing to non-pointer.")
}
}
func TestWrite_canWriteToBool(t *testing.T) {
// a pointer to hold the boolean value
ptr := true
// try to copy a false value to the pointer
WriteAnswer(&ptr, "", false)
// if the value is true
if ptr {
// the test failed
t.Error("Could not write a false bool to a pointer")
}
}
func TestWrite_canWriteString(t *testing.T) {
// a pointer to hold the boolean value
ptr := ""
// try to copy a false value to the pointer
err := WriteAnswer(&ptr, "", "hello")
if err != nil {
t.Error(err)
}
// if the value is not what we wrote
if ptr != "hello" {
t.Error("Could not write a string value to a pointer")
}
}
func TestWrite_canWriteSlice(t *testing.T) {
// a pointer to hold the value
ptr := []string{}
// copy in a value
WriteAnswer(&ptr, "", []string{"hello", "world"})
// make sure there are two entries
assert.Equal(t, []string{"hello", "world"}, ptr)
}
func TestWrite_recoversInvalidReflection(t *testing.T) {
// a variable to mutate
ptr := false
// write a boolean value to the string
err := WriteAnswer(&ptr, "", "hello")
// if there was no error
if err == nil {
// the test failed
t.Error("Did not encounter error when forced invalid write.")
}
}
func TestWriteAnswer_handlesNonStructValues(t *testing.T) {
// the value to write to
ptr := ""
// write a value to the pointer
WriteAnswer(&ptr, "", "world")
// if we didn't change the value appropriate
if ptr != "world" {
// the test failed
t.Error("Did not write value to primitive pointer")
}
}
func TestWriteAnswer_canMutateStruct(t *testing.T) {
// the struct to hold the answer
ptr := struct{ Name string }{}
// write a value to an existing field
err := WriteAnswer(&ptr, "name", "world")
if err != nil {
// the test failed
t.Errorf("Encountered error while writing answer: %v", err.Error())
// we're done here
return
}
// make sure we changed the field
if ptr.Name != "world" {
// the test failed
t.Error("Did not mutate struct field when writing answer.")
}
}
func TestWriteAnswer_canMutateMap(t *testing.T) {
// the map to hold the answer
ptr := make(map[string]interface{})
// write a value to an existing field
err := WriteAnswer(&ptr, "name", "world")
if err != nil {
// the test failed
t.Errorf("Encountered error while writing answer: %v", err.Error())
// we're done here
return
}
// make sure we changed the field
if ptr["name"] != "world" {
// the test failed
t.Error("Did not mutate map when writing answer.")
}
}
func TestWrite_returnsErrorIfInvalidMapType(t *testing.T) {
// try to copy a value to a non map[string]interface{}
ptr := make(map[int]string)
err := WriteAnswer(&ptr, "name", "world")
// make sure there was an error
if err == nil {
t.Error("Did not encounter error when writing to invalid map.")
}
}
func TestWrite_writesStringSliceToIntSlice(t *testing.T) {
// make a slice of int to write to
target := []int{}
// write the answer
err := WriteAnswer(&target, "name", []string{"1", "2", "3"})
// make sure there was no error
assert.Nil(t, err, "WriteSlice to Int Slice")
// and we got what we wanted
assert.Equal(t, []int{1, 2, 3}, target)
}
func TestWrite_writesStringArrayToIntArray(t *testing.T) {
// make an array of int to write to
target := [3]int{}
// write the answer
err := WriteAnswer(&target, "name", [3]string{"1", "2", "3"})
// make sure there was no error
assert.Nil(t, err, "WriteArray to Int Array")
// and we got what we wanted
assert.Equal(t, [3]int{1, 2, 3}, target)
}
func TestWriteAnswer_returnsErrWhenFieldNotFound(t *testing.T) {
// the struct to hold the answer
ptr := struct{ Name string }{}
// write a value to an existing field
err := WriteAnswer(&ptr, "", "world")
if err == nil {
// the test failed
t.Error("Did not encountered error while writing answer to non-existing field.")
}
}
func TestFindFieldIndex_canFindExportedField(t *testing.T) {
// create a reflective wrapper over the struct to look through
val := reflect.ValueOf(struct{ Name string }{})
// find the field matching "name"
fieldIndex, err := findFieldIndex(val, "name")
// if something went wrong
if err != nil {
// the test failed
t.Error(err.Error())
return
}
// make sure we got the right value
if val.Type().Field(fieldIndex).Name != "Name" {
// the test failed
t.Errorf("Did not find the correct field name. Expected 'Name' found %v.", val.Type().Field(fieldIndex).Name)
}
}
func TestFindFieldIndex_canFindTaggedField(t *testing.T) {
// the struct to look through
val := reflect.ValueOf(struct {
Username string `survey:"name"`
}{})
// find the field matching "name"
fieldIndex, err := findFieldIndex(val, "name")
// if something went wrong
if err != nil {
// the test failed
t.Error(err.Error())
return
}
// make sure we got the right value
if val.Type().Field(fieldIndex).Name != "Username" {
// the test failed
t.Errorf("Did not find the correct field name. Expected 'Username' found %v.", val.Type().Field(fieldIndex).Name)
}
}
func TestFindFieldIndex_canHandleCapitalAnswerNames(t *testing.T) {
// create a reflective wrapper over the struct to look through
val := reflect.ValueOf(struct{ Name string }{})
// find the field matching "name"
fieldIndex, err := findFieldIndex(val, "Name")
// if something went wrong
if err != nil {
// the test failed
t.Error(err.Error())
return
}
// make sure we got the right value
if val.Type().Field(fieldIndex).Name != "Name" {
// the test failed
t.Errorf("Did not find the correct field name. Expected 'Name' found %v.", val.Type().Field(fieldIndex).Name)
}
}
func TestFindFieldIndex_tagOverwriteFieldName(t *testing.T) {
// the struct to look through
val := reflect.ValueOf(struct {
Name string
Username string `survey:"name"`
}{})
// find the field matching "name"
fieldIndex, err := findFieldIndex(val, "name")
// if something went wrong
if err != nil {
// the test failed
t.Error(err.Error())
return
}
// make sure we got the right value
if val.Type().Field(fieldIndex).Name != "Username" {
// the test failed
t.Errorf("Did not find the correct field name. Expected 'Username' found %v.", val.Type().Field(fieldIndex).Name)
}
}
type testFieldSettable struct {
Values map[string]string
}
type testStringSettable struct {
Value string `survey:"string"`
}
type testTaggedStruct struct {
TaggedValue testStringSettable `survey:"tagged"`
}
type testPtrTaggedStruct struct {
TaggedValue *testStringSettable `survey:"tagged"`
}
func (t *testFieldSettable) WriteAnswer(name string, value interface{}) error {
if t.Values == nil {
t.Values = map[string]string{}
}
if v, ok := value.(string); ok {
t.Values[name] = v
return nil
}
return fmt.Errorf("Incompatible type %T", value)
}
func (t *testStringSettable) WriteAnswer(_ string, value interface{}) error {
t.Value = value.(string)
return nil
}
func TestWriteWithFieldSettable(t *testing.T) {
testSet1 := testFieldSettable{}
err := WriteAnswer(&testSet1, "values", "stringVal")
assert.Nil(t, err)
assert.Equal(t, map[string]string{"values": "stringVal"}, testSet1.Values)
testSet2 := testFieldSettable{}
err = WriteAnswer(&testSet2, "values", 123)
assert.Error(t, fmt.Errorf("Incompatible type int64"), err)
assert.Equal(t, map[string]string{}, testSet2.Values)
testString1 := testStringSettable{}
err = WriteAnswer(&testString1, "", "value1")
assert.Nil(t, err)
assert.Equal(t, testStringSettable{"value1"}, testString1)
testSetStruct := testTaggedStruct{}
err = WriteAnswer(&testSetStruct, "tagged", "stringVal1")
assert.Nil(t, err)
assert.Equal(t, testTaggedStruct{TaggedValue: testStringSettable{"stringVal1"}}, testSetStruct)
testPtrSetStruct := testPtrTaggedStruct{&testStringSettable{}}
err = WriteAnswer(&testPtrSetStruct, "tagged", "stringVal1")
assert.Nil(t, err)
assert.Equal(t, testPtrTaggedStruct{TaggedValue: &testStringSettable{"stringVal1"}}, testPtrSetStruct)
}
// CONVERSION TESTS
func TestWrite_canStringToBool(t *testing.T) {
// a pointer to hold the boolean value
ptr := true
// try to copy a false value to the pointer
WriteAnswer(&ptr, "", "false")
// if the value is true
if ptr {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToInt(t *testing.T) {
// a pointer to hold the value
var ptr int = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToInt8(t *testing.T) {
// a pointer to hold the value
var ptr int8 = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToInt16(t *testing.T) {
// a pointer to hold the value
var ptr int16 = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToInt32(t *testing.T) {
// a pointer to hold the value
var ptr int32 = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToInt64(t *testing.T) {
// a pointer to hold the value
var ptr int64 = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToUint(t *testing.T) {
// a pointer to hold the value
var ptr uint = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToUint8(t *testing.T) {
// a pointer to hold the value
var ptr uint8 = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToUint16(t *testing.T) {
// a pointer to hold the value
var ptr uint16 = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToUint32(t *testing.T) {
// a pointer to hold the value
var ptr uint32 = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToUint64(t *testing.T) {
// a pointer to hold the value
var ptr uint64 = 1
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2")
// if the value is true
if ptr != 2 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToFloat32(t *testing.T) {
// a pointer to hold the value
var ptr float32 = 1.0
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2.5")
// if the value is true
if ptr != 2.5 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canStringToFloat64(t *testing.T) {
// a pointer to hold the value
var ptr float64 = 1.0
// try to copy a value to the pointer
WriteAnswer(&ptr, "", "2.5")
// if the value is true
if ptr != 2.5 {
// the test failed
t.Error("Could not convert string to pointer type")
}
}
func TestWrite_canConvertStructFieldTypes(t *testing.T) {
// the struct to hold the answer
ptr := struct {
Name string
Age uint
Male bool
Height float64
}{}
// write the values as strings
check(t, WriteAnswer(&ptr, "name", "Bob"))
check(t, WriteAnswer(&ptr, "age", "22"))
check(t, WriteAnswer(&ptr, "male", "true"))
check(t, WriteAnswer(&ptr, "height", "6.2"))
// make sure we changed the fields
if ptr.Name != "Bob" {
t.Error("Did not mutate Name when writing answer.")
}
if ptr.Age != 22 {
t.Error("Did not mutate Age when writing answer.")
}
if !ptr.Male {
t.Error("Did not mutate Male when writing answer.")
}
if ptr.Height != 6.2 {
t.Error("Did not mutate Height when writing answer.")
}
}
func check(t *testing.T, err error) {
if err != nil {
t.Fatalf("Encountered error while writing answer: %v", err.Error())
}
}
-83
View File
@@ -1,83 +0,0 @@
package survey
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
// disable color output for all prompts to simplify testing
core.DisableColor = true
}
func TestEditorRender(t *testing.T) {
tests := []struct {
title string
prompt Editor
data EditorTemplateData
expected string
}{
{
"Test Editor question output without default",
Editor{Message: "What is your favorite month:"},
EditorTemplateData{},
"? What is your favorite month: [Enter to launch editor] ",
},
{
"Test Editor question output with default",
Editor{Message: "What is your favorite month:", Default: "April"},
EditorTemplateData{},
"? What is your favorite month: (April) [Enter to launch editor] ",
},
{
"Test Editor answer output",
Editor{Message: "What is your favorite month:"},
EditorTemplateData{Answer: "October", ShowAnswer: true},
"? What is your favorite month: October\n",
},
{
"Test Editor question output without default but with help hidden",
Editor{Message: "What is your favorite month:", Help: "This is helpful"},
EditorTemplateData{},
"? What is your favorite month: [? for help] [Enter to launch editor] ",
},
{
"Test Editor question output with default and with help hidden",
Editor{Message: "What is your favorite month:", Default: "April", Help: "This is helpful"},
EditorTemplateData{},
"? What is your favorite month: [? for help] (April) [Enter to launch editor] ",
},
{
"Test Editor question output without default but with help shown",
Editor{Message: "What is your favorite month:", Help: "This is helpful"},
EditorTemplateData{ShowHelp: true},
`ⓘ This is helpful
? What is your favorite month: [Enter to launch editor] `,
},
{
"Test Editor question output with default and with help shown",
Editor{Message: "What is your favorite month:", Default: "April", Help: "This is helpful"},
EditorTemplateData{ShowHelp: true},
`ⓘ This is helpful
? What is your favorite month: (April) [Enter to launch editor] `,
},
}
outputBuffer := bytes.NewBufferString("")
terminal.Stdout = outputBuffer
for _, test := range tests {
outputBuffer.Reset()
test.data.Editor = test.prompt
err := test.prompt.Render(
EditorQuestionTemplate,
test.data,
)
assert.Nil(t, err, test.title)
assert.Equal(t, test.expected, outputBuffer.String(), test.title)
}
}
-84
View File
@@ -1,84 +0,0 @@
package survey
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
// disable color output for all prompts to simplify testing
core.DisableColor = true
}
func TestInputRender(t *testing.T) {
tests := []struct {
title string
prompt Input
data InputTemplateData
expected string
}{
{
"Test Input question output without default",
Input{Message: "What is your favorite month:"},
InputTemplateData{},
"? What is your favorite month: ",
},
{
"Test Input question output with default",
Input{Message: "What is your favorite month:", Default: "April"},
InputTemplateData{},
"? What is your favorite month: (April) ",
},
{
"Test Input answer output",
Input{Message: "What is your favorite month:"},
InputTemplateData{Answer: "October", ShowAnswer: true},
"? What is your favorite month: October\n",
},
{
"Test Input question output without default but with help hidden",
Input{Message: "What is your favorite month:", Help: "This is helpful"},
InputTemplateData{},
"? What is your favorite month: [? for help] ",
},
{
"Test Input question output with default and with help hidden",
Input{Message: "What is your favorite month:", Default: "April", Help: "This is helpful"},
InputTemplateData{},
"? What is your favorite month: [? for help] (April) ",
},
{
"Test Input question output without default but with help shown",
Input{Message: "What is your favorite month:", Help: "This is helpful"},
InputTemplateData{ShowHelp: true},
`ⓘ This is helpful
? What is your favorite month: `,
},
{
"Test Input question output with default and with help shown",
Input{Message: "What is your favorite month:", Default: "April", Help: "This is helpful"},
InputTemplateData{ShowHelp: true},
`ⓘ This is helpful
? What is your favorite month: (April) `,
},
}
outputBuffer := bytes.NewBufferString("")
terminal.Stdout = outputBuffer
for _, test := range tests {
outputBuffer.Reset()
test.data.Input = test.prompt
err := test.prompt.Render(
InputQuestionTemplate,
test.data,
)
assert.Nil(t, err, test.title)
assert.Equal(t, test.expected, outputBuffer.String(), test.title)
}
}
-105
View File
@@ -1,105 +0,0 @@
package survey
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
// disable color output for all prompts to simplify testing
core.DisableColor = true
}
func TestMultiSelectRender(t *testing.T) {
prompt := MultiSelect{
Message: "Pick your words:",
Options: []string{"foo", "bar", "baz", "buz"},
Default: []string{"bar", "buz"},
}
helpfulPrompt := prompt
helpfulPrompt.Help = "This is helpful"
tests := []struct {
title string
prompt MultiSelect
data MultiSelectTemplateData
expected string
}{
{
"Test MultiSelect question output",
prompt,
MultiSelectTemplateData{
SelectedIndex: 2,
PageEntries: prompt.Options,
Checked: map[string]bool{"bar": true, "buz": true},
},
`? Pick your words:
◯ foo
◉ bar
◯ baz
◉ buz
`,
},
{
"Test MultiSelect answer output",
prompt,
MultiSelectTemplateData{
Answer: "foo, buz",
ShowAnswer: true,
},
"? Pick your words: foo, buz\n",
},
{
"Test MultiSelect question output with help hidden",
helpfulPrompt,
MultiSelectTemplateData{
SelectedIndex: 2,
PageEntries: prompt.Options,
Checked: map[string]bool{"bar": true, "buz": true},
},
`? Pick your words: [? for help]
◯ foo
◉ bar
◯ baz
◉ buz
`,
},
{
"Test MultiSelect question output with help shown",
helpfulPrompt,
MultiSelectTemplateData{
SelectedIndex: 2,
PageEntries: prompt.Options,
Checked: map[string]bool{"bar": true, "buz": true},
ShowHelp: true,
},
`ⓘ This is helpful
? Pick your words:
◯ foo
◉ bar
◯ baz
◉ buz
`,
},
}
outputBuffer := bytes.NewBufferString("")
terminal.Stdout = outputBuffer
for _, test := range tests {
outputBuffer.Reset()
test.data.MultiSelect = test.prompt
err := test.prompt.Render(
MultiSelectQuestionTemplate,
test.data,
)
assert.Nil(t, err, test.title)
assert.Equal(t, test.expected, outputBuffer.String(), test.title)
}
}
-53
View File
@@ -1,53 +0,0 @@
package survey
import (
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
)
func init() {
// disable color output for all prompts to simplify testing
core.DisableColor = true
}
func TestPasswordRender(t *testing.T) {
tests := []struct {
title string
prompt Password
data PasswordTemplateData
expected string
}{
{
"Test Password question output",
Password{Message: "Tell me your secret:"},
PasswordTemplateData{},
"? Tell me your secret: ",
},
{
"Test Password question output with help hidden",
Password{Message: "Tell me your secret:", Help: "This is helpful"},
PasswordTemplateData{},
"? Tell me your secret: [? for help] ",
},
{
"Test Password question output with help shown",
Password{Message: "Tell me your secret:", Help: "This is helpful"},
PasswordTemplateData{ShowHelp: true},
`ⓘ This is helpful
? Tell me your secret: `,
},
}
for _, test := range tests {
test.data.Password = test.prompt
actual, err := core.RunTemplate(
PasswordQuestionTemplate,
&test.data,
)
assert.Nil(t, err, test.title)
assert.Equal(t, test.expected, actual, test.title)
}
}
-89
View File
@@ -1,89 +0,0 @@
package survey
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
func init() {
// disable color output for all prompts to simplify testing
core.DisableColor = true
}
func TestSelectRender(t *testing.T) {
prompt := Select{
Message: "Pick your word:",
Options: []string{"foo", "bar", "baz", "buz"},
Default: "baz",
}
helpfulPrompt := prompt
helpfulPrompt.Help = "This is helpful"
tests := []struct {
title string
prompt Select
data SelectTemplateData
expected string
}{
{
"Test Select question output",
prompt,
SelectTemplateData{SelectedIndex: 2, PageEntries: prompt.Options},
`? Pick your word:
foo
bar
baz
buz
`,
},
{
"Test Select answer output",
prompt,
SelectTemplateData{Answer: "buz", ShowAnswer: true, PageEntries: prompt.Options},
"? Pick your word: buz\n",
},
{
"Test Select question output with help hidden",
helpfulPrompt,
SelectTemplateData{SelectedIndex: 2, PageEntries: prompt.Options},
`? Pick your word: [? for help]
foo
bar
baz
buz
`,
},
{
"Test Select question output with help shown",
helpfulPrompt,
SelectTemplateData{SelectedIndex: 2, ShowHelp: true, PageEntries: prompt.Options},
`ⓘ This is helpful
? Pick your word:
foo
bar
baz
buz
`,
},
}
outputBuffer := bytes.NewBufferString("")
terminal.Stdout = outputBuffer
for _, test := range tests {
outputBuffer.Reset()
test.data.Select = test.prompt
err := test.prompt.Render(
SelectQuestionTemplate,
test.data,
)
assert.Nil(t, err, test.title)
assert.Equal(t, test.expected, outputBuffer.String(), test.title)
}
}
-118
View File
@@ -1,118 +0,0 @@
package survey
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/AlecAivazis/survey.v1/core"
)
func init() {
// disable color output for all prompts to simplify testing
core.DisableColor = true
}
func TestValidationError(t *testing.T) {
err := fmt.Errorf("Football is not a valid month")
actual, err := core.RunTemplate(
core.ErrorTemplate,
err,
)
if err != nil {
t.Errorf("Failed to run template to format error: %s", err)
}
expected := `✘ Sorry, your reply was invalid: Football is not a valid month
`
if actual != expected {
t.Errorf("Formatted error was not formatted correctly. Found:\n%s\nExpected:\n%s", actual, expected)
}
}
func TestAsk_returnsErrorIfTargetIsNil(t *testing.T) {
// pass an empty place to leave the answers
err := Ask([]*Question{}, nil)
// if we didn't get an error
if err == nil {
// the test failed
t.Error("Did not encounter error when asking with no where to record.")
}
}
func TestPagination_tooFew(t *testing.T) {
// a small list of options
choices := []string{"choice1", "choice2", "choice3"}
// a page bigger than the total number
pageSize := 4
// the current selection
sel := 3
// compute the page info
page, idx := paginate(pageSize, choices, sel)
// make sure we see the full list of options
assert.Equal(t, choices, page)
// with the second index highlighted (no change)
assert.Equal(t, 3, idx)
}
func TestPagination_firstHalf(t *testing.T) {
// the choices for the test
choices := []string{"choice1", "choice2", "choice3", "choice4", "choice5", "choice6"}
// section the choices into groups of 4 so the choice is somewhere in the middle
// to verify there is no displacement of the page
pageSize := 4
// test the second item
sel := 2
// compute the page info
page, idx := paginate(pageSize, choices, sel)
// we should see the first three options
assert.Equal(t, choices[0:4], page)
// with the second index highlighted
assert.Equal(t, 2, idx)
}
func TestPagination_middle(t *testing.T) {
// the choices for the test
choices := []string{"choice0", "choice1", "choice2", "choice3", "choice4", "choice5"}
// section the choices into groups of 3
pageSize := 2
// test the second item so that we can verify we are in the middle of the list
sel := 3
// compute the page info
page, idx := paginate(pageSize, choices, sel)
// we should see the first three options
assert.Equal(t, choices[2:4], page)
// with the second index highlighted
assert.Equal(t, 1, idx)
}
func TestPagination_lastHalf(t *testing.T) {
// the choices for the test
choices := []string{"choice0", "choice1", "choice2", "choice3", "choice4", "choice5"}
// section the choices into groups of 3
pageSize := 3
// test the last item to verify we're not in the middle
sel := 5
// compute the page info
page, idx := paginate(pageSize, choices, sel)
// we should see the first three options
assert.Equal(t, choices[3:6], page)
// we should be at the bottom of the list
assert.Equal(t, 2, idx)
}
-151
View File
@@ -1,151 +0,0 @@
package survey
import (
"math/rand"
"testing"
)
func TestRequired_canSucceedOnPrimitiveTypes(t *testing.T) {
// a string to test
str := "hello"
// if the string is not valid
if valid := Required(str); valid != nil {
//
t.Error("Non null returned an error when one wasn't expected.")
}
}
func TestRequired_canFailOnPrimitiveTypes(t *testing.T) {
// a string to test
str := ""
// if the string is valid
if notValid := Required(str); notValid == nil {
//
t.Error("Non null did not return an error when one was expected.")
}
}
func TestRequired_canSucceedOnMap(t *testing.T) {
// an non-empty map to test
val := map[string]int{"hello": 1}
// if the string is not valid
if valid := Required(val); valid != nil {
//
t.Error("Non null returned an error when one wasn't expected.")
}
}
func TestRequired_canFailOnMap(t *testing.T) {
// an non-empty map to test
val := map[string]int{}
// if the string is valid
if notValid := Required(val); notValid == nil {
//
t.Error("Non null did not return an error when one was expected.")
}
}
func TestRequired_canSucceedOnLists(t *testing.T) {
// a string to test
str := []string{"hello"}
// if the string is not valid
if valid := Required(str); valid != nil {
//
t.Error("Non null returned an error when one wasn't expected.")
}
}
func TestRequired_canFailOnLists(t *testing.T) {
// a string to test
str := []string{}
// if the string is not valid
if notValid := Required(str); notValid == nil {
//
t.Error("Non null did not return an error when one was expected.")
}
}
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func randString(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand.Int63()%int64(len(letterBytes))]
}
return string(b)
}
func TestMaxLength(t *testing.T) {
// the string to test
testStr := randString(150)
// validate the string
if err := MaxLength(140)(testStr); err == nil {
t.Error("No error returned with input greater than 150 characters.")
}
}
func TestMinLength(t *testing.T) {
// validate the string
if err := MinLength(12)(randString(10)); err == nil {
t.Error("No error returned with input less than 12 characters.")
}
}
func TestMinLength_onInt(t *testing.T) {
// validate the string
if err := MinLength(12)(1); err == nil {
t.Error("No error returned when enforcing length on int.")
}
}
func TestMaxLength_onInt(t *testing.T) {
// validate the string
if err := MaxLength(12)(1); err == nil {
t.Error("No error returned when enforcing length on int.")
}
}
func TestComposeValidators_passes(t *testing.T) {
// create a validator that requires a string of no more than 10 characters
valid := ComposeValidators(
Required,
MaxLength(10),
)
str := randString(12)
// if a valid string fails
if err := valid(str); err == nil {
// the test failed
t.Error("Composed validator did not pass. Wanted string less than 10 chars, passed in", str)
}
}
func TestComposeValidators_failsOnFirstError(t *testing.T) {
// create a validator that requires a string of no more than 10 characters
valid := ComposeValidators(
Required,
MaxLength(10),
)
// if an empty string passes
if err := valid(""); err == nil {
// the test failed
t.Error("Composed validator did not fail on first test like expected.")
}
}
func TestComposeValidators_failsOnSubsequentValidators(t *testing.T) {
// create a validator that requires a string of no more than 10 characters
valid := ComposeValidators(
Required,
MaxLength(10),
)
str := randString(12)
// if a string longer than 10 passes
if err := valid(str); err == nil {
// the test failed
t.Error("Composed validator did not fail on second first test like expected. Should fail max length > 10 :", str)
}
}