From 7ed43baaa6be88a55952a3411575922c8d883a08 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 06 Jul 2026 15:47:42 +0800
Subject: [PATCH] feat: default right modifier hotkey
---
C1.source/privatevoice.src/internal/config/config_test.go | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 150 insertions(+), 0 deletions(-)
diff --git a/C1.source/privatevoice.src/internal/config/config_test.go b/C1.source/privatevoice.src/internal/config/config_test.go
index c04af51..c6d94aa 100644
--- a/C1.source/privatevoice.src/internal/config/config_test.go
+++ b/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
+}
--
Gitblit v1.9.3