1package config
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8)
9
10func TestValidateKeybinds_NoConflicts(t *testing.T) {
11 kb := defaultKeybinds()
12 conflicts := ValidateKeybinds(kb)
13 if len(conflicts) != 0 {
14 t.Errorf("default keybinds have conflicts: %v", conflicts)
15 }
16}
17
18func TestValidateKeybinds_InboxConflict(t *testing.T) {
19 kb := defaultKeybinds()
20 kb.Inbox.Archive = kb.Inbox.Delete // same key as delete
21 conflicts := ValidateKeybinds(kb)
22 if len(conflicts) == 0 {
23 t.Fatal("expected conflict, got none")
24 }
25 found := false
26 for _, c := range conflicts {
27 if strings.Contains(c, "inbox") {
28 found = true
29 break
30 }
31 }
32 if !found {
33 t.Errorf("expected inbox conflict, got: %v", conflicts)
34 }
35}
36
37func TestValidateKeybinds_CrossAreaNotConflict(t *testing.T) {
38 kb := defaultKeybinds()
39 // "d" is delete in both inbox and email — intentional, not a conflict
40 kb.Inbox.Delete = "d"
41 kb.Email.Delete = "d"
42 conflicts := ValidateKeybinds(kb)
43 if len(conflicts) != 0 {
44 t.Errorf("cross-area duplicates should not be conflicts: %v", conflicts)
45 }
46}
47
48func TestValidateKeybinds_EmptyKeySkipped(t *testing.T) {
49 kb := defaultKeybinds()
50 kb.Drafts.Delete = ""
51 kb.Drafts.Open = ""
52 conflicts := ValidateKeybinds(kb)
53 if len(conflicts) != 0 {
54 t.Errorf("empty keys should not produce conflicts: %v", conflicts)
55 }
56}
57
58func TestLoadKeybindsFromDir_WritesDefault(t *testing.T) {
59 dir := t.TempDir()
60 if err := LoadKeybindsFromDir(dir); err != nil {
61 t.Fatalf("LoadKeybindsFromDir: %v", err)
62 }
63 if Keybinds.Inbox.Delete == "" {
64 t.Error("expected inbox.delete to be set after loading defaults")
65 }
66}
67
68func TestLoadKeybindsFromDir_ParsesCustom(t *testing.T) {
69 dir := t.TempDir()
70 // Write defaults first
71 if err := LoadKeybindsFromDir(dir); err != nil {
72 t.Fatalf("write defaults: %v", err)
73 }
74
75 // Override inbox delete key
76 custom := `{"inbox":{"delete":"x","archive":"a","refresh":"r","open":"enter","next_tab":"l","prev_tab":"h","visual_mode":"v"},"global":{"quit":"ctrl+c","cancel":"esc","nav_up":"k","nav_down":"j"},"email":{"reply":"r","forward":"f","delete":"d","archive":"a","toggle_images":"i","rsvp_accept":"1","rsvp_decline":"2","rsvp_tentative":"3","focus_attachments":"tab"},"composer":{"external_editor":"ctrl+e","next_field":"tab","prev_field":"shift+tab"},"folder":{"next_folder":"tab","prev_folder":"shift+tab","move":"m","focus_preview":"]","focus_inbox":"["},"drafts":{"open":"enter","delete":"d"}}`
77 if err := os.WriteFile(filepath.Join(dir, "keybinds.json"), []byte(custom), 0600); err != nil {
78 t.Fatalf("write custom: %v", err)
79 }
80 if err := LoadKeybindsFromDir(dir); err != nil {
81 t.Fatalf("LoadKeybindsFromDir custom: %v", err)
82 }
83 if Keybinds.Inbox.Delete != "x" {
84 t.Errorf("expected inbox.delete=x, got %q", Keybinds.Inbox.Delete)
85 }
86}