package config
|
|
import (
|
"encoding/json"
|
"os"
|
"path/filepath"
|
"runtime"
|
"testing"
|
|
"voicesnap/internal/model"
|
"voicesnap/internal/paths"
|
)
|
|
func TestDefaultLanguageConfig(t *testing.T) {
|
cfg := Default()
|
if cfg.LanguageMode != LanguageModeAuto {
|
t.Fatalf("language mode = %q, want %q", cfg.LanguageMode, LanguageModeAuto)
|
}
|
if cfg.LanguageID != model.DefaultLanguageID {
|
t.Fatalf("language id = %q, want %q", cfg.LanguageID, model.DefaultLanguageID)
|
}
|
if cfg.SelectedModelID != model.DefaultModelID {
|
t.Fatalf("selected model = %q, want %q", cfg.SelectedModelID, model.DefaultModelID)
|
}
|
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)
|
}
|
}
|
|
func TestNormalizeLanguageMode(t *testing.T) {
|
if got := NormalizeLanguageMode(LanguageModeManual); got != LanguageModeManual {
|
t.Fatalf("manual normalized to %q", got)
|
}
|
if got := NormalizeLanguageMode("bad"); got != LanguageModeAuto {
|
t.Fatalf("bad mode normalized to %q, want %q", got, LanguageModeAuto)
|
}
|
}
|
|
func TestNormalizeModelSelectionMode(t *testing.T) {
|
if got := NormalizeModelSelectionMode(ModelSelectionModeManual); got != ModelSelectionModeManual {
|
t.Fatalf("manual normalized to %q", got)
|
}
|
if got := NormalizeModelSelectionMode("bad"); got != ModelSelectionModeAuto {
|
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
|
}
|