Ariver
2026-07-06 7cec9cadc16b6daf902c89aca770f37f1843099b
C1.source/privatevoice.src/internal/config/config_test.go
@@ -1,9 +1,14 @@
package config
import (
   "encoding/json"
   "os"
   "path/filepath"
   "runtime"
   "testing"
   "voicesnap/internal/model"
   "voicesnap/internal/paths"
)
func TestDefaultLanguageConfig(t *testing.T) {
@@ -19,6 +24,117 @@
   }
   if cfg.ModelSelectionMode != ModelSelectionModeAuto {
      t.Fatalf("model selection mode = %q, want %q", cfg.ModelSelectionMode, ModelSelectionModeAuto)
   }
}
func TestDefaultHotkeyForNewConfig(t *testing.T) {
   tests := []struct {
      goos string
      want int
   }{
      {goos: "darwin", want: RightModifierDefaultVK},
      {goos: "windows", want: RightModifierDefaultVK},
      {goos: "linux", want: LegacyDefaultHotkeyVK},
   }
   for _, tt := range tests {
      if got := defaultHotkeyVKForNewConfig(tt.goos); got != tt.want {
         t.Fatalf("defaultHotkeyVKForNewConfig(%q) = 0x%X, want 0x%X", tt.goos, got, tt.want)
      }
   }
}
func TestLoadCreatesFirstConfigWithNewPlatformDefault(t *testing.T) {
   withIsolatedConfigHome(t)
   cfg, err := Load()
   if err != nil {
      t.Fatalf("Load() error = %v", err)
   }
   if got, want := cfg.HotkeyVK, defaultHotkeyVKForNewConfig(runtime.GOOS); got != want {
      t.Fatalf("HotkeyVK = 0x%X, want 0x%X", got, want)
   }
   if cfg.HotkeyMode != HotkeyModeHold {
      t.Fatalf("HotkeyMode = %q, want %q", cfg.HotkeyMode, HotkeyModeHold)
   }
   raw := readConfigJSON(t)
   if got, ok := raw["HotkeyVK"].(float64); !ok || int(got) != cfg.HotkeyVK {
      t.Fatalf("saved HotkeyVK = %#v, want %d", raw["HotkeyVK"], cfg.HotkeyVK)
   }
   if got := raw["HotkeyMode"]; got != HotkeyModeHold {
      t.Fatalf("saved HotkeyMode = %#v, want %q", got, HotkeyModeHold)
   }
}
func TestLoadExistingConfigPreservesHotkeyAndMode(t *testing.T) {
   withIsolatedConfigHome(t)
   writeConfigJSON(t, map[string]interface{}{
      "HotkeyVK":   0x41,
      "HotkeyMode": HotkeyModeTap,
   })
   cfg, err := Load()
   if err != nil {
      t.Fatalf("Load() error = %v", err)
   }
   if cfg.HotkeyVK != 0x41 {
      t.Fatalf("HotkeyVK = 0x%X, want 0x41", cfg.HotkeyVK)
   }
   if cfg.HotkeyMode != HotkeyModeTap {
      t.Fatalf("HotkeyMode = %q, want %q", cfg.HotkeyMode, HotkeyModeTap)
   }
}
func TestLoadExistingConfigMissingHotkeyUsesLegacyFallback(t *testing.T) {
   withIsolatedConfigHome(t)
   writeConfigJSON(t, map[string]interface{}{
      "HotkeyMode": HotkeyModeTap,
   })
   cfg, err := Load()
   if err != nil {
      t.Fatalf("Load() error = %v", err)
   }
   if cfg.HotkeyVK != LegacyDefaultHotkeyVK {
      t.Fatalf("HotkeyVK = 0x%X, want legacy 0x%X", cfg.HotkeyVK, LegacyDefaultHotkeyVK)
   }
   if cfg.HotkeyVK == RightModifierDefaultVK {
      t.Fatalf("existing config missing HotkeyVK must not inherit new default 0x%X", RightModifierDefaultVK)
   }
   if cfg.HotkeyMode != HotkeyModeTap {
      t.Fatalf("HotkeyMode = %q, want %q", cfg.HotkeyMode, HotkeyModeTap)
   }
}
func TestLoadExistingConfigMissingModeKeepsLegacyHoldFallback(t *testing.T) {
   withIsolatedConfigHome(t)
   writeConfigJSON(t, map[string]interface{}{
      "HotkeyVK": 0x41,
   })
   cfg, err := Load()
   if err != nil {
      t.Fatalf("Load() error = %v", err)
   }
   if cfg.HotkeyVK != 0x41 {
      t.Fatalf("HotkeyVK = 0x%X, want 0x41", cfg.HotkeyVK)
   }
   if cfg.HotkeyMode != HotkeyModeHold {
      t.Fatalf("HotkeyMode = %q, want %q", cfg.HotkeyMode, HotkeyModeHold)
   }
}
func TestExistingConfigFallbackUsesLegacyHotkey(t *testing.T) {
   cfg := ExistingConfigFallback()
   if cfg.HotkeyVK != LegacyDefaultHotkeyVK {
      t.Fatalf("HotkeyVK = 0x%X, want legacy 0x%X", cfg.HotkeyVK, LegacyDefaultHotkeyVK)
   }
   if cfg.HotkeyVK == RightModifierDefaultVK {
      t.Fatalf("existing config fallback must not inherit new default 0x%X", RightModifierDefaultVK)
   }
   if cfg.HotkeyMode != HotkeyModeHold {
      t.Fatalf("HotkeyMode = %q, want %q", cfg.HotkeyMode, HotkeyModeHold)
   }
}
@@ -39,3 +155,37 @@
      t.Fatalf("bad mode normalized to %q, want %q", got, ModelSelectionModeAuto)
   }
}
func withIsolatedConfigHome(t *testing.T) {
   t.Helper()
   home := t.TempDir()
   t.Setenv("HOME", home)
   t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config"))
}
func writeConfigJSON(t *testing.T, value map[string]interface{}) {
   t.Helper()
   if err := paths.Ensure(); err != nil {
      t.Fatalf("paths.Ensure() error = %v", err)
   }
   data, err := json.Marshal(value)
   if err != nil {
      t.Fatalf("json.Marshal() error = %v", err)
   }
   if err := os.WriteFile(paths.File("config.json"), data, 0644); err != nil {
      t.Fatalf("write config error = %v", err)
   }
}
func readConfigJSON(t *testing.T) map[string]interface{} {
   t.Helper()
   data, err := os.ReadFile(paths.File("config.json"))
   if err != nil {
      t.Fatalf("read config error = %v", err)
   }
   var raw map[string]interface{}
   if err := json.Unmarshal(data, &raw); err != nil {
      t.Fatalf("json.Unmarshal() error = %v", err)
   }
   return raw
}