* test: Add test coverage for 16 files (40.3% -> 45.5%) Add comprehensive tests for previously untested packages: - internal/agent/state_test.go - internal/cmd/errors_test.go - internal/crew/types_test.go - internal/doctor/errors_test.go - internal/dog/types_test.go - internal/mail/bd_test.go - internal/opencode/plugin_test.go - internal/rig/overlay_test.go - internal/runtime/runtime_test.go - internal/session/town_test.go - internal/style/style_test.go - internal/ui/markdown_test.go - internal/ui/terminal_test.go - internal/wisp/io_test.go - internal/wisp/types_test.go - internal/witness/types_test.go style_test.go uses func(...string) to match lipgloss variadic Render signature. * fix(lint): remove unused error return from buildCVSummary buildCVSummary always returned nil for its error value, causing golangci-lint to fail with "result 1 (error) is always nil". The function handles errors internally by returning partial data, so the error return was misleading. Removed it and updated caller.
190 lines
4.7 KiB
Go
190 lines
4.7 KiB
Go
package agent
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestStateConstants(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
state State
|
|
value string
|
|
}{
|
|
{"StateStopped", StateStopped, "stopped"},
|
|
{"StateRunning", StateRunning, "running"},
|
|
{"StatePaused", StatePaused, "paused"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if string(tt.state) != tt.value {
|
|
t.Errorf("State constant = %q, want %q", tt.state, tt.value)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestStateManager_StateFile(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
manager := NewStateManager[TestState](tmpDir, "test-state.json", func() *TestState {
|
|
return &TestState{Value: "default"}
|
|
})
|
|
|
|
expectedPath := filepath.Join(tmpDir, ".runtime", "test-state.json")
|
|
if manager.StateFile() != expectedPath {
|
|
t.Errorf("StateFile() = %q, want %q", manager.StateFile(), expectedPath)
|
|
}
|
|
}
|
|
|
|
func TestStateManager_Load_NoFile(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
manager := NewStateManager[TestState](tmpDir, "nonexistent.json", func() *TestState {
|
|
return &TestState{Value: "default"}
|
|
})
|
|
|
|
state, err := manager.Load()
|
|
if err != nil {
|
|
t.Fatalf("Load() error = %v", err)
|
|
}
|
|
if state.Value != "default" {
|
|
t.Errorf("Load() value = %q, want %q", state.Value, "default")
|
|
}
|
|
}
|
|
|
|
func TestStateManager_Load_Save_Load(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
manager := NewStateManager[TestState](tmpDir, "test-state.json", func() *TestState {
|
|
return &TestState{Value: "default"}
|
|
})
|
|
|
|
// Save initial state
|
|
state := &TestState{Value: "test-value", Count: 42}
|
|
if err := manager.Save(state); err != nil {
|
|
t.Fatalf("Save() error = %v", err)
|
|
}
|
|
|
|
// Load it back
|
|
loaded, err := manager.Load()
|
|
if err != nil {
|
|
t.Fatalf("Load() error = %v", err)
|
|
}
|
|
if loaded.Value != state.Value {
|
|
t.Errorf("Load() value = %q, want %q", loaded.Value, state.Value)
|
|
}
|
|
if loaded.Count != state.Count {
|
|
t.Errorf("Load() count = %d, want %d", loaded.Count, state.Count)
|
|
}
|
|
}
|
|
|
|
func TestStateManager_Load_CreatesDirectory(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
manager := NewStateManager[TestState](tmpDir, "test-state.json", func() *TestState {
|
|
return &TestState{Value: "default"}
|
|
})
|
|
|
|
// Save should create .runtime directory
|
|
state := &TestState{Value: "test"}
|
|
if err := manager.Save(state); err != nil {
|
|
t.Fatalf("Save() error = %v", err)
|
|
}
|
|
|
|
// Verify directory was created
|
|
runtimeDir := filepath.Join(tmpDir, ".runtime")
|
|
if _, err := os.Stat(runtimeDir); err != nil {
|
|
t.Errorf("Save() should create .runtime directory: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestStateManager_Load_InvalidJSON(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
manager := NewStateManager[TestState](tmpDir, "test-state.json", func() *TestState {
|
|
return &TestState{Value: "default"}
|
|
})
|
|
|
|
// Write invalid JSON
|
|
statePath := manager.StateFile()
|
|
if err := os.MkdirAll(filepath.Dir(statePath), 0755); err != nil {
|
|
t.Fatalf("Failed to create directory: %v", err)
|
|
}
|
|
if err := os.WriteFile(statePath, []byte("invalid json"), 0644); err != nil {
|
|
t.Fatalf("Failed to write file: %v", err)
|
|
}
|
|
|
|
_, err := manager.Load()
|
|
if err == nil {
|
|
t.Error("Load() with invalid JSON should return error")
|
|
}
|
|
}
|
|
|
|
func TestState_String(t *testing.T) {
|
|
tests := []struct {
|
|
state State
|
|
want string
|
|
}{
|
|
{StateStopped, "stopped"},
|
|
{StateRunning, "running"},
|
|
{StatePaused, "paused"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
if string(tt.state) != tt.want {
|
|
t.Errorf("State(%q) = %q, want %q", tt.state, string(tt.state), tt.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStateManager_GenericType(t *testing.T) {
|
|
// Test that StateManager works with different types
|
|
|
|
type ComplexState struct {
|
|
Name string `json:"name"`
|
|
Values []int `json:"values"`
|
|
Enabled bool `json:"enabled"`
|
|
Nested struct {
|
|
X int `json:"x"`
|
|
} `json:"nested"`
|
|
}
|
|
|
|
tmpDir := t.TempDir()
|
|
manager := NewStateManager[ComplexState](tmpDir, "complex.json", func() *ComplexState {
|
|
return &ComplexState{Name: "default", Values: []int{}}
|
|
})
|
|
|
|
original := &ComplexState{
|
|
Name: "test",
|
|
Values: []int{1, 2, 3},
|
|
Enabled: true,
|
|
}
|
|
original.Nested.X = 42
|
|
|
|
if err := manager.Save(original); err != nil {
|
|
t.Fatalf("Save() error = %v", err)
|
|
}
|
|
|
|
loaded, err := manager.Load()
|
|
if err != nil {
|
|
t.Fatalf("Load() error = %v", err)
|
|
}
|
|
|
|
if loaded.Name != original.Name {
|
|
t.Errorf("Name = %q, want %q", loaded.Name, original.Name)
|
|
}
|
|
if len(loaded.Values) != len(original.Values) {
|
|
t.Errorf("Values length = %d, want %d", len(loaded.Values), len(original.Values))
|
|
}
|
|
if loaded.Enabled != original.Enabled {
|
|
t.Errorf("Enabled = %v, want %v", loaded.Enabled, original.Enabled)
|
|
}
|
|
if loaded.Nested.X != original.Nested.X {
|
|
t.Errorf("Nested.X = %d, want %d", loaded.Nested.X, original.Nested.X)
|
|
}
|
|
}
|
|
|
|
// TestState is a simple type for testing
|
|
type TestState struct {
|
|
Value string `json:"value"`
|
|
Count int `json:"count"`
|
|
}
|