Add wallpaper and default avatar support

Wallpaper with fallback hierarchy: config path > Moonarch system
default (/usr/share/moonarch/wallpaper.jpg) > package fallback.
Applied to both primary and secondary monitors.

Default avatar from Moongreet ecosystem with theme-colored SVG
rendering via PixbufLoader and proper clipping frame (Gtk.Box
with overflow hidden), matching the Moongreet avatar pattern.
This commit is contained in:
2026-03-26 13:01:25 +01:00
parent d0d390d0cb
commit dd9937b020
7 changed files with 167 additions and 17 deletions
+15 -1
View File
@@ -5,7 +5,7 @@ import os
from pathlib import Path
from unittest.mock import patch
from moonlock.users import get_current_user, get_avatar_path, User
from moonlock.users import get_current_user, get_avatar_path, get_default_avatar_path, User
class TestGetCurrentUser:
@@ -79,3 +79,17 @@ class TestGetAvatarPath:
def test_returns_none_when_no_avatar(self, tmp_path: Path):
path = get_avatar_path(tmp_path)
assert path is None
class TestGetDefaultAvatarPath:
"""Tests for default avatar fallback."""
def test_default_avatar_exists(self):
"""The package default avatar must always be present."""
path = get_default_avatar_path()
assert path.is_file()
def test_default_avatar_is_svg(self):
"""The default avatar should be an SVG file."""
path = get_default_avatar_path()
assert path.suffix == ".svg"
+53
View File
@@ -0,0 +1,53 @@
# ABOUTME: Tests for wallpaper path resolution.
# ABOUTME: Verifies fallback hierarchy: config > Moonarch system default > package fallback.
from pathlib import Path
from unittest.mock import patch
from moonlock.config import Config, resolve_background_path, MOONARCH_WALLPAPER, PACKAGE_WALLPAPER
class TestResolveBackgroundPath:
"""Tests for the wallpaper fallback hierarchy."""
def test_config_path_used_when_file_exists(self, tmp_path: Path):
"""Config background_path takes priority if the file exists."""
wallpaper = tmp_path / "custom.jpg"
wallpaper.write_bytes(b"\xff\xd8")
config = Config(background_path=str(wallpaper))
result = resolve_background_path(config)
assert result == wallpaper
def test_config_path_skipped_when_file_missing(self, tmp_path: Path):
"""Config path should be skipped if the file does not exist."""
config = Config(background_path="/nonexistent/wallpaper.jpg")
with patch("moonlock.config.MOONARCH_WALLPAPER", tmp_path / "nope.jpg"):
result = resolve_background_path(config)
assert result == PACKAGE_WALLPAPER
def test_moonarch_default_used_when_no_config(self, tmp_path: Path):
"""Moonarch system wallpaper is used when config has no background_path."""
moonarch_wp = tmp_path / "wallpaper.jpg"
moonarch_wp.write_bytes(b"\xff\xd8")
config = Config(background_path=None)
with patch("moonlock.config.MOONARCH_WALLPAPER", moonarch_wp):
result = resolve_background_path(config)
assert result == moonarch_wp
def test_moonarch_default_skipped_when_missing(self, tmp_path: Path):
"""Falls back to package wallpaper when Moonarch default is missing."""
config = Config(background_path=None)
with patch("moonlock.config.MOONARCH_WALLPAPER", tmp_path / "nope.jpg"):
result = resolve_background_path(config)
assert result == PACKAGE_WALLPAPER
def test_package_fallback_always_exists(self):
"""The package fallback wallpaper must always be present."""
assert PACKAGE_WALLPAPER.is_file()
def test_full_fallback_chain(self, tmp_path: Path):
"""With no config and no Moonarch default, package fallback is returned."""
config = Config()
with patch("moonlock.config.MOONARCH_WALLPAPER", tmp_path / "nope.jpg"):
result = resolve_background_path(config)
assert result == PACKAGE_WALLPAPER