import json from pathlib import Path from voxip_kiosk import browser as b from voxip_kiosk.config import DEFAULTS XRANDR = """Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 7680 x 7680 HDMI-1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 531mm x 299mm 1920x1080 60.00*+ 50.00 59.94 1280x720 60.00 50.00 59.94 720x576 50.00 HDMI-2 disconnected (normal left inverted right x axis y axis) """ def test_build_args_never_weakens_tls_and_binds_devtools_locally(tmp_path): args = b.build_args("/usr/bin/chromium", dict(DEFAULTS), tmp_path / "p", tmp_path / "c", "file:///start.html", (1920, 1080)) joined = " ".join(args) for flag in b.FORBIDDEN_FLAGS: assert flag not in joined assert "--remote-debugging-address=127.0.0.1" in args assert "--kiosk" in args and "--noerrdialogs" in args and "--disable-session-crashed-bubble" in args assert "--window-size=1920,1080" in args assert args[-1] == "file:///start.html" assert not any(a.startswith("--force-device-scale-factor") for a in args) def test_build_args_zoom(tmp_path): args = b.build_args("/usr/bin/chromium", dict(DEFAULTS, zoom=1.5), tmp_path, tmp_path, "x") assert "--force-device-scale-factor=1.5" in args def test_parse_xrandr(): outputs = b.parse_xrandr(XRANDR) assert len(outputs) == 1 out = outputs[0] assert out["name"] == "HDMI-1" assert out["modes"] == ["1920x1080", "1280x720", "720x576"] assert out["current"] == "1920x1080@60.00" assert out["preferred"] == "1920x1080" assert out["size"] == (1920, 1080) def test_xrandr_args_rotation_and_resolution(): out = b.parse_xrandr(XRANDR)[0] assert b.xrandr_args(out, dict(DEFAULTS, rotation=90)) == ["xrandr", "--output", "HDMI-1", "--auto", "--rotate", "right"] assert b.xrandr_args(out, dict(DEFAULTS, rotation=270, resolution="1280x720@50")) == [ "xrandr", "--output", "HDMI-1", "--mode", "1280x720", "--rate", "50", "--rotate", "left"] # unsupported mode falls back to auto instead of failing assert "--auto" in b.xrandr_args(out, dict(DEFAULTS, resolution="3840x2160")) def test_xset_commands(): assert ["xset", "-dpms"] in b.xset_commands(dict(DEFAULTS)) cmds = b.xset_commands(dict(DEFAULTS, screen_always_on=False, screen_off_minutes=15)) assert ["xset", "+dpms"] in cmds and ["xset", "dpms", "0", "0", "900"] in cmds def test_clean_profile_removes_locks_and_crash_flag(tmp_path): profile = tmp_path / "profile" (profile / "Default").mkdir(parents=True) (profile / "SingletonLock").symlink_to("kiosk-1234") (profile / "Default" / "Preferences").write_text(json.dumps({"profile": {"exit_type": "Crashed", "exited_cleanly": False}, "x": 1})) b.clean_profile(profile) assert not (profile / "SingletonLock").is_symlink() prefs = json.loads((profile / "Default" / "Preferences").read_text()) assert prefs["profile"] == {"exit_type": "Normal", "exited_cleanly": True} assert prefs["x"] == 1 def test_start_page_url_contains_target(paths): url = b.start_page_url(paths, dict(DEFAULTS, url="https://e.org/x?token=abc", device_name="Hal 1")) assert url.startswith(f"file://{paths.www_dir}/start.html?") assert "next=https%3A%2F%2Fe.org%2Fx%3Ftoken%3Dabc" in url and "name=Hal+1" in url def test_local_pages_exist(): www = Path(__file__).resolve().parents[1] / "www" for page in ("start.html", "offline.html", "setup.html", "kiosk.css", "logo.svg"): assert (www / page).exists() def test_prepare_display_waits_for_a_screen_only_after_boot(paths, monkeypatch): calls = [] monkeypatch.setattr(b, "_run", lambda args: calls.append(args) or None) monkeypatch.setattr(b.time, "sleep", lambda s: None) monkeypatch.setattr(b.sysinfo, "uptime_seconds", lambda: 3600.0) assert b.prepare_display(paths, dict(DEFAULTS)) is None assert sum(c == ["xrandr", "--query"] for c in calls) == 1 calls.clear() monkeypatch.setattr(b.sysinfo, "uptime_seconds", lambda: 40.0) b.prepare_display(paths, dict(DEFAULTS)) assert sum(c == ["xrandr", "--query"] for c in calls) == 15