320 lines
6.9 KiB
Go
320 lines
6.9 KiB
Go
package prompt
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// mockReader implements the Reader interface for testing
|
|
type mockReader struct {
|
|
input string
|
|
pos int
|
|
}
|
|
|
|
func (m *mockReader) ReadString(delim byte) (string, error) {
|
|
if m.pos >= len(m.input) {
|
|
return "", io.EOF
|
|
}
|
|
|
|
idx := strings.IndexByte(m.input[m.pos:], delim)
|
|
if idx == -1 {
|
|
result := m.input[m.pos:]
|
|
m.pos = len(m.input)
|
|
return result, nil
|
|
}
|
|
|
|
result := m.input[m.pos : m.pos+idx+1]
|
|
m.pos += idx + 1
|
|
return result, nil
|
|
}
|
|
|
|
func TestPromptStringWithReader(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
defaultValue string
|
|
required bool
|
|
expected string
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "user enters value",
|
|
input: "testvalue\n",
|
|
defaultValue: "default",
|
|
required: false,
|
|
expected: "testvalue",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "user accepts default",
|
|
input: "\n",
|
|
defaultValue: "default",
|
|
required: false,
|
|
expected: "default",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "required field empty then filled",
|
|
input: "\nactualvalue\n",
|
|
defaultValue: "",
|
|
required: true,
|
|
expected: "actualvalue",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "optional empty field",
|
|
input: "\n",
|
|
defaultValue: "",
|
|
required: false,
|
|
expected: "",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "whitespace trimmed",
|
|
input: " test \n",
|
|
defaultValue: "",
|
|
required: false,
|
|
expected: "test",
|
|
expectError: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
reader := &mockReader{input: tt.input}
|
|
result, err := promptStringWithReader(reader, "Test Label", tt.defaultValue, tt.required)
|
|
|
|
if (err != nil) != tt.expectError {
|
|
t.Errorf("Expected error: %v, got: %v", tt.expectError, err)
|
|
}
|
|
|
|
if result != tt.expected {
|
|
t.Errorf("Expected %q, got %q", tt.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPromptIntWithReader(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
defaultValue int
|
|
required bool
|
|
expected int
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "user enters valid number",
|
|
input: "42\n",
|
|
defaultValue: 0,
|
|
required: false,
|
|
expected: 42,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "user accepts default",
|
|
input: "\n",
|
|
defaultValue: 5432,
|
|
required: false,
|
|
expected: 5432,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "invalid then valid number",
|
|
input: "abc\n123\n",
|
|
defaultValue: 0,
|
|
required: false,
|
|
expected: 123,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "required field empty then filled",
|
|
input: "\n999\n",
|
|
defaultValue: 0,
|
|
required: true,
|
|
expected: 999,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "zero value",
|
|
input: "0\n",
|
|
defaultValue: 10,
|
|
required: false,
|
|
expected: 0,
|
|
expectError: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
reader := &mockReader{input: tt.input}
|
|
result, err := promptIntWithReader(reader, "Test Label", tt.defaultValue, tt.required)
|
|
|
|
if (err != nil) != tt.expectError {
|
|
t.Errorf("Expected error: %v, got: %v", tt.expectError, err)
|
|
}
|
|
|
|
if result != tt.expected {
|
|
t.Errorf("Expected %d, got %d", tt.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateDirectory(t *testing.T) {
|
|
// Create a temporary directory for testing
|
|
tmpDir := t.TempDir()
|
|
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
setup func() string
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "existing directory",
|
|
setup: func() string {
|
|
return tmpDir
|
|
},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "non-existent directory gets created",
|
|
setup: func() string {
|
|
return filepath.Join(tmpDir, "newdir")
|
|
},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "nested directory gets created",
|
|
setup: func() string {
|
|
return filepath.Join(tmpDir, "level1", "level2", "level3")
|
|
},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "file exists at path",
|
|
setup: func() string {
|
|
filePath := filepath.Join(tmpDir, "testfile")
|
|
os.WriteFile(filePath, []byte("test"), 0644)
|
|
return filePath
|
|
},
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
path := tt.setup()
|
|
err := ValidateDirectory(path)
|
|
|
|
if (err != nil) != tt.expectError {
|
|
t.Errorf("Expected error: %v, got: %v", tt.expectError, err)
|
|
}
|
|
|
|
// If no error expected, verify directory exists
|
|
if !tt.expectError {
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
t.Errorf("Directory should exist: %v", err)
|
|
}
|
|
if !info.IsDir() {
|
|
t.Errorf("Path should be a directory")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPrintFunctions(t *testing.T) {
|
|
// These functions write to stdout, so we just ensure they don't panic
|
|
// Testing colored output is complex due to terminal color codes
|
|
|
|
tests := []struct {
|
|
name string
|
|
fn func()
|
|
}{
|
|
{"PrintHeader", func() { PrintHeader("Test Header") }},
|
|
{"PrintSuccess", func() { PrintSuccess("Success message") }},
|
|
{"PrintError", func() { PrintError("Error message") }},
|
|
{"PrintInfo", func() { PrintInfo("Info message") }},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Just ensure the function doesn't panic
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
t.Errorf("Function panicked: %v", r)
|
|
}
|
|
}()
|
|
|
|
tt.fn()
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPromptDirectory(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
defaultValue string
|
|
required bool
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "valid directory path",
|
|
input: tmpDir + "\n",
|
|
defaultValue: "",
|
|
required: true,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "creates new directory",
|
|
input: filepath.Join(tmpDir, "newdir") + "\n",
|
|
defaultValue: "",
|
|
required: true,
|
|
expectError: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Note: This test would require refactoring PromptDirectory to accept a reader
|
|
// For now, we test ValidateDirectory which is the core logic
|
|
if tt.input != "" {
|
|
path := strings.TrimSpace(tt.input[:len(tt.input)-1])
|
|
err := ValidateDirectory(path)
|
|
if (err != nil) != tt.expectError {
|
|
t.Errorf("Expected error: %v, got: %v", tt.expectError, err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Benchmark tests
|
|
func BenchmarkPromptStringWithReader(b *testing.B) {
|
|
reader := &mockReader{input: strings.Repeat("test\n", b.N)}
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
promptStringWithReader(reader, "Label", "default", false)
|
|
}
|
|
}
|
|
|
|
func BenchmarkPromptIntWithReader(b *testing.B) {
|
|
reader := &mockReader{input: strings.Repeat("42\n", b.N)}
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
promptIntWithReader(reader, "Label", 0, false)
|
|
}
|
|
}
|