mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-13 00:42:49 -05:00
rename backend to core
This commit is contained in:
499
core/internal/mangowc/keybinds_test.go
Normal file
499
core/internal/mangowc/keybinds_test.go
Normal file
@@ -0,0 +1,499 @@
|
||||
package mangowc
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAutogenerateComment(t *testing.T) {
|
||||
tests := []struct {
|
||||
command string
|
||||
params string
|
||||
expected string
|
||||
}{
|
||||
{"spawn", "kitty", "kitty"},
|
||||
{"spawn_shell", "firefox", "firefox"},
|
||||
{"killclient", "", "Close window"},
|
||||
{"quit", "", "Exit MangoWC"},
|
||||
{"reload_config", "", "Reload configuration"},
|
||||
{"focusstack", "next", "Focus next window"},
|
||||
{"focusstack", "prev", "Focus previous window"},
|
||||
{"focusdir", "left", "Focus left"},
|
||||
{"focusdir", "right", "Focus right"},
|
||||
{"focusdir", "up", "Focus up"},
|
||||
{"focusdir", "down", "Focus down"},
|
||||
{"exchange_client", "left", "Swap window left"},
|
||||
{"exchange_client", "right", "Swap window right"},
|
||||
{"togglefloating", "", "Float/unfloat window"},
|
||||
{"togglefullscreen", "", "Toggle fullscreen"},
|
||||
{"togglefakefullscreen", "", "Toggle fake fullscreen"},
|
||||
{"togglemaximizescreen", "", "Toggle maximize"},
|
||||
{"toggleglobal", "", "Toggle global"},
|
||||
{"toggleoverview", "", "Toggle overview"},
|
||||
{"toggleoverlay", "", "Toggle overlay"},
|
||||
{"minimized", "", "Minimize window"},
|
||||
{"restore_minimized", "", "Restore minimized"},
|
||||
{"toggle_scratchpad", "", "Toggle scratchpad"},
|
||||
{"setlayout", "tile", "Set layout tile"},
|
||||
{"switch_layout", "", "Switch layout"},
|
||||
{"view", "1,0", "View tag 1"},
|
||||
{"tag", "2,0", "Move to tag 2"},
|
||||
{"toggleview", "3,0", "Toggle tag 3"},
|
||||
{"viewtoleft", "", "View left tag"},
|
||||
{"viewtoright", "", "View right tag"},
|
||||
{"viewtoleft_have_client", "", "View left tag"},
|
||||
{"viewtoright_have_client", "", "View right tag"},
|
||||
{"tagtoleft", "", "Move to left tag"},
|
||||
{"tagtoright", "", "Move to right tag"},
|
||||
{"focusmon", "left", "Focus monitor left"},
|
||||
{"tagmon", "right", "Move to monitor right"},
|
||||
{"incgaps", "1", "Increase gaps"},
|
||||
{"incgaps", "-1", "Decrease gaps"},
|
||||
{"togglegaps", "", "Toggle gaps"},
|
||||
{"movewin", "+0,-50", "Move window by +0,-50"},
|
||||
{"resizewin", "+0,+50", "Resize window by +0,+50"},
|
||||
{"set_proportion", "1.0", "Set proportion 1.0"},
|
||||
{"switch_proportion_preset", "", "Switch proportion preset"},
|
||||
{"unknown", "", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.command+"_"+tt.params, func(t *testing.T) {
|
||||
result := autogenerateComment(tt.command, tt.params)
|
||||
if result != tt.expected {
|
||||
t.Errorf("autogenerateComment(%q, %q) = %q, want %q",
|
||||
tt.command, tt.params, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetKeybindAtLine(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
line string
|
||||
expected *KeyBinding
|
||||
}{
|
||||
{
|
||||
name: "basic_keybind",
|
||||
line: "bind=ALT,q,killclient,",
|
||||
expected: &KeyBinding{
|
||||
Mods: []string{"ALT"},
|
||||
Key: "q",
|
||||
Command: "killclient",
|
||||
Params: "",
|
||||
Comment: "Close window",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "keybind_with_params",
|
||||
line: "bind=ALT,Left,focusdir,left",
|
||||
expected: &KeyBinding{
|
||||
Mods: []string{"ALT"},
|
||||
Key: "Left",
|
||||
Command: "focusdir",
|
||||
Params: "left",
|
||||
Comment: "Focus left",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "keybind_with_comment",
|
||||
line: "bind=Alt,t,spawn,kitty # Open terminal",
|
||||
expected: &KeyBinding{
|
||||
Mods: []string{"Alt"},
|
||||
Key: "t",
|
||||
Command: "spawn",
|
||||
Params: "kitty",
|
||||
Comment: "Open terminal",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "keybind_hidden",
|
||||
line: "bind=SUPER,h,spawn,secret # [hidden]",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "keybind_multiple_mods",
|
||||
line: "bind=SUPER+SHIFT,Up,exchange_client,up",
|
||||
expected: &KeyBinding{
|
||||
Mods: []string{"SUPER", "SHIFT"},
|
||||
Key: "Up",
|
||||
Command: "exchange_client",
|
||||
Params: "up",
|
||||
Comment: "Swap window up",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "keybind_no_mods",
|
||||
line: "bind=NONE,Print,spawn,screenshot",
|
||||
expected: &KeyBinding{
|
||||
Mods: []string{},
|
||||
Key: "Print",
|
||||
Command: "spawn",
|
||||
Params: "screenshot",
|
||||
Comment: "screenshot",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "keybind_multiple_params",
|
||||
line: "bind=Ctrl,1,view,1,0",
|
||||
expected: &KeyBinding{
|
||||
Mods: []string{"Ctrl"},
|
||||
Key: "1",
|
||||
Command: "view",
|
||||
Params: "1,0",
|
||||
Comment: "View tag 1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bindl_flag",
|
||||
line: "bindl=SUPER+ALT,l,spawn,dms ipc call lock lock",
|
||||
expected: &KeyBinding{
|
||||
Mods: []string{"SUPER", "ALT"},
|
||||
Key: "l",
|
||||
Command: "spawn",
|
||||
Params: "dms ipc call lock lock",
|
||||
Comment: "dms ipc call lock lock",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "keybind_with_spaces",
|
||||
line: "bind = SUPER, r, reload_config",
|
||||
expected: &KeyBinding{
|
||||
Mods: []string{"SUPER"},
|
||||
Key: "r",
|
||||
Command: "reload_config",
|
||||
Params: "",
|
||||
Comment: "Reload configuration",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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.Command != tt.expected.Command {
|
||||
t.Errorf("Command = %q, want %q", result.Command, tt.expected.Command)
|
||||
}
|
||||
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 TestParseKeys(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configFile := filepath.Join(tmpDir, "config.conf")
|
||||
|
||||
content := `# MangoWC Configuration
|
||||
blur=0
|
||||
border_radius=12
|
||||
|
||||
# Key Bindings
|
||||
bind=SUPER,r,reload_config
|
||||
bind=Alt,t,spawn,kitty # Terminal
|
||||
bind=ALT,q,killclient,
|
||||
bind=ALT,Left,focusdir,left
|
||||
|
||||
# Hidden binding
|
||||
bind=SUPER,h,spawn,secret # [hidden]
|
||||
|
||||
# Multiple modifiers
|
||||
bind=SUPER+SHIFT,Up,exchange_client,up
|
||||
|
||||
# Workspace bindings
|
||||
bind=Ctrl,1,view,1,0
|
||||
bind=Ctrl,2,view,2,0
|
||||
`
|
||||
|
||||
if err := os.WriteFile(configFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
keybinds, err := ParseKeys(configFile)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseKeys failed: %v", err)
|
||||
}
|
||||
|
||||
expectedCount := 7
|
||||
if len(keybinds) != expectedCount {
|
||||
t.Errorf("Expected %d keybinds, got %d", expectedCount, len(keybinds))
|
||||
}
|
||||
|
||||
if len(keybinds) > 0 && keybinds[0].Command != "reload_config" {
|
||||
t.Errorf("First keybind command = %q, want %q", keybinds[0].Command, "reload_config")
|
||||
}
|
||||
|
||||
foundHidden := false
|
||||
for _, kb := range keybinds {
|
||||
if kb.Command == "spawn" && kb.Params == "secret" {
|
||||
foundHidden = true
|
||||
}
|
||||
}
|
||||
if foundHidden {
|
||||
t.Error("Hidden keybind should not be included in results")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadContentMultipleFiles(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
file1 := filepath.Join(tmpDir, "a.conf")
|
||||
file2 := filepath.Join(tmpDir, "b.conf")
|
||||
|
||||
content1 := "bind=ALT,q,killclient,\n"
|
||||
content2 := "bind=Alt,t,spawn,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)
|
||||
}
|
||||
|
||||
keybinds := parser.ParseKeys()
|
||||
if len(keybinds) != 2 {
|
||||
t.Errorf("Expected 2 keybinds from multiple files, got %d", len(keybinds))
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadContentSingleFile(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configFile := filepath.Join(tmpDir, "config.conf")
|
||||
|
||||
content := "bind=ALT,q,killclient,\n"
|
||||
|
||||
if err := os.WriteFile(configFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to write config: %v", err)
|
||||
}
|
||||
|
||||
parser := NewParser()
|
||||
if err := parser.ReadContent(configFile); err != nil {
|
||||
t.Fatalf("ReadContent failed: %v", err)
|
||||
}
|
||||
|
||||
keybinds := parser.ParseKeys()
|
||||
if len(keybinds) != 1 {
|
||||
t.Errorf("Expected 1 keybind, got %d", len(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-mango-"+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, "config.conf")
|
||||
if err := os.WriteFile(configFile, []byte("bind=ALT,q,killclient,\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 TestEmptyAndCommentLines(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configFile := filepath.Join(tmpDir, "config.conf")
|
||||
|
||||
content := `
|
||||
# This is a comment
|
||||
bind=ALT,q,killclient,
|
||||
|
||||
# Another comment
|
||||
|
||||
bind=Alt,t,spawn,kitty
|
||||
`
|
||||
|
||||
if err := os.WriteFile(configFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
keybinds, err := ParseKeys(configFile)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(keybinds) != 2 {
|
||||
t.Errorf("Expected 2 keybinds (comments ignored), got %d", len(keybinds))
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidBindLines(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
line string
|
||||
}{
|
||||
{
|
||||
name: "missing_parts",
|
||||
line: "bind=SUPER,q",
|
||||
},
|
||||
{
|
||||
name: "not_bind",
|
||||
line: "blur=0",
|
||||
},
|
||||
{
|
||||
name: "empty_line",
|
||||
line: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
parser := NewParser()
|
||||
parser.contentLines = []string{tt.line}
|
||||
result := parser.getKeybindAtLine(0)
|
||||
|
||||
if result != nil {
|
||||
t.Errorf("expected nil for invalid line, got %+v", result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealWorldConfig(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
configFile := filepath.Join(tmpDir, "config.conf")
|
||||
|
||||
content := `# Application Launchers
|
||||
bind=Alt,t,spawn,kitty
|
||||
bind=Alt,space,spawn,dms ipc call spotlight toggle
|
||||
bind=Alt,v,spawn,dms ipc call clipboard toggle
|
||||
|
||||
# exit
|
||||
bind=ALT+SHIFT,e,quit
|
||||
bind=ALT,q,killclient,
|
||||
|
||||
# switch window focus
|
||||
bind=SUPER,Tab,focusstack,next
|
||||
bind=ALT,Left,focusdir,left
|
||||
bind=ALT,Right,focusdir,right
|
||||
|
||||
# tag switch
|
||||
bind=SUPER,Left,viewtoleft,0
|
||||
bind=CTRL,Left,viewtoleft_have_client,0
|
||||
bind=SUPER,Right,viewtoright,0
|
||||
|
||||
bind=Ctrl,1,view,1,0
|
||||
bind=Ctrl,2,view,2,0
|
||||
bind=Ctrl,3,view,3,0
|
||||
`
|
||||
|
||||
if err := os.WriteFile(configFile, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("Failed to write test config: %v", err)
|
||||
}
|
||||
|
||||
keybinds, err := ParseKeys(configFile)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseKeys failed: %v", err)
|
||||
}
|
||||
|
||||
if len(keybinds) < 14 {
|
||||
t.Errorf("Expected at least 14 keybinds, got %d", len(keybinds))
|
||||
}
|
||||
|
||||
foundSpawn := false
|
||||
foundQuit := false
|
||||
foundView := false
|
||||
|
||||
for _, kb := range keybinds {
|
||||
if kb.Command == "spawn" && kb.Params == "kitty" {
|
||||
foundSpawn = true
|
||||
}
|
||||
if kb.Command == "quit" {
|
||||
foundQuit = true
|
||||
}
|
||||
if kb.Command == "view" && kb.Params == "1,0" {
|
||||
foundView = true
|
||||
}
|
||||
}
|
||||
|
||||
if !foundSpawn {
|
||||
t.Error("Did not find spawn kitty keybind")
|
||||
}
|
||||
if !foundQuit {
|
||||
t.Error("Did not find quit keybind")
|
||||
}
|
||||
if !foundView {
|
||||
t.Error("Did not find view workspace 1 keybind")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user