package providers import ( "os" "path/filepath" "testing" ) func TestNewHyprlandProvider(t *testing.T) { t.Run("custom path", func(t *testing.T) { p := NewHyprlandProvider("/custom/path") if p == nil { t.Fatal("NewHyprlandProvider returned nil") } if p.configPath != "/custom/path" { t.Errorf("configPath = %q, want %q", p.configPath, "/custom/path") } }) t.Run("empty path defaults", func(t *testing.T) { p := NewHyprlandProvider("") if p == nil { t.Fatal("NewHyprlandProvider returned nil") } configDir, err := os.UserConfigDir() if err != nil { t.Fatalf("UserConfigDir failed: %v", err) } expected := filepath.Join(configDir, "hypr") if p.configPath != expected { t.Errorf("configPath = %q, want %q", p.configPath, expected) } }) } func TestHyprlandProviderName(t *testing.T) { p := NewHyprlandProvider("") if p.Name() != "hyprland" { t.Errorf("Name() = %q, want %q", p.Name(), "hyprland") } } func TestHyprlandProviderGetCheatSheet(t *testing.T) { tmpDir := t.TempDir() configFile := filepath.Join(tmpDir, "hyprland.conf") content := `##! Window Management bind = SUPER, Q, killactive bind = SUPER, F, fullscreen, 0 ###! Movement bind = SUPER, left, movefocus, l bind = SUPER, right, movefocus, r ##! Applications bind = SUPER, T, exec, kitty # Terminal bind = SUPER, 1, workspace, 1 ` if err := os.WriteFile(configFile, []byte(content), 0644); err != nil { t.Fatalf("Failed to write test config: %v", err) } p := NewHyprlandProvider(tmpDir) sheet, err := p.GetCheatSheet() if err != nil { t.Fatalf("GetCheatSheet failed: %v", err) } if sheet.Title != "Hyprland Keybinds" { t.Errorf("Title = %q, want %q", sheet.Title, "Hyprland Keybinds") } if sheet.Provider != "hyprland" { t.Errorf("Provider = %q, want %q", sheet.Provider, "hyprland") } if len(sheet.Binds) == 0 { t.Error("expected categorized bindings, got none") } if windowBinds, ok := sheet.Binds["Window"]; !ok || len(windowBinds) == 0 { t.Error("expected Window category with bindings") } if execBinds, ok := sheet.Binds["Execute"]; !ok || len(execBinds) == 0 { t.Error("expected Execute category with bindings") } if wsBinds, ok := sheet.Binds["Workspace"]; !ok || len(wsBinds) == 0 { t.Error("expected Workspace category with bindings") } } func TestHyprlandProviderGetCheatSheetError(t *testing.T) { p := NewHyprlandProvider("/nonexistent/path") _, err := p.GetCheatSheet() if err == nil { t.Error("expected error for nonexistent path, got nil") } } func TestFormatKey(t *testing.T) { tmpDir := t.TempDir() configFile := filepath.Join(tmpDir, "hyprland.conf") tests := []struct { name string content string expected string category string }{ { name: "single mod", content: "bind = SUPER, Q, killactive", expected: "SUPER+Q", category: "Window", }, { name: "multiple mods", content: "bind = SUPER+SHIFT, F, fullscreen, 0", expected: "SUPER+SHIFT+F", category: "Window", }, { name: "no mods", content: "bind = , Print, exec, screenshot", expected: "Print", category: "Execute", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := os.WriteFile(configFile, []byte(tt.content), 0644); err != nil { t.Fatalf("Failed to write test config: %v", err) } p := NewHyprlandProvider(tmpDir) sheet, err := p.GetCheatSheet() if err != nil { t.Fatalf("GetCheatSheet failed: %v", err) } categoryBinds, ok := sheet.Binds[tt.category] if !ok || len(categoryBinds) == 0 { t.Fatalf("expected binds in category %q", tt.category) } if categoryBinds[0].Key != tt.expected { t.Errorf("Key = %q, want %q", categoryBinds[0].Key, tt.expected) } }) } } func TestDescriptionFallback(t *testing.T) { tmpDir := t.TempDir() configFile := filepath.Join(tmpDir, "hyprland.conf") tests := []struct { name string content string wantDesc string }{ { name: "autogenerated description for known dispatcher", content: "bind = SUPER, Q, killactive", wantDesc: "Close window", }, { name: "custom comment overrides autogeneration", content: "bind = SUPER, T, exec, kitty # Open terminal", wantDesc: "Open terminal", }, { name: "fallback for unknown dispatcher without params", content: "bind = SUPER, W, unknowndispatcher", wantDesc: "unknowndispatcher", }, { name: "fallback for unknown dispatcher with params", content: "bind = SUPER, X, customdispatcher, arg1", wantDesc: "customdispatcher arg1", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := os.WriteFile(configFile, []byte(tt.content), 0644); err != nil { t.Fatalf("Failed to write test config: %v", err) } p := NewHyprlandProvider(tmpDir) sheet, err := p.GetCheatSheet() if err != nil { t.Fatalf("GetCheatSheet failed: %v", err) } found := false for _, binds := range sheet.Binds { for _, bind := range binds { if bind.Description == tt.wantDesc { found = true break } } if found { break } } if !found { t.Errorf("expected description %q not found in any bind", tt.wantDesc) } }) } }