1
0
streamdeck-lets-go/autoswitch_test.go
Maksim Totmin f65ff75a43 Initial commit: Stream Deck daemon with web UI
- Web-based key editor (Alpine.js SPA)
- Actions: shell commands, scripts, built-in media/volume/brightness, page switching
- Keyboard shortcut action (wtype/xdotool)
- On-device display with periodic command output
- Auto page switching (Hyprland, Sway, Niri, GNOME, KDE, X11)
- Screensaver with idle detection
- Config hot-reload
- Multi-device support
2026-06-16 22:35:14 +07:00

224 lines
5.0 KiB
Go

package main
import (
"encoding/json"
"testing"
"streamdeck-lets-go/internal/config"
)
func TestFindFocusedSwayNode(t *testing.T) {
input := `{
"id": 0,
"type": "root",
"nodes": [
{
"type": "output",
"name": "eDP-1",
"nodes": [
{
"type": "workspace",
"name": "1",
"nodes": [
{
"type": "con",
"focused": false,
"app_id": "firefox",
"name": "Firefox",
"nodes": []
}
]
},
{
"type": "workspace",
"name": "2",
"nodes": [
{
"type": "con",
"focused": true,
"app_id": "Alacritty",
"name": "Alacritty",
"nodes": []
}
]
}
],
"floating_nodes": []
}
]
}`
var root swayNode
if err := json.Unmarshal([]byte(input), &root); err != nil {
t.Fatal(err)
}
node := findFocusedSwayNode(&root)
if node == nil {
t.Fatal("expected focused node, got nil")
}
if node.AppID == nil || *node.AppID != "Alacritty" {
t.Fatalf("expected Alacritty, got %v", node.AppID)
}
if node.Name != "Alacritty" {
t.Fatalf("expected name Alacritty, got %s", node.Name)
}
}
func TestFindFocusedSwayNode_XWayland(t *testing.T) {
input := `{
"id": 0,
"type": "root",
"nodes": [
{
"type": "output",
"nodes": [
{
"type": "workspace",
"nodes": [
{
"type": "con",
"focused": true,
"app_id": null,
"name": "Steam",
"window_properties": {"class": "steam"},
"nodes": []
}
]
}
]
}
]
}`
var root swayNode
json.Unmarshal([]byte(input), &root)
node := findFocusedSwayNode(&root)
if node == nil {
t.Fatal("expected focused node, got nil")
}
if node.Props == nil || node.Props.Class != "steam" {
t.Fatal("expected window_properties.class = steam")
}
}
func TestFindFocusedSwayNode_NoFocus(t *testing.T) {
input := `{
"id": 0,
"type": "root",
"nodes": [
{
"type": "output",
"nodes": [
{
"type": "workspace",
"nodes": [
{
"type": "con",
"focused": false,
"app_id": "kitty",
"name": "kitty",
"nodes": []
}
]
}
]
}
]
}`
var root swayNode
json.Unmarshal([]byte(input), &root)
node := findFocusedSwayNode(&root)
if node != nil {
t.Fatal("expected nil when no focused node")
}
}
func TestAutoSwitchManager_Evaluate(t *testing.T) {
rules := []config.SwitchRule{
{WMClass: "firefox", Page: "browser"},
{WMClass: "Alacritty|kitty", Title: ".*vim.*", Page: "coding", Stay: true},
}
m := NewAutoSwitchManager(rules, "default")
page, ok := m.Evaluate(Window{WMClass: "firefox", Title: "Mozilla Firefox"}, "default")
if !ok || page != "browser" {
t.Fatalf("expected browser, got %s/%v", page, ok)
}
page, ok = m.Evaluate(Window{WMClass: "Alacritty", Title: "nvim main.go"}, "default")
if !ok || page != "coding" {
t.Fatalf("expected coding, got %s/%v", page, ok)
}
page, ok = m.Evaluate(Window{WMClass: "firefox", Title: "YouTube"}, "browser")
if !ok || page != "browser" {
t.Fatalf("expected browser again, got %s/%v", page, ok)
}
}
func TestAutoSwitchManager_Stay(t *testing.T) {
rules := []config.SwitchRule{
{WMClass: "firefox", Page: "browser", Stay: false},
}
m := NewAutoSwitchManager(rules, "home")
m.Evaluate(Window{WMClass: "firefox", Title: "Mozilla Firefox"}, "home")
page, ok := m.Evaluate(Window{WMClass: "thunar", Title: "Files"}, "browser")
if !ok || page != "home" {
t.Fatalf("expected revert to home, got %s/%v", page, ok)
}
}
func TestAutoSwitchManager_StayTrue(t *testing.T) {
rules := []config.SwitchRule{
{WMClass: "firefox", Page: "browser", Stay: true},
}
m := NewAutoSwitchManager(rules, "home")
m.Evaluate(Window{WMClass: "firefox", Title: "Mozilla Firefox"}, "home")
page, ok := m.Evaluate(Window{WMClass: "thunar", Title: "Files"}, "browser")
if ok {
t.Fatalf("expected no switch (stay=true), got %s", page)
}
}
func TestAutoSwitchManager_ManualOverride(t *testing.T) {
rules := []config.SwitchRule{
{WMClass: "firefox", Page: "browser", Stay: false},
}
m := NewAutoSwitchManager(rules, "home")
// 1. Firefox opens → auto-switch to "browser"
m.Evaluate(Window{WMClass: "firefox", Title: "Mozilla Firefox"}, "home")
// 2. User manually switches to "settings"
m.NotifyManualPage("settings")
// 3. Window changes to thunar on "settings" → no match → stay on settings
page, ok := m.Evaluate(Window{WMClass: "thunar", Title: "Files"}, "settings")
if ok {
t.Fatalf("expected no switch (already on manual page), got %s", page)
}
// 4. Firefox comes back → auto-switch to "browser" again
page, ok = m.Evaluate(Window{WMClass: "firefox", Title: "Mozilla Firefox"}, "settings")
if !ok || page != "browser" {
t.Fatalf("expected browser, got %s/%v", page, ok)
}
// 5. Thunar again, current page is "browser" (auto) → no match → revert to "settings"
page, ok = m.Evaluate(Window{WMClass: "thunar", Title: "Files"}, "browser")
if !ok || page != "settings" {
t.Fatalf("expected revert to settings, got %s/%v", page, ok)
}
}