forked from viewit/KX-Bridge-Release
Issue #103: the printer has no MQTT-level command to power off or enter standby, so users on a separate-room setup have to physically walk over or use a smart plug (e.g. Tasmota) manually. Added per-printer power_on_url/power_off_url/power_status_url config (Settings > Power Switch) and a power button with a live on/off indicator on each printer's card in the Printers grid - plain HTTP GET calls, no Moonraker device_power dependency. Issue #104: the stable-release update check only ever requested the single newest Gitea release (limit=1) regardless of type. Since nightly/dev prereleases publish far more often than stable ones, that newest release is almost always a prerelease, so the "not a prerelease" filter found nothing and reported "no stable releases found" even though a newer stable release existed further back in the list. Fixed by requesting enough releases (limit=20) to look past a run of prereleases. Also fixes a related pre-existing bug surfaced while testing #103's config: configparser's default string interpolation rejected any config.ini value containing a literal '%' (ValueError: invalid interpolation syntax) - this broke saving Tasmota-style power URLs (cmnd=Power%20on) and would have broken any other value with a '%' character. Fixed globally with interpolation=None on every ConfigParser() instantiation in config_loader.py and kobrax_moonraker_bridge.py.
58 lines
2.1 KiB
Python
58 lines
2.1 KiB
Python
"""Update-check regression for Issue #104.
|
|
|
|
STABLE_RELEASE_API used limit=1, so it only ever saw the single newest
|
|
release on Gitea regardless of type. Since nightly/dev prereleases publish
|
|
far more often than stable releases, that newest release is almost always a
|
|
prerelease - the stable_releases filter (not prerelease) then found nothing
|
|
and /api/update/check returned "no stable releases found" even though older
|
|
stable releases exist.
|
|
"""
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
|
|
def _fake_releases_response(payload):
|
|
resp = MagicMock()
|
|
resp.status = 200
|
|
resp.json = AsyncMock(return_value=payload)
|
|
ctx = MagicMock()
|
|
ctx.__aenter__ = AsyncMock(return_value=resp)
|
|
ctx.__aexit__ = AsyncMock(return_value=False)
|
|
return ctx
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_stable_update_check_finds_release_behind_newer_prereleases(client):
|
|
c, bridge = client
|
|
bridge._read_version = lambda: "0.9.27"
|
|
|
|
releases = (
|
|
[{"tag_name": f"nightly-0.9.30-nightly{i}", "prerelease": True} for i in range(1, 7)]
|
|
+ [{"tag_name": "v0.9.29", "prerelease": False, "body": "changelog"}]
|
|
)
|
|
|
|
with patch("aiohttp.ClientSession.get", return_value=_fake_releases_response(releases)):
|
|
resp = await c.get("/api/update/check")
|
|
data = await resp.json()
|
|
|
|
assert resp.status == 200
|
|
assert data["latest"] == "0.9.29"
|
|
assert data["update_available"] is True
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_stable_update_check_requests_enough_releases_to_skip_prereleases(client):
|
|
"""The API URL itself must ask for more than the single newest release -
|
|
a limit=1 request can never find a stable release behind a run of
|
|
prereleases no matter how the response is parsed."""
|
|
c, bridge = client
|
|
bridge._read_version = lambda: "0.9.27"
|
|
|
|
import re
|
|
assert not re.search(r"limit=1(?!\d)", bridge.STABLE_RELEASE_API), (
|
|
"STABLE_RELEASE_API must request more than 1 release, otherwise a "
|
|
"recent nightly/dev prerelease being the newest release hides all "
|
|
"stable releases behind it (Issue #104)"
|
|
)
|