mirror of
https://github.com/kuhyx/steam-backlog-enforcer.git
synced 2026-07-04 11:43:12 +02:00
Extracted from testsAndMisc monorepo. Changes: - Rewrote imports from python_pkg.steam_backlog_enforcer.* → steam_backlog_enforcer.* - Moved run.sh, install.sh, README.md, service file to repo root - Added standalone pyproject.toml, requirements.txt, .pre-commit-config.yaml, .gitignore - Added GitHub Actions CI workflows (tests + pre-commit) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
135 lines
4.3 KiB
Python
135 lines
4.3 KiB
Python
"""Tests for scanning module — part 2 (missing coverage)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from steam_backlog_enforcer.config import Config, State
|
|
from steam_backlog_enforcer.scanning import (
|
|
_check_game_tampering,
|
|
detect_tampering,
|
|
)
|
|
|
|
PKG = "steam_backlog_enforcer.scanning"
|
|
|
|
|
|
def _entry(
|
|
app_id: int = 1,
|
|
name: str = "G",
|
|
total: int = 10,
|
|
unlocked: int = 5,
|
|
playtime: int = 60,
|
|
) -> dict[str, Any]:
|
|
return {
|
|
"app_id": app_id,
|
|
"name": name,
|
|
"total_achievements": total,
|
|
"unlocked_achievements": unlocked,
|
|
"playtime_minutes": playtime,
|
|
}
|
|
|
|
|
|
class TestCheckGameTampering:
|
|
"""Tests for _check_game_tampering."""
|
|
|
|
def test_current_game_skipped(self) -> None:
|
|
state = State(current_app_id=1)
|
|
result = _check_game_tampering(MagicMock(), _entry(app_id=1), state)
|
|
assert result is None
|
|
|
|
def test_already_complete_skipped(self) -> None:
|
|
state = State()
|
|
result = _check_game_tampering(
|
|
MagicMock(),
|
|
_entry(unlocked=10, total=10),
|
|
state,
|
|
)
|
|
assert result is None
|
|
|
|
def test_zero_playtime_skipped(self) -> None:
|
|
state = State()
|
|
result = _check_game_tampering(
|
|
MagicMock(),
|
|
_entry(playtime=0),
|
|
state,
|
|
)
|
|
assert result is None
|
|
|
|
def test_no_new_achievements(self) -> None:
|
|
client = MagicMock()
|
|
game = MagicMock()
|
|
game.unlocked_achievements = 5
|
|
client.refresh_single_game.return_value = game
|
|
state = State()
|
|
result = _check_game_tampering(client, _entry(unlocked=5), state)
|
|
assert result is None
|
|
|
|
def test_tampering_detected(self) -> None:
|
|
client = MagicMock()
|
|
game = MagicMock()
|
|
game.unlocked_achievements = 8
|
|
client.refresh_single_game.return_value = game
|
|
state = State()
|
|
entry = _entry(app_id=99, name="Cheated", unlocked=5)
|
|
result = _check_game_tampering(client, entry, state)
|
|
assert result is not None
|
|
assert result == ("Cheated", 99, 3)
|
|
|
|
def test_refresh_returns_none(self) -> None:
|
|
client = MagicMock()
|
|
client.refresh_single_game.return_value = None
|
|
state = State()
|
|
result = _check_game_tampering(client, _entry(), state)
|
|
assert result is None
|
|
|
|
|
|
class TestDetectTampering:
|
|
"""Tests for detect_tampering."""
|
|
|
|
def test_no_snapshot(self) -> None:
|
|
with patch(f"{PKG}.load_snapshot", return_value=None):
|
|
detect_tampering(Config(steam_api_key="k", steam_id="i"), State())
|
|
|
|
def test_no_tampering(self) -> None:
|
|
entries = [_entry(app_id=1)]
|
|
with (
|
|
patch(f"{PKG}.load_snapshot", return_value=entries),
|
|
patch(f"{PKG}.SteamAPIClient"),
|
|
patch(f"{PKG}._check_game_tampering", return_value=None),
|
|
patch(f"{PKG}._echo"),
|
|
):
|
|
detect_tampering(Config(steam_api_key="k", steam_id="i"), State())
|
|
|
|
def test_tampering_found(self) -> None:
|
|
entries = [_entry(app_id=1, name="BadGame")]
|
|
with (
|
|
patch(f"{PKG}.load_snapshot", return_value=entries),
|
|
patch(f"{PKG}.SteamAPIClient"),
|
|
patch(
|
|
f"{PKG}._check_game_tampering",
|
|
return_value=("BadGame", 1, 3),
|
|
),
|
|
patch(f"{PKG}._echo") as mock_echo,
|
|
patch(f"{PKG}.send_notification"),
|
|
):
|
|
detect_tampering(Config(steam_api_key="k", steam_id="i"), State())
|
|
assert any("TAMPERING" in str(c) for c in mock_echo.call_args_list)
|
|
|
|
def test_stops_at_limit(self) -> None:
|
|
"""Stops after _TAMPER_CHECK_LIMIT suspicious games."""
|
|
entries = [_entry(app_id=i, name=f"G{i}") for i in range(10)]
|
|
with (
|
|
patch(f"{PKG}.load_snapshot", return_value=entries),
|
|
patch(f"{PKG}.SteamAPIClient"),
|
|
patch(
|
|
f"{PKG}._check_game_tampering",
|
|
return_value=("Game", 1, 1),
|
|
) as mock_check,
|
|
patch(f"{PKG}._echo"),
|
|
patch(f"{PKG}.send_notification"),
|
|
):
|
|
detect_tampering(Config(steam_api_key="k", steam_id="i"), State())
|
|
# Should stop after 3 (_TAMPER_CHECK_LIMIT)
|
|
assert mock_check.call_count == 3
|