mirror of
https://github.com/spoopyghosty0/frameport.git
synced 2026-10-25 01:02:49 +02:00
- Check the Steam shortcut on every update, also when nothing else changed: a connection lost during "Add to Steam" or Steam putting its old shortcuts.vdf back left games without a library entry. The agent restarts Steam only when the entry really changes. - Artwork updates for installs without a recorded artwork manifest start from a clean folder again (an old portrait.jpg next to a new portrait.png was picked at random for the Steam grid). - OpenSSH uploads only rename .part files that are already complete (sftp's reput refuses them, which sent every resume to the Paramiko fallback). - frame.tbxr_vendor revision 2: GL4ES ports get "Update on Frame" for the #191 draw fix. - Configuration-only updates send the library's current Steam tags. - finalize drops fingerprints and the artwork record an older app didn't send. - set_settings: malformed numbers are refused before anything is written; int settings keep a fractional value. - Display diagnostics use Windows PowerShell 5.1 without pwsh's PSModulePath; window diagnostics and the instance owner file can't stop the GUI from starting.
90 lines
4.0 KiB
Python
90 lines
4.0 KiB
Python
"""Desktop diagnostics stay on demand, bounded and useful when Windows queries fail or return no events."""
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from frameport.diag import display
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def reset_window(monkeypatch):
|
|
monkeypatch.setattr(display, "_window", {})
|
|
|
|
|
|
def test_non_windows_does_not_start_display_queries(monkeypatch):
|
|
monkeypatch.setattr(display, "_is_windows", lambda: False)
|
|
|
|
def unexpected():
|
|
pytest.fail("Windows query ran on another platform")
|
|
|
|
monkeypatch.setattr(display, "_windows_displays", unexpected)
|
|
monkeypatch.setattr(display, "_recent_events", unexpected)
|
|
assert display.collect()["windows"] == {"status": "not_applicable"}
|
|
|
|
|
|
def test_window_events_are_cached_without_running_queries(monkeypatch, caplog):
|
|
monkeypatch.setattr(display, "_is_windows", lambda: True)
|
|
monkeypatch.setitem(sys.modules, "flet.version", SimpleNamespace(flet_version="1.0.2", flutter_version="3.44.8"))
|
|
window = SimpleNamespace(width=1280, height=720, left=3086, top=172,
|
|
minimized=False, maximized=False, full_screen=False)
|
|
with caplog.at_level("INFO", logger="frameport"):
|
|
display.record_window("minimize", window, theme="portal", reduce_motion=True)
|
|
assert "desktop window:" in caplog.text and '"event":"minimize"' in caplog.text
|
|
assert display._window["minimized"] is True and display._window["position"] == [3086, 172]
|
|
monkeypatch.setattr(display, "_windows_displays", lambda: {"status": "ok", "adapters": []})
|
|
monkeypatch.setattr(display, "_recent_events", lambda: {"status": "ok", "events": []})
|
|
result = display.collect()
|
|
assert result["runtime"]["flutter"] == "3.44.8"
|
|
assert result["window"]["event"] == "minimize"
|
|
display.record_window("focus", window, theme="portal", reduce_motion=True)
|
|
display.record_window("restore", window, theme="portal", reduce_motion=True)
|
|
assert display._window["focused"] is True and display._window["minimized"] is False
|
|
|
|
|
|
@pytest.mark.parametrize("response,status", [
|
|
('{"status":"ok","events":[]}', "ok"),
|
|
('{"status":"error","error":"AccessDenied","events":[]}', "error"),
|
|
('{"status":"ok","events":"invalid"}', "error"),
|
|
("not JSON", "error"),
|
|
])
|
|
def test_event_query_distinguishes_empty_results_from_failures(monkeypatch, response, status):
|
|
def run(args, **kwargs):
|
|
assert args[0].lower().endswith(("powershell.exe", "powershell"))
|
|
assert args[1:4] == ["-NoLogo", "-NoProfile", "-NonInteractive"]
|
|
assert not any(k.upper() == "PSMODULEPATH" for k in kwargs["env"]) # pwsh 7's modules break 5.1
|
|
assert kwargs["timeout"] == 5 and kwargs["creationflags"] == 0x08000000
|
|
assert "-FilterXPath" in args[-1] and "-MaxEvents 60" in args[-1]
|
|
assert ".Message" not in args[-1] # event metadata, not unrelated free text or device IDs
|
|
return subprocess.CompletedProcess(args, 0, response, "")
|
|
|
|
monkeypatch.setattr(display.subprocess, "run", run)
|
|
result = display._recent_events()
|
|
assert result["status"] == status
|
|
if status == "ok":
|
|
assert result["events"] == []
|
|
|
|
|
|
def test_event_query_timeout_does_not_look_like_no_events(monkeypatch):
|
|
def run(*args, **kwargs):
|
|
raise subprocess.TimeoutExpired(args[0], kwargs["timeout"])
|
|
|
|
monkeypatch.setattr(display.subprocess, "run", run)
|
|
assert display._recent_events() == {"status": "timeout", "timeout_seconds": 5}
|
|
|
|
|
|
def test_display_failure_does_not_discard_event_or_window_data(monkeypatch):
|
|
monkeypatch.setattr(display, "_is_windows", lambda: True)
|
|
|
|
def broken():
|
|
raise OSError("display API unavailable")
|
|
|
|
monkeypatch.setattr(display, "_windows_displays", broken)
|
|
monkeypatch.setattr(display, "_recent_events", lambda: {"status": "ok", "events": []})
|
|
result = display.collect()
|
|
assert result["windows"]["displays"]["status"] == "error"
|
|
assert result["windows"]["system_events"]["status"] == "ok"
|
|
json.dumps(result)
|