Implement wisp-based config storage at .beads-wisp/config/<rig>.json for local-only settings that are never synced via git. API: - Get(key) - returns value or nil - Set(key, value) - stores value - Block(key) - marks key as blocked (NullValue equivalent) - Unset(key) - removes from values and blocked - IsBlocked(key) - checks if blocked (gt-3w685) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
225 lines
5.4 KiB
Go
225 lines
5.4 KiB
Go
package wisp
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestConfig_BasicOperations(t *testing.T) {
|
|
// Create temp directory for test
|
|
tmpDir := t.TempDir()
|
|
rigName := "testrig"
|
|
|
|
cfg := NewConfig(tmpDir, rigName)
|
|
|
|
// Test initial state - Get returns nil
|
|
if got := cfg.Get("key1"); got != nil {
|
|
t.Errorf("Get(key1) = %v, want nil", got)
|
|
}
|
|
|
|
// Test Set and Get
|
|
if err := cfg.Set("key1", "value1"); err != nil {
|
|
t.Fatalf("Set(key1) error: %v", err)
|
|
}
|
|
|
|
if got := cfg.Get("key1"); got != "value1" {
|
|
t.Errorf("Get(key1) = %v, want value1", got)
|
|
}
|
|
|
|
// Test GetString
|
|
if got := cfg.GetString("key1"); got != "value1" {
|
|
t.Errorf("GetString(key1) = %v, want value1", got)
|
|
}
|
|
|
|
// Test file was created in correct location
|
|
expectedPath := filepath.Join(tmpDir, WispConfigDir, ConfigSubdir, rigName+".json")
|
|
if _, err := os.Stat(expectedPath); os.IsNotExist(err) {
|
|
t.Errorf("Config file not created at expected path: %s", expectedPath)
|
|
}
|
|
}
|
|
|
|
func TestConfig_Block(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
cfg := NewConfig(tmpDir, "testrig")
|
|
|
|
// Set a value first
|
|
if err := cfg.Set("key1", "value1"); err != nil {
|
|
t.Fatalf("Set(key1) error: %v", err)
|
|
}
|
|
|
|
// Verify it's not blocked
|
|
if cfg.IsBlocked("key1") {
|
|
t.Error("key1 should not be blocked initially")
|
|
}
|
|
|
|
// Block the key
|
|
if err := cfg.Block("key1"); err != nil {
|
|
t.Fatalf("Block(key1) error: %v", err)
|
|
}
|
|
|
|
// Verify it's blocked
|
|
if !cfg.IsBlocked("key1") {
|
|
t.Error("key1 should be blocked after Block()")
|
|
}
|
|
|
|
// Get should return nil for blocked key
|
|
if got := cfg.Get("key1"); got != nil {
|
|
t.Errorf("Get(key1) = %v, want nil for blocked key", got)
|
|
}
|
|
|
|
// Set should be ignored for blocked key
|
|
if err := cfg.Set("key1", "newvalue"); err != nil {
|
|
t.Fatalf("Set on blocked key error: %v", err)
|
|
}
|
|
if got := cfg.Get("key1"); got != nil {
|
|
t.Errorf("Get(key1) after Set = %v, want nil (blocked key)", got)
|
|
}
|
|
}
|
|
|
|
func TestConfig_Unset(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
cfg := NewConfig(tmpDir, "testrig")
|
|
|
|
// Set and then unset
|
|
if err := cfg.Set("key1", "value1"); err != nil {
|
|
t.Fatalf("Set(key1) error: %v", err)
|
|
}
|
|
if err := cfg.Unset("key1"); err != nil {
|
|
t.Fatalf("Unset(key1) error: %v", err)
|
|
}
|
|
if got := cfg.Get("key1"); got != nil {
|
|
t.Errorf("Get(key1) after Unset = %v, want nil", got)
|
|
}
|
|
|
|
// Block and then unset
|
|
if err := cfg.Block("key2"); err != nil {
|
|
t.Fatalf("Block(key2) error: %v", err)
|
|
}
|
|
if !cfg.IsBlocked("key2") {
|
|
t.Error("key2 should be blocked")
|
|
}
|
|
if err := cfg.Unset("key2"); err != nil {
|
|
t.Fatalf("Unset(key2) error: %v", err)
|
|
}
|
|
if cfg.IsBlocked("key2") {
|
|
t.Error("key2 should not be blocked after Unset")
|
|
}
|
|
}
|
|
|
|
func TestConfig_TypedGetters(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
cfg := NewConfig(tmpDir, "testrig")
|
|
|
|
// Test GetBool
|
|
if err := cfg.Set("enabled", true); err != nil {
|
|
t.Fatalf("Set(enabled) error: %v", err)
|
|
}
|
|
if got := cfg.GetBool("enabled"); !got {
|
|
t.Error("GetBool(enabled) = false, want true")
|
|
}
|
|
if got := cfg.GetBool("nonexistent"); got {
|
|
t.Error("GetBool(nonexistent) = true, want false")
|
|
}
|
|
|
|
// GetString on non-string returns empty
|
|
if got := cfg.GetString("enabled"); got != "" {
|
|
t.Errorf("GetString(enabled) = %q, want empty for bool value", got)
|
|
}
|
|
}
|
|
|
|
func TestConfig_AllAndKeys(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
cfg := NewConfig(tmpDir, "testrig")
|
|
|
|
// Set some values
|
|
_ = cfg.Set("key1", "value1")
|
|
_ = cfg.Set("key2", 42)
|
|
_ = cfg.Block("key3")
|
|
|
|
// Test All (should not include blocked)
|
|
all := cfg.All()
|
|
if len(all) != 2 {
|
|
t.Errorf("All() returned %d items, want 2", len(all))
|
|
}
|
|
if all["key1"] != "value1" {
|
|
t.Errorf("All()[key1] = %v, want value1", all["key1"])
|
|
}
|
|
|
|
// Test BlockedKeys
|
|
blocked := cfg.BlockedKeys()
|
|
if len(blocked) != 1 || blocked[0] != "key3" {
|
|
t.Errorf("BlockedKeys() = %v, want [key3]", blocked)
|
|
}
|
|
|
|
// Test Keys (includes both)
|
|
keys := cfg.Keys()
|
|
if len(keys) != 3 {
|
|
t.Errorf("Keys() returned %d items, want 3", len(keys))
|
|
}
|
|
}
|
|
|
|
func TestConfig_Clear(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
cfg := NewConfig(tmpDir, "testrig")
|
|
|
|
// Set some values and blocks
|
|
_ = cfg.Set("key1", "value1")
|
|
_ = cfg.Block("key2")
|
|
|
|
// Clear
|
|
if err := cfg.Clear(); err != nil {
|
|
t.Fatalf("Clear() error: %v", err)
|
|
}
|
|
|
|
// Verify everything is gone
|
|
if got := cfg.Get("key1"); got != nil {
|
|
t.Errorf("Get(key1) after Clear = %v, want nil", got)
|
|
}
|
|
if cfg.IsBlocked("key2") {
|
|
t.Error("key2 should not be blocked after Clear")
|
|
}
|
|
}
|
|
|
|
func TestConfig_Persistence(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
rigName := "testrig"
|
|
|
|
// Create first config instance and set value
|
|
cfg1 := NewConfig(tmpDir, rigName)
|
|
if err := cfg1.Set("persistent", "value"); err != nil {
|
|
t.Fatalf("Set error: %v", err)
|
|
}
|
|
if err := cfg1.Block("blocked"); err != nil {
|
|
t.Fatalf("Block error: %v", err)
|
|
}
|
|
|
|
// Create second config instance and verify persistence
|
|
cfg2 := NewConfig(tmpDir, rigName)
|
|
if got := cfg2.Get("persistent"); got != "value" {
|
|
t.Errorf("Persistence: Get(persistent) = %v, want value", got)
|
|
}
|
|
if !cfg2.IsBlocked("blocked") {
|
|
t.Error("Persistence: blocked key should persist")
|
|
}
|
|
}
|
|
|
|
func TestConfig_MultipleRigs(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
|
|
cfg1 := NewConfig(tmpDir, "rig1")
|
|
cfg2 := NewConfig(tmpDir, "rig2")
|
|
|
|
// Set different values
|
|
_ = cfg1.Set("key", "value1")
|
|
_ = cfg2.Set("key", "value2")
|
|
|
|
// Verify isolation
|
|
if got := cfg1.Get("key"); got != "value1" {
|
|
t.Errorf("rig1 Get(key) = %v, want value1", got)
|
|
}
|
|
if got := cfg2.Get("key"); got != "value2" {
|
|
t.Errorf("rig2 Get(key) = %v, want value2", got)
|
|
}
|
|
}
|