Tests
This commit is contained in:
319
internal/prompt/prompt_test.go
Normal file
319
internal/prompt/prompt_test.go
Normal file
@ -0,0 +1,319 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user