test: cover app and playback controller mixin behavior

This commit is contained in:
2026-02-18 03:17:48 +01:00
parent 4bc9b3fd3f
commit e88dcee155
8 changed files with 791 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
from __future__ import annotations
from pathlib import Path
from typing import Any, cast
from auditui.playback import controller_state as state_mod
from auditui.playback.controller import PlaybackController
class Proc:
"""Simple process shim exposing poll and pid for state tests."""
def __init__(self, poll_value=None) -> None:
"""Store poll return value and fake pid."""
self._poll_value = poll_value
self.pid = 123
def poll(self):
"""Return configured process status code or None."""
return self._poll_value
def _controller() -> tuple[PlaybackController, list[str]]:
"""Build playback controller and collected notifications list."""
messages: list[str] = []
return PlaybackController(messages.append, None), messages
def test_get_current_elapsed_rolls_pause_into_duration(monkeypatch) -> None:
"""Ensure elapsed helper absorbs stale pause_start_time when resumed."""
controller, _ = _controller()
controller.pause_start_time = 100.0
controller.is_paused = False
monkeypatch.setattr(state_mod.time, "time", lambda: 120.0)
monkeypatch.setattr(state_mod.elapsed_mod, "get_elapsed", lambda *args: 50.0)
assert controller._get_current_elapsed() == 50.0
assert controller.paused_duration == 20.0
assert controller.pause_start_time is None
def test_validate_playback_state_stops_when_process_ended() -> None:
"""Ensure state validation stops and reports when process is gone."""
controller, messages = _controller()
controller.playback_process = cast(Any, Proc(poll_value=1))
controller.is_playing = True
controller.current_file_path = Path("book.aax")
ok = controller._validate_playback_state(require_paused=False)
assert ok is False
assert messages[-1] == "Playback process has ended"
def test_send_signal_sets_paused_state_and_notifies(monkeypatch) -> None:
"""Ensure SIGSTOP updates paused state and includes filename in status."""
controller, messages = _controller()
controller.playback_process = cast(Any, Proc())
controller.current_file_path = Path("book.aax")
monkeypatch.setattr(state_mod.process_mod, "send_signal", lambda proc, sig: None)
controller._send_signal(state_mod.signal.SIGSTOP, "Paused", "pause")
assert controller.is_paused is True
assert messages[-1] == "Paused: book.aax"
def test_send_signal_handles_process_lookup(monkeypatch) -> None:
"""Ensure missing process lookup errors are handled with user-facing message."""
controller, messages = _controller()
controller.playback_process = cast(Any, Proc())
def raise_lookup(proc, sig):
"""Raise process lookup error to exercise exception path."""
del proc, sig
raise ProcessLookupError("gone")
monkeypatch.setattr(state_mod.process_mod, "send_signal", raise_lookup)
monkeypatch.setattr(state_mod.process_mod, "terminate_process", lambda proc: None)
controller._send_signal(state_mod.signal.SIGCONT, "Playing", "resume")
assert messages[-1] == "Process no longer exists"