| | |
| | | package config |
| | | |
| | | import ( |
| | | "encoding/json" |
| | | "os" |
| | | "path/filepath" |
| | | "runtime" |
| | | "testing" |
| | | |
| | | "voicesnap/internal/model" |
| | | "voicesnap/internal/paths" |
| | | ) |
| | | |
| | | func TestDefaultLanguageConfig(t *testing.T) { |
| | |
| | | } |
| | | 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) |
| | | } |
| | | } |
| | | |
| | |
| | | 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 |
| | | } |