package config import ( "os" "path/filepath" "strings" "testing" ) func TestDefaultValid(t *testing.T) { if err := Default().Validate(); err != nil { t.Fatal(err) } } func TestLayoutFallback(t *testing.T) { c := Default() if _, ok := c.LayoutFor(`\\.\DISPLAY99`); !ok { t.Fatal("expected wildcard layout") } } func TestActiveLayoutSelection(t *testing.T) { c := Default() c.Layouts = append(c.Layouts, Layout{Name: "wide", Monitor: "*", Zones: []Zone{{Name: "wide", Width: 100, Height: 100}}}) c.ActiveLayout = "wide" got, ok := c.LayoutFor(`\\.\DISPLAY1`) if !ok || got.Name != "wide" || len(got.Zones) != 1 { t.Fatalf("wrong active layout: %+v, %v", got, ok) } } func TestLegacyLayoutUpgrade(t *testing.T) { c := Default() c.ActiveLayout = "" for i := range c.Layouts { c.Layouts[i].Name = "" } c.upgradeLegacyLayouts() if c.ActiveLayout != "default" || c.Layouts[0].Name != "default" { t.Fatalf("legacy layout was not upgraded: %+v", c) } } func TestLoadLegacyUnnamedLayout(t *testing.T) { path := filepath.Join(t.TempDir(), "legacy.yaml") data := []byte("version: 1\ngap: 8\nshift_drag: true\nlayouts:\n - monitor: '*'\n zones:\n - {x: 0, y: 0, width: 100, height: 100}\n") if err := os.WriteFile(path, data, 0o600); err != nil { t.Fatal(err) } c, err := Load(path) if err != nil { t.Fatal(err) } if c.ActiveLayout != "default" || c.Layouts[0].Name != "default" { t.Fatalf("legacy file was not upgraded: %+v", c) } } func TestMissingActiveLayoutFails(t *testing.T) { c := Default() c.ActiveLayout = "missing" if err := c.Validate(); err == nil { t.Fatal("expected missing active layout to fail") } } func TestLayoutNamesAreUniqueAndOrdered(t *testing.T) { c := Default() c.Layouts = append(c.Layouts, Layout{Name: "Columns", Monitor: `\\.\DISPLAY2`}, Layout{Name: "Rows", Monitor: "*"}, ) got := c.LayoutNames() if len(got) != 2 || got[0] != "columns" || got[1] != "Rows" { t.Fatalf("unexpected names: %#v", got) } } func TestSetActiveLayoutPreservesConfiguration(t *testing.T) { path := filepath.Join(t.TempDir(), "fancywin.yaml") original := "# keep this comment\r\nversion: 1\r\nactive_layout: old # old value\r\nlayouts: []\r\n" if err := os.WriteFile(path, []byte(original), 0o640); err != nil { t.Fatal(err) } if err := SetActiveLayout(path, "new layout"); err != nil { t.Fatal(err) } data, err := os.ReadFile(path) if err != nil { t.Fatal(err) } text := string(data) if !strings.Contains(text, "# keep this comment\r\n") || !strings.Contains(text, "active_layout: new layout\r\n") || !strings.Contains(text, "layouts: []\r\n") { t.Fatalf("unexpected rewritten file: %q", text) } } func TestExcluded(t *testing.T) { c := Default() c.Excluded = []string{"notepad", "exact.exe"} if !c.IsExcluded(`C:\Windows\notepad.exe`) || !c.IsExcluded(`C:\x\exact.exe`) || c.IsExcluded(`C:\x\other.exe`) { t.Fatal("bad exclusion matching") } } func TestInvalidNumberedAction(t *testing.T) { c := Default() c.Hotkeys = []Hotkey{{Keys: "win+alt+1", Action: "zone_nope"}} if err := c.Validate(); err == nil { t.Fatal("expected invalid numbered action to fail") } } func TestOverlayValidation(t *testing.T) { c := Default() c.Overlay.Color = "blue" if err := c.Validate(); err == nil { t.Fatal("expected invalid overlay color to fail") } c = Default() c.Overlay.Opacity = 101 if err := c.Validate(); err == nil { t.Fatal("expected invalid overlay opacity to fail") } }