screen-locker/screen_locker/tests/test_adb_and_phone.py
Krzysztof kuhy Rudnicki bdc405c8c9 Split _shutdown, _phone_verification and _status_data
Six new modules, all composed or re-exported so no caller changes:

  _shutdown.py (384)          -> _shutdown_sick_state.py  SickDayStateMixin
                                 _wake_alarm.py           WakeAlarmMixin
  _phone_verification.py (380)-> _adb_transport.py        AdbTransportMixin
                                 _http_workout_fetch.py   HttpWorkoutFetchMixin
  _status_data.py (370)       -> _status_types.py         the 7 dataclasses
                                 _status_projection.py    shutdown projection
                                                          + format_summary_line

Moving a name means moving where it is *read*, so 30-odd mock patch targets
move with it. Most importantly conftest.py's autouse _block_real_network
fixture: ruff correctly dropped the now-unused `socket` import from
_phone_verification, which silently removed the guard's target and would have
let subnet probes reach the real network. It now blocks socket in both modules
that actually own the probes, and both targets are asserted to exist.

976 tests pass at 100% branch coverage; pylint 8.70 -> 8.71; `screen_lock
--status` renders the real week unchanged. File-length gate: 41 -> 35.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EveB813BQ8abAP68VSqZ5Y
2026-08-15 20:11:28 +02:00

154 lines
4.2 KiB
Python

"""Tests for ADB commands, phone connection, and database operations."""
# pylint: disable=protected-access,unused-argument
from __future__ import annotations
import subprocess
from typing import TYPE_CHECKING
from unittest.mock import MagicMock, patch
from screen_locker.tests.conftest import create_locker
if TYPE_CHECKING:
from pathlib import Path
class TestRunAdb:
"""Tests for _run_adb ADB command execution."""
def test_run_adb_success(
self,
mock_tk: MagicMock,
mock_sys_exit: MagicMock,
tmp_path: Path,
) -> None:
"""Test successful ADB command."""
locker = create_locker(mock_tk, tmp_path)
mock_result = MagicMock(returncode=0, stdout="ok\n")
with patch(
"screen_locker._adb_transport.subprocess.run",
return_value=mock_result,
) as mock_run:
success, output = locker._run_adb(["devices"])
assert success is True
assert output == "ok\n"
mock_run.assert_called_once()
def test_run_adb_failure(
self,
mock_tk: MagicMock,
mock_sys_exit: MagicMock,
tmp_path: Path,
) -> None:
"""Test failed ADB command."""
locker = create_locker(mock_tk, tmp_path)
mock_result = MagicMock(returncode=1, stdout="")
with patch(
"screen_locker._adb_transport.subprocess.run",
return_value=mock_result,
):
success, _output = locker._run_adb(["devices"])
assert success is False
def test_run_adb_not_found(
self,
mock_tk: MagicMock,
mock_sys_exit: MagicMock,
tmp_path: Path,
) -> None:
"""Test ADB binary not found."""
locker = create_locker(mock_tk, tmp_path)
with patch(
"screen_locker._adb_transport.subprocess.run",
side_effect=FileNotFoundError("adb not found"),
):
success, output = locker._run_adb(["devices"])
assert success is False
assert not output
def test_run_adb_oserror(
self,
mock_tk: MagicMock,
mock_sys_exit: MagicMock,
tmp_path: Path,
) -> None:
"""Test ADB OSError."""
locker = create_locker(mock_tk, tmp_path)
with patch(
"screen_locker._adb_transport.subprocess.run",
side_effect=OSError("permission denied"),
):
success, output = locker._run_adb(["devices"])
assert success is False
assert not output
def test_run_adb_timeout(
self,
mock_tk: MagicMock,
mock_sys_exit: MagicMock,
tmp_path: Path,
) -> None:
"""Test ADB command timeout."""
locker = create_locker(mock_tk, tmp_path)
with patch(
"screen_locker._adb_transport.subprocess.run",
side_effect=subprocess.TimeoutExpired("adb", 15),
):
success, output = locker._run_adb(["devices"])
assert success is False
assert not output
class TestAdbShell:
"""Tests for _adb_shell method."""
def test_adb_shell_no_root(
self,
mock_tk: MagicMock,
mock_sys_exit: MagicMock,
tmp_path: Path,
) -> None:
"""Test ADB shell without root."""
locker = create_locker(mock_tk, tmp_path)
object.__setattr__(
locker,
"_run_adb",
MagicMock(
return_value=(True, "output"),
),
)
success, output = locker._adb_shell("ls /sdcard")
locker._run_adb.assert_called_once_with(["shell", "ls /sdcard"])
assert success is True
assert output == "output"
def test_adb_shell_with_root(
self,
mock_tk: MagicMock,
mock_sys_exit: MagicMock,
tmp_path: Path,
) -> None:
"""Test ADB shell with root."""
locker = create_locker(mock_tk, tmp_path)
object.__setattr__(
locker,
"_run_adb",
MagicMock(
return_value=(True, "output"),
),
)
success, _output = locker._adb_shell("ls /data", root=True)
locker._run_adb.assert_called_once_with(
["shell", "su", "-c", "ls /data"],
)
assert success is True