aboutsummaryrefslogtreecommitdiff
path: root/scripts/testing/tests/test_desktop.py
blob: 6f79bfd07ed4be06f903c2a8354882954caad3b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# SPDX-License-Identifier: GPL-3.0-or-later
"""Post-install checks: window manager + desktop integration.

Parity port of validate_window_manager and its Hyprland/DWM branches, plus
validate_autologin_config. Hyprland and DWM checks are gated on which DE the
run installed; socket/portal-query checks are gated on a live compositor (the
headless test VM has none).

Note: validate_hyprland_tools historically checked `swww`, but archsetup now
installs `awww` (swww successor) and `pacman -Q swww` no longer matches — so
this checks awww. That divergence from the shell sweep is a correctness fix.
"""

import pytest


HYPRLAND_TOOLS = [
    "hyprland", "hypridle", "hyprlock", "waybar", "fuzzel",
    "awww", "grim", "slurp", "gammastep", "foot",
]

HYPRLAND_CONFIGS = [
    ".config/hypr/hyprland.conf",
    ".config/hypr/hypridle.conf",
    ".config/hypr/hyprlock.conf",
    ".config/waybar/config",
    ".config/fuzzel/fuzzel.ini",
    ".config/gammastep/config.ini",
]

SUCKLESS_TOOLS = ["dwm", "st", "dmenu", "slock"]

PORTALS_CONF = ".config/xdg-desktop-portal/portals.conf"


@pytest.mark.attribution("archsetup")
@pytest.mark.parametrize("pkg", HYPRLAND_TOOLS)
def test_hyprland_tool_installed(host, hyprland_installed, pkg):
    if not hyprland_installed:
        pytest.skip("Hyprland not installed (DESKTOP_ENV != hyprland)")
    assert host.package(pkg).is_installed, "%s missing" % pkg


@pytest.mark.attribution("archsetup")
@pytest.mark.parametrize("rel", HYPRLAND_CONFIGS)
def test_hyprland_config_present(host, hyprland_installed, home, rel):
    if not hyprland_installed:
        pytest.skip("Hyprland not installed (DESKTOP_ENV != hyprland)")
    assert host.file("%s/%s" % (home, rel)).exists, "%s missing" % rel


@pytest.mark.attribution("archsetup")
def test_live_update_guard_installed(host, hyprland_installed):
    if not hyprland_installed:
        pytest.skip("Hyprland not installed (DESKTOP_ENV != hyprland)")
    guard = host.file("/usr/local/bin/hypr-live-update-guard")
    assert guard.exists, "live-update guard script missing"
    assert guard.mode & 0o111, "live-update guard not executable"
    hook = host.file("/etc/pacman.d/hooks/hypr-live-update-guard.hook")
    assert hook.exists, "live-update guard pacman hook missing"
    assert "hypr-live-update-guard" in hook.content_string, \
        "hook does not invoke the guard script"


@pytest.mark.attribution("archsetup")
def test_portal_settings_backend_not_disabled(host, hyprland_installed, home):
    if not hyprland_installed:
        pytest.skip("Hyprland not installed")
    conf = host.file("%s/%s" % (home, PORTALS_CONF))
    assert conf.exists, "portals.conf missing"
    line = host.run(
        "grep org.freedesktop.impl.portal.Settings %s" % conf.path
    ).stdout
    assert "=none" not in line.replace(" ", ""), "Settings portal disabled (=none)"


def test_portal_returns_dark_mode(host, hyprland_installed, compositor_running, target_user):
    if not hyprland_installed:
        pytest.skip("Hyprland not installed")
    if not compositor_running:
        pytest.skip("no compositor running (headless) — portal query not applicable")
    cmd = (
        "sudo -u %s busctl --user call org.freedesktop.portal.Desktop "
        "/org/freedesktop/portal/desktop org.freedesktop.portal.Settings Read "
        "'ss' 'org.freedesktop.appearance' 'color-scheme'" % target_user
    )
    out = host.run(cmd).stdout
    assert "u 1" in out, "Settings portal should report color-scheme=1 (dark)"


def test_hyprland_socket(host, hyprland_installed, compositor_running):
    if not hyprland_installed:
        pytest.skip("Hyprland not installed")
    if not compositor_running:
        pytest.skip("Hyprland not running (headless) — socket check not applicable")
    assert host.run("test -S /tmp/hypr/*/.socket.sock").rc == 0


@pytest.mark.attribution("archsetup")
@pytest.mark.parametrize("tool", SUCKLESS_TOOLS)
def test_suckless_tool_installed(host, dwm_installed, tool):
    if not dwm_installed:
        pytest.skip("DWM not installed (DESKTOP_ENV != dwm)")
    assert host.file("/usr/local/bin/%s" % tool).exists, "%s missing" % tool


def test_autologin_configured(host):
    conf = host.file("/etc/systemd/system/getty@tty1.service.d/autologin.conf")
    if not conf.exists:
        pytest.skip("autologin not configured (AUTOLOGIN=no, may be intentional)")
    assert conf.exists


BT_PANEL_BINS = ["bt", "bt-panel", "bt-priv", "waybar-bt"]


@pytest.mark.attribution("archsetup")
@pytest.mark.parametrize("name", BT_PANEL_BINS)
def test_bt_panel_bin_stowed(host, hyprland_installed, home, name):
    # Executable via either stow shape (per-file symlink or folded dir).
    if not hyprland_installed:
        pytest.skip("Hyprland not installed (DESKTOP_ENV != hyprland)")
    path = "%s/.local/bin/%s" % (home, name)
    assert host.file(path).exists, "%s missing from ~/.local/bin" % name
    assert host.run("test -x %s" % path).rc == 0, "%s not executable" % name


@pytest.mark.attribution("archsetup")
def test_bt_panel_wired(host, hyprland_installed, home):
    # A fresh install lands the panel reachable: bar module, keybind, css.
    if not hyprland_installed:
        pytest.skip("Hyprland not installed (DESKTOP_ENV != hyprland)")
    waybar = host.file("%s/.config/waybar/config" % home)
    assert "custom/bluetooth" in waybar.content_string, \
        "waybar config lacks the custom/bluetooth module"
    hyprconf = host.file("%s/.config/hypr/hyprland.conf" % home)
    assert "bt-panel" in hyprconf.content_string, \
        "hyprland.conf lacks the bt-panel keybind"
    assert host.file("%s/.config/themes/dupre/panel.css" % home).exists, \
        "shared panel css missing from the stowed theme"