steam-backlog-enforcer/steam_backlog_enforcer/tests/test_command_gate.py
Krzysztof kuhy Rudnicki a9ca4a4ee7
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (mypy, mypy, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (pylint, pylint, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (rest, , mypy,pylint) (push) Waiting to run
Tests / test (push) Waiting to run
Tests / web-coverage (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
serve runs unconfigured (fresh installs could not reach web Setup); web control UI finished
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 19:22:17 +02:00

68 lines
2.4 KiB
Python

"""Tests for _command_gate: the lock rules shared by the CLI and web jobs."""
from __future__ import annotations
from contextlib import contextmanager
from typing import TYPE_CHECKING
from unittest.mock import MagicMock, patch
import pytest
from steam_backlog_enforcer import _command_gate as _gate
from steam_backlog_enforcer.config import Config, State
from steam_backlog_enforcer.tests._main_helpers import locked_state
if TYPE_CHECKING:
from collections.abc import Iterator
_PKG = "steam_backlog_enforcer._command_gate"
_CONFIGURED = Config(steam_api_key="k", steam_id="i")
@contextmanager
def _block(*, active: bool, days: float = 3.5) -> Iterator[None]:
"""Patch the total-block status the gate reads."""
status = MagicMock(days_remaining=days)
with (
patch(f"{_PKG}.is_total_block_active", return_value=active),
patch(f"{_PKG}.get_total_block_status", return_value=status),
):
yield
class TestLockReason:
def test_unconfigured_is_refused(self) -> None:
assert _gate.lock_reason("status", Config(), State()) == (
_gate.NOT_CONFIGURED_MSG
)
@pytest.mark.parametrize("command", ["setup", "add-exception", "serve"])
def test_setup_commands_need_no_key(self, command: str) -> None:
with _block(active=False):
assert _gate.lock_reason(command, Config(), State()) is None
def test_total_block_names_days_and_allowed_commands(self) -> None:
with _block(active=True):
reason = _gate.lock_reason("scan", _CONFIGURED, State())
assert reason is not None
assert "Total gaming block active (3.5 day(s) left)" in reason
assert "Allowed:" in reason
def test_exempt_commands_pass_the_total_block(self) -> None:
with _block(active=True):
assert _gate.lock_reason("status", _CONFIGURED, State()) is None
def test_manual_pick_lock_names_the_picks(self) -> None:
with _block(active=False):
reason = _gate.lock_reason("scan", _CONFIGURED, locked_state())
assert reason is not None
assert "Manual pick lock active (TestGame)" in reason
def test_exempt_commands_pass_the_pick_lock(self) -> None:
with _block(active=False):
assert _gate.lock_reason("status", _CONFIGURED, locked_state()) is None
def test_no_state_skips_the_pick_check(self) -> None:
with _block(active=False):
assert _gate.lock_reason("scan", _CONFIGURED, None) is None