Files
CloakBrowser/tests/test_update.py
T
CloakHQ 8cecebf118 feat: move binary releases to wrapper repo, add auto-update check
- Binary downloads now served from CloakHQ/cloakbrowser releases (chromium-v* tags)
- Auto-update: background version check on launch, downloads newer binary for next use
- Graceful error on macOS/Windows (Linux-only binaries for now)
- Rate-limited (1hr), opt-out via CLOAKBROWSER_AUTO_UPDATE=false
- Add release-binary.yml workflow for anonymous binary releases
2026-02-25 19:38:32 +01:00

173 lines
6.0 KiB
Python

"""Tests for auto-update and version management."""
from __future__ import annotations
import os
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
from cloakbrowser.config import (
CHROMIUM_VERSION,
_version_newer,
_version_tuple,
get_download_url,
get_effective_version,
)
from cloakbrowser.download import (
_get_latest_chromium_version,
_should_check_for_update,
)
class TestVersionComparison:
def test_version_tuple_parsing(self):
assert _version_tuple("145.0.7718.0") == (145, 0, 7718, 0)
assert _version_tuple("142.0.7444.175") == (142, 0, 7444, 175)
def test_newer_version(self):
assert _version_newer("145.0.7718.0", "142.0.7444.175") is True
def test_older_version(self):
assert _version_newer("142.0.7444.175", "145.0.7718.0") is False
def test_same_version(self):
assert _version_newer("142.0.7444.175", "142.0.7444.175") is False
def test_patch_bump(self):
assert _version_newer("142.0.7444.176", "142.0.7444.175") is True
def test_major_bump(self):
assert _version_newer("143.0.0.0", "142.9.9999.999") is True
class TestDownloadUrl:
def test_default_url_format(self):
url = get_download_url()
assert "github.com/CloakHQ/cloakbrowser/releases/download" in url
assert f"chromium-v{CHROMIUM_VERSION}" in url
assert url.endswith(".tar.gz")
def test_custom_version_url(self):
url = get_download_url("145.0.7718.0")
assert "chromium-v145.0.7718.0" in url
def test_no_old_repo_reference(self):
url = get_download_url()
assert "chromium-stealth-builds" not in url
class TestShouldCheckForUpdate:
def test_disabled_by_env(self):
with patch.dict(os.environ, {"CLOAKBROWSER_AUTO_UPDATE": "false"}):
assert _should_check_for_update() is False
def test_disabled_by_env_case_insensitive(self):
with patch.dict(os.environ, {"CLOAKBROWSER_AUTO_UPDATE": "False"}):
assert _should_check_for_update() is False
def test_disabled_by_binary_override(self):
with patch.dict(os.environ, {"CLOAKBROWSER_BINARY_PATH": "/some/path"}):
assert _should_check_for_update() is False
def test_disabled_by_custom_download_url(self):
with patch.dict(
os.environ, {"CLOAKBROWSER_DOWNLOAD_URL": "https://my-mirror.com"}
):
assert _should_check_for_update() is False
def test_rate_limited(self, tmp_path):
import time
with patch.dict(
os.environ,
{
"CLOAKBROWSER_CACHE_DIR": str(tmp_path),
"CLOAKBROWSER_BINARY_PATH": "",
"CLOAKBROWSER_AUTO_UPDATE": "",
"CLOAKBROWSER_DOWNLOAD_URL": "",
},
):
check_file = tmp_path / ".last_update_check"
check_file.write_text(str(time.time()))
assert _should_check_for_update() is False
def test_stale_rate_limit_allows_check(self, tmp_path):
import time
with patch.dict(
os.environ,
{
"CLOAKBROWSER_CACHE_DIR": str(tmp_path),
"CLOAKBROWSER_BINARY_PATH": "",
"CLOAKBROWSER_AUTO_UPDATE": "",
"CLOAKBROWSER_DOWNLOAD_URL": "",
},
):
check_file = tmp_path / ".last_update_check"
check_file.write_text(str(time.time() - 7200)) # 2 hours ago
assert _should_check_for_update() is True
class TestEffectiveVersion:
def test_no_marker_returns_hardcoded(self, tmp_path):
with patch.dict(os.environ, {"CLOAKBROWSER_CACHE_DIR": str(tmp_path)}):
assert get_effective_version() == CHROMIUM_VERSION
def test_marker_with_newer_version(self, tmp_path):
with patch.dict(os.environ, {"CLOAKBROWSER_CACHE_DIR": str(tmp_path)}):
marker = tmp_path / "latest_version"
marker.write_text("999.0.0.0")
# Binary doesn't exist, so should fall back
assert get_effective_version() == CHROMIUM_VERSION
def test_marker_with_older_version_ignored(self, tmp_path):
with patch.dict(os.environ, {"CLOAKBROWSER_CACHE_DIR": str(tmp_path)}):
marker = tmp_path / "latest_version"
marker.write_text("100.0.0.0")
assert get_effective_version() == CHROMIUM_VERSION
class TestGetLatestVersion:
def test_parses_chromium_tag(self):
mock_response = MagicMock()
mock_response.json.return_value = [
{"tag_name": "chromium-v145.0.7718.0", "draft": False},
{"tag_name": "chromium-v142.0.7444.175", "draft": False},
]
mock_response.raise_for_status = MagicMock()
with patch("cloakbrowser.download.httpx.get", return_value=mock_response):
result = _get_latest_chromium_version()
assert result == "145.0.7718.0"
def test_skips_draft_releases(self):
mock_response = MagicMock()
mock_response.json.return_value = [
{"tag_name": "chromium-v999.0.0.0", "draft": True},
{"tag_name": "chromium-v145.0.7718.0", "draft": False},
]
mock_response.raise_for_status = MagicMock()
with patch("cloakbrowser.download.httpx.get", return_value=mock_response):
result = _get_latest_chromium_version()
assert result == "145.0.7718.0"
def test_skips_non_chromium_tags(self):
mock_response = MagicMock()
mock_response.json.return_value = [
{"tag_name": "v0.2.0", "draft": False},
{"tag_name": "chromium-v145.0.7718.0", "draft": False},
]
mock_response.raise_for_status = MagicMock()
with patch("cloakbrowser.download.httpx.get", return_value=mock_response):
result = _get_latest_chromium_version()
assert result == "145.0.7718.0"
def test_network_error_returns_none(self):
with patch("cloakbrowser.download.httpx.get", side_effect=Exception("timeout")):
result = _get_latest_chromium_version()
assert result is None