test: reorganize core suite into explicit domain files
This commit is contained in:
103
tests/library/test_library_client_progress_updates.py
Normal file
103
tests/library/test_library_client_progress_updates.py
Normal file
@@ -0,0 +1,103 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from auditui.library import LibraryClient
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class ProgressClient:
|
||||
"""Client double for position and finished-state API methods."""
|
||||
|
||||
get_responses: dict[str, dict] = field(default_factory=dict)
|
||||
put_calls: list[tuple[str, dict]] = field(default_factory=list)
|
||||
post_response: dict = field(default_factory=dict)
|
||||
fail_put: bool = False
|
||||
|
||||
def get(self, path: str, **kwargs: object) -> dict:
|
||||
"""Return preconfigured payloads by API path."""
|
||||
del kwargs
|
||||
return self.get_responses.get(path, {})
|
||||
|
||||
def put(self, path: str, body: dict) -> dict:
|
||||
"""Record payloads or raise to exercise error handling."""
|
||||
if self.fail_put:
|
||||
raise OSError("write failed")
|
||||
self.put_calls.append((path, body))
|
||||
return {}
|
||||
|
||||
def post(self, path: str, body: dict) -> dict:
|
||||
"""Return licenserequest response for ACR extraction."""
|
||||
del path, body
|
||||
return self.post_response
|
||||
|
||||
|
||||
def test_is_finished_true_from_percent_complete() -> None:
|
||||
"""Ensure 100 percent completion is treated as finished."""
|
||||
library = LibraryClient(ProgressClient()) # type: ignore[arg-type]
|
||||
assert library.is_finished({"percent_complete": 100}) is True
|
||||
|
||||
|
||||
def test_get_last_position_reads_matching_annotation() -> None:
|
||||
"""Ensure last position is read in seconds from matching annotation."""
|
||||
client = ProgressClient(
|
||||
get_responses={
|
||||
"1.0/annotations/lastpositions": {
|
||||
"asin_last_position_heard_annots": [
|
||||
{"asin": "X", "last_position_heard": {"position_ms": 9000}}
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
library = LibraryClient(client) # type: ignore[arg-type]
|
||||
assert library.get_last_position("X") == 9.0
|
||||
|
||||
|
||||
def test_get_last_position_returns_none_for_missing_state() -> None:
|
||||
"""Ensure DoesNotExist status is surfaced as no saved position."""
|
||||
client = ProgressClient(
|
||||
get_responses={
|
||||
"1.0/annotations/lastpositions": {
|
||||
"asin_last_position_heard_annots": [
|
||||
{"asin": "X", "last_position_heard": {"status": "DoesNotExist"}}
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
library = LibraryClient(client) # type: ignore[arg-type]
|
||||
assert library.get_last_position("X") is None
|
||||
|
||||
|
||||
def test_save_last_position_validates_non_positive_values() -> None:
|
||||
"""Ensure save_last_position short-circuits on non-positive input."""
|
||||
library = LibraryClient(ProgressClient()) # type: ignore[arg-type]
|
||||
assert library.save_last_position("A", 0) is False
|
||||
|
||||
|
||||
def test_update_position_writes_version_when_available() -> None:
|
||||
"""Ensure version is included in payload when metadata provides it."""
|
||||
client = ProgressClient(
|
||||
get_responses={
|
||||
"1.0/content/A/metadata": {
|
||||
"content_metadata": {
|
||||
"content_reference": {"acr": "token", "version": "2"}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
library = LibraryClient(client) # type: ignore[arg-type]
|
||||
assert library._update_position("A", 5.5) is True
|
||||
path, body = client.put_calls[0]
|
||||
assert path == "1.0/lastpositions/A"
|
||||
assert body["position_ms"] == 5500
|
||||
assert body["version"] == "2"
|
||||
|
||||
|
||||
def test_mark_as_finished_updates_item_in_place() -> None:
|
||||
"""Ensure successful finish update mutates local item flags."""
|
||||
client = ProgressClient(post_response={"content_license": {"acr": "token"}})
|
||||
library = LibraryClient(client) # type: ignore[arg-type]
|
||||
item = {"runtime_length_min": 1, "listening_status": {}}
|
||||
assert library.mark_as_finished("ASIN", item) is True
|
||||
assert item["is_finished"] is True
|
||||
assert item["listening_status"]["is_finished"] is True
|
||||
Reference in New Issue
Block a user