diff options
Diffstat (limited to 'internal/notify/icons_test.go')
| -rw-r--r-- | internal/notify/icons_test.go | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/internal/notify/icons_test.go b/internal/notify/icons_test.go index 527b330..9a6824a 100644 --- a/internal/notify/icons_test.go +++ b/internal/notify/icons_test.go @@ -68,3 +68,91 @@ func TestResolveIconThemeName(t *testing.T) { t.Fatalf("missing name must be empty, got %q", got) } } + +// iconEnv builds a throwaway XDG tree, points qt6ct at theme, and returns the +// root. HOME, XDG_DATA_HOME and XDG_DATA_DIRS are restored after the test. +func iconEnv(t *testing.T, theme string) string { + t.Helper() + root := t.TempDir() + home := filepath.Join(root, "home") + if err := os.MkdirAll(filepath.Join(home, ".config", "qt6ct"), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(home, ".config", "qt6ct", "qt6ct.conf"), []byte("icon_theme="+theme+"\n"), 0o644); err != nil { + t.Fatal(err) + } + t.Setenv("XDG_DATA_HOME", root) + t.Setenv("XDG_DATA_DIRS", "") + t.Setenv("HOME", home) + return root +} + +// putIcon creates a placeholder icon file, and its parents. +func putIcon(t *testing.T, path string) { + t.Helper() + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(path, []byte("<svg/>"), 0o644); err != nil { + t.Fatal(err) + } +} + +// writeIndex writes a theme's index.theme with a single Inherits value. +func writeIndex(t *testing.T, dir, inherits string) { + t.Helper() + if err := os.MkdirAll(dir, 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(dir, "index.theme"), []byte("[Icon Theme]\nInherits="+inherits+"\n"), 0o644); err != nil { + t.Fatal(err) + } +} + +func TestResolveIconFreedesktopLayout(t *testing.T) { + root := iconEnv(t, "Flat") + putIcon(t, filepath.Join(root, "icons", "Flat", "scalable", "apps", "firefox.svg")) + putIcon(t, filepath.Join(root, "icons", "Flat", "48x48", "apps", "firefox.png")) + want := filepath.Join(root, "icons", "Flat", "scalable", "apps", "firefox.svg") + if got := ResolveIcon("firefox"); got != want { + t.Fatalf("freedesktop scalable: got %q want %q", got, want) + } + + root = iconEnv(t, "Grid") + putIcon(t, filepath.Join(root, "icons", "Grid", "48x48", "apps", "gimp.png")) + want = filepath.Join(root, "icons", "Grid", "48x48", "apps", "gimp.png") + if got := ResolveIcon("gimp"); got != want { + t.Fatalf("freedesktop raster: got %q want %q", got, want) + } +} + +func TestResolveIconSizePreference(t *testing.T) { + root := iconEnv(t, "Sized") + base := filepath.Join(root, "icons", "Sized") + putIcon(t, filepath.Join(base, "apps", "48", "app.png")) + putIcon(t, filepath.Join(base, "apps", "32@2x", "app.png")) + want := filepath.Join(base, "apps", "32@2x", "app.png") + if got := ResolveIcon("app"); got != want { + t.Fatalf("@2x beats plain 48 (64px vs 48px): got %q want %q", got, want) + } + + root = iconEnv(t, "Tied") + base = filepath.Join(root, "icons", "Tied") + putIcon(t, filepath.Join(base, "32x32@2x", "apps", "app.png")) + putIcon(t, filepath.Join(base, "64x64", "apps", "app.png")) + want = filepath.Join(base, "32x32@2x", "apps", "app.png") + if got := ResolveIcon("app"); got != want { + t.Fatalf("equal 64px must break ties deterministically: got %q want %q", got, want) + } +} + +func TestResolveIconInheritsCycle(t *testing.T) { + root := iconEnv(t, "LoopA") + writeIndex(t, filepath.Join(root, "icons", "LoopA"), "LoopB") + writeIndex(t, filepath.Join(root, "icons", "LoopB"), "LoopA") + putIcon(t, filepath.Join(root, "icons", "hicolor", "48x48", "apps", "app.png")) + want := filepath.Join(root, "icons", "hicolor", "48x48", "apps", "app.png") + if got := ResolveIcon("app"); got != want { + t.Fatalf("cycle must terminate and fall through to hicolor: got %q want %q", got, want) + } +} |
