1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00
Files
DankMaterialShell/backend/internal/hyprland/keybinds_test.go
2025-11-12 17:18:45 -05:00

397 lines
11 KiB
Go

package hyprland
import (
"os"
"path/filepath"
"testing"
)
func TestAutogenerateComment(t *testing.T) {
tests := []struct {
dispatcher string
params string
expected string
}{
{"resizewindow", "", "Resize window"},
{"movewindow", "", "Move window"},
{"movewindow", "l", "move in left direction"},
{"movewindow", "r", "move in right direction"},
{"movewindow", "u", "move in up direction"},
{"movewindow", "d", "move in down direction"},
{"pin", "", "pin (show on all workspaces)"},
{"splitratio", "0.5", "Window split ratio 0.5"},
{"togglefloating", "", "Float/unfloat window"},
{"resizeactive", "10 20", "Resize window by 10 20"},
{"killactive", "", "Close window"},
{"fullscreen", "0", "Toggle fullscreen"},
{"fullscreen", "1", "Toggle maximization"},
{"fullscreen", "2", "Toggle fullscreen on Hyprland's side"},
{"fakefullscreen", "", "Toggle fake fullscreen"},
{"workspace", "+1", "focus right"},
{"workspace", "-1", "focus left"},
{"workspace", "5", "focus workspace 5"},
{"movefocus", "l", "move focus left"},
{"movefocus", "r", "move focus right"},
{"movefocus", "u", "move focus up"},
{"movefocus", "d", "move focus down"},
{"swapwindow", "l", "swap in left direction"},
{"swapwindow", "r", "swap in right direction"},
{"swapwindow", "u", "swap in up direction"},
{"swapwindow", "d", "swap in down direction"},
{"movetoworkspace", "+1", "move to right workspace (non-silent)"},
{"movetoworkspace", "-1", "move to left workspace (non-silent)"},
{"movetoworkspace", "3", "move to workspace 3 (non-silent)"},
{"movetoworkspacesilent", "+1", "move to right workspace"},
{"movetoworkspacesilent", "-1", "move to right workspace"},
{"movetoworkspacesilent", "2", "move to workspace 2"},
{"togglespecialworkspace", "", "toggle special"},
{"exec", "firefox", "firefox"},
{"unknown", "", ""},
}
for _, tt := range tests {
t.Run(tt.dispatcher+"_"+tt.params, func(t *testing.T) {
result := autogenerateComment(tt.dispatcher, tt.params)
if result != tt.expected {
t.Errorf("autogenerateComment(%q, %q) = %q, want %q",
tt.dispatcher, tt.params, result, tt.expected)
}
})
}
}
func TestGetKeybindAtLine(t *testing.T) {
tests := []struct {
name string
line string
expected *KeyBinding
}{
{
name: "basic_keybind",
line: "bind = SUPER, Q, killactive",
expected: &KeyBinding{
Mods: []string{"SUPER"},
Key: "Q",
Dispatcher: "killactive",
Params: "",
Comment: "Close window",
},
},
{
name: "keybind_with_params",
line: "bind = SUPER, left, movefocus, l",
expected: &KeyBinding{
Mods: []string{"SUPER"},
Key: "left",
Dispatcher: "movefocus",
Params: "l",
Comment: "move focus left",
},
},
{
name: "keybind_with_comment",
line: "bind = SUPER, T, exec, kitty # Open terminal",
expected: &KeyBinding{
Mods: []string{"SUPER"},
Key: "T",
Dispatcher: "exec",
Params: "kitty",
Comment: "Open terminal",
},
},
{
name: "keybind_hidden",
line: "bind = SUPER, H, exec, secret # [hidden]",
expected: nil,
},
{
name: "keybind_multiple_mods",
line: "bind = SUPER+SHIFT, F, fullscreen, 0",
expected: &KeyBinding{
Mods: []string{"SUPER", "SHIFT"},
Key: "F",
Dispatcher: "fullscreen",
Params: "0",
Comment: "Toggle fullscreen",
},
},
{
name: "keybind_no_mods",
line: "bind = , Print, exec, screenshot",
expected: &KeyBinding{
Mods: []string{},
Key: "Print",
Dispatcher: "exec",
Params: "screenshot",
Comment: "screenshot",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
parser := NewParser()
parser.contentLines = []string{tt.line}
result := parser.getKeybindAtLine(0)
if tt.expected == nil {
if result != nil {
t.Errorf("expected nil, got %+v", result)
}
return
}
if result == nil {
t.Errorf("expected %+v, got nil", tt.expected)
return
}
if result.Key != tt.expected.Key {
t.Errorf("Key = %q, want %q", result.Key, tt.expected.Key)
}
if result.Dispatcher != tt.expected.Dispatcher {
t.Errorf("Dispatcher = %q, want %q", result.Dispatcher, tt.expected.Dispatcher)
}
if result.Params != tt.expected.Params {
t.Errorf("Params = %q, want %q", result.Params, tt.expected.Params)
}
if result.Comment != tt.expected.Comment {
t.Errorf("Comment = %q, want %q", result.Comment, tt.expected.Comment)
}
if len(result.Mods) != len(tt.expected.Mods) {
t.Errorf("Mods length = %d, want %d", len(result.Mods), len(tt.expected.Mods))
} else {
for i := range result.Mods {
if result.Mods[i] != tt.expected.Mods[i] {
t.Errorf("Mods[%d] = %q, want %q", i, result.Mods[i], tt.expected.Mods[i])
}
}
}
})
}
}
func TestParseKeysWithSections(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
`
if err := os.WriteFile(configFile, []byte(content), 0644); err != nil {
t.Fatalf("Failed to write test config: %v", err)
}
section, err := ParseKeys(tmpDir)
if err != nil {
t.Fatalf("ParseKeys failed: %v", err)
}
if len(section.Children) != 2 {
t.Errorf("Expected 2 top-level sections, got %d", len(section.Children))
}
if len(section.Children) >= 1 {
windowMgmt := section.Children[0]
if windowMgmt.Name != "Window Management" {
t.Errorf("First section name = %q, want %q", windowMgmt.Name, "Window Management")
}
if len(windowMgmt.Keybinds) != 2 {
t.Errorf("Window Management keybinds = %d, want 2", len(windowMgmt.Keybinds))
}
if len(windowMgmt.Children) != 1 {
t.Errorf("Window Management children = %d, want 1", len(windowMgmt.Children))
} else {
movement := windowMgmt.Children[0]
if movement.Name != "Movement" {
t.Errorf("Movement section name = %q, want %q", movement.Name, "Movement")
}
if len(movement.Keybinds) != 2 {
t.Errorf("Movement keybinds = %d, want 2", len(movement.Keybinds))
}
}
}
if len(section.Children) >= 2 {
apps := section.Children[1]
if apps.Name != "Applications" {
t.Errorf("Second section name = %q, want %q", apps.Name, "Applications")
}
if len(apps.Keybinds) != 1 {
t.Errorf("Applications keybinds = %d, want 1", len(apps.Keybinds))
}
if len(apps.Keybinds) > 0 && apps.Keybinds[0].Comment != "Terminal" {
t.Errorf("Applications keybind comment = %q, want %q", apps.Keybinds[0].Comment, "Terminal")
}
}
}
func TestParseKeysWithCommentBinds(t *testing.T) {
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "test.conf")
content := `#/# = SUPER, A, exec, app1
bind = SUPER, B, exec, app2
#/# = SUPER, C, exec, app3 # Custom comment
`
if err := os.WriteFile(configFile, []byte(content), 0644); err != nil {
t.Fatalf("Failed to write test config: %v", err)
}
section, err := ParseKeys(tmpDir)
if err != nil {
t.Fatalf("ParseKeys failed: %v", err)
}
if len(section.Keybinds) != 3 {
t.Errorf("Expected 3 keybinds, got %d", len(section.Keybinds))
}
if len(section.Keybinds) > 0 && section.Keybinds[0].Key != "A" {
t.Errorf("First keybind key = %q, want %q", section.Keybinds[0].Key, "A")
}
if len(section.Keybinds) > 1 && section.Keybinds[1].Key != "B" {
t.Errorf("Second keybind key = %q, want %q", section.Keybinds[1].Key, "B")
}
if len(section.Keybinds) > 2 && section.Keybinds[2].Comment != "Custom comment" {
t.Errorf("Third keybind comment = %q, want %q", section.Keybinds[2].Comment, "Custom comment")
}
}
func TestReadContentMultipleFiles(t *testing.T) {
tmpDir := t.TempDir()
file1 := filepath.Join(tmpDir, "a.conf")
file2 := filepath.Join(tmpDir, "b.conf")
content1 := "bind = SUPER, Q, killactive\n"
content2 := "bind = SUPER, T, exec, kitty\n"
if err := os.WriteFile(file1, []byte(content1), 0644); err != nil {
t.Fatalf("Failed to write file1: %v", err)
}
if err := os.WriteFile(file2, []byte(content2), 0644); err != nil {
t.Fatalf("Failed to write file2: %v", err)
}
parser := NewParser()
if err := parser.ReadContent(tmpDir); err != nil {
t.Fatalf("ReadContent failed: %v", err)
}
section := parser.ParseKeys()
if len(section.Keybinds) != 2 {
t.Errorf("Expected 2 keybinds from multiple files, got %d", len(section.Keybinds))
}
}
func TestReadContentErrors(t *testing.T) {
tests := []struct {
name string
path string
}{
{
name: "nonexistent_directory",
path: "/nonexistent/path/that/does/not/exist",
},
{
name: "empty_directory",
path: t.TempDir(),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := ParseKeys(tt.path)
if err == nil {
t.Error("Expected error, got nil")
}
})
}
}
func TestReadContentWithTildeExpansion(t *testing.T) {
homeDir, err := os.UserHomeDir()
if err != nil {
t.Skip("Cannot get home directory")
}
tmpSubdir := filepath.Join(homeDir, ".config", "test-hypr-"+t.Name())
if err := os.MkdirAll(tmpSubdir, 0755); err != nil {
t.Skip("Cannot create test directory in home")
}
defer os.RemoveAll(tmpSubdir)
configFile := filepath.Join(tmpSubdir, "test.conf")
if err := os.WriteFile(configFile, []byte("bind = SUPER, Q, killactive\n"), 0644); err != nil {
t.Fatalf("Failed to write test config: %v", err)
}
relPath, err := filepath.Rel(homeDir, tmpSubdir)
if err != nil {
t.Skip("Cannot create relative path")
}
parser := NewParser()
tildePathMatch := "~/" + relPath
err = parser.ReadContent(tildePathMatch)
if err != nil {
t.Errorf("ReadContent with tilde path failed: %v", err)
}
}
func TestKeybindWithParamsContainingCommas(t *testing.T) {
parser := NewParser()
parser.contentLines = []string{"bind = SUPER, R, exec, notify-send 'Title' 'Message, with comma'"}
result := parser.getKeybindAtLine(0)
if result == nil {
t.Fatal("Expected keybind, got nil")
}
expected := "notify-send 'Title' 'Message, with comma'"
if result.Params != expected {
t.Errorf("Params = %q, want %q", result.Params, expected)
}
}
func TestEmptyAndCommentLines(t *testing.T) {
tmpDir := t.TempDir()
configFile := filepath.Join(tmpDir, "test.conf")
content := `
# This is a comment
bind = SUPER, Q, killactive
# Another comment
bind = SUPER, T, exec, kitty
`
if err := os.WriteFile(configFile, []byte(content), 0644); err != nil {
t.Fatalf("Failed to write test config: %v", err)
}
section, err := ParseKeys(tmpDir)
if err != nil {
t.Fatalf("ParseKeys failed: %v", err)
}
if len(section.Keybinds) != 2 {
t.Errorf("Expected 2 keybinds (comments ignored), got %d", len(section.Keybinds))
}
}