A2: Pin JellyfinClient observable behavior

5 tests pin Jellyfin client surface. is_connected requires ALL
four of base_url + api_key + user_id + music_library_id (stricter
than Plex's is_connected). get_all_album_ids returns a set of
string GUID ids matching the cross-server uniform set semantics.
pull/497/head
Broque Thomas 3 weeks ago
parent c1da56b2c2
commit 5da2cfec46

@ -0,0 +1,104 @@
"""Phase A pinning tests for JellyfinClient.
Pin the OBSERVABLE BEHAVIOR the engine will dispatch through after
Phase B/C. Jellyfin's connection-readiness check is stricter than
Plex (requires base_url + api_key + user_id + music_library_id all
present), and get_all_artists has a side effect of pre-populating
caches.
"""
from __future__ import annotations
from unittest.mock import MagicMock, patch
import pytest
from core.jellyfin_client import JellyfinClient
@pytest.fixture
def jellyfin_client():
"""A bare JellyfinClient with no real connection."""
client = JellyfinClient.__new__(JellyfinClient)
client.base_url = None
client.api_key = None
client.user_id = None
client.music_library_id = None
client._connection_attempted = False
client._is_connecting = False
# Initialize the various caches the real __init__ sets up
client._album_cache = {}
client._track_cache = {}
client._artist_cache = {}
client._cache_populated = False
client._metadata_only_mode = False
return client
# ---------------------------------------------------------------------------
# is_connected
# ---------------------------------------------------------------------------
def test_is_connected_returns_false_when_no_credentials(jellyfin_client):
"""Pinning: any of base_url / api_key / user_id / music_library_id
being None False. All four must be set."""
with patch.object(jellyfin_client, 'ensure_connection', return_value=False):
assert jellyfin_client.is_connected() is False
def test_is_connected_returns_true_only_when_all_four_set(jellyfin_client):
"""Pinning: requires base_url AND api_key AND user_id AND
music_library_id. Setting only some still False."""
jellyfin_client._connection_attempted = True
# Only some — still False
jellyfin_client.base_url = 'http://j'
jellyfin_client.api_key = 'k'
jellyfin_client.user_id = 'u'
jellyfin_client.music_library_id = None
assert jellyfin_client.is_connected() is False
# All four — True
jellyfin_client.music_library_id = 'lib'
assert jellyfin_client.is_connected() is True
# ---------------------------------------------------------------------------
# get_all_artists / get_all_album_ids
# ---------------------------------------------------------------------------
def test_get_all_artists_returns_empty_when_not_connected(jellyfin_client):
with patch.object(jellyfin_client, 'ensure_connection', return_value=False):
assert jellyfin_client.get_all_artists() == []
def test_get_all_artists_returns_empty_when_no_music_library_id(jellyfin_client):
"""Pinning: even with ensure_connection True, no music_library_id
selected empty (don't crash)."""
jellyfin_client.music_library_id = None
with patch.object(jellyfin_client, 'ensure_connection', return_value=True):
assert jellyfin_client.get_all_artists() == []
def test_get_all_album_ids_returns_set(jellyfin_client):
"""Pinning: returns a set of string Jellyfin GUID ids. Same shape
semantic as Plex (set of strings) engine extraction depends on
uniform set type."""
jellyfin_client._connection_attempted = True
jellyfin_client.base_url = 'http://j'
jellyfin_client.api_key = 'k'
jellyfin_client.user_id = 'u'
jellyfin_client.music_library_id = 'lib'
fake_response_pages = [
{'Items': [{'Id': 'guid-1'}, {'Id': 'guid-2'}], 'TotalRecordCount': 2},
]
with patch.object(jellyfin_client, 'ensure_connection', return_value=True), \
patch.object(jellyfin_client, '_make_request', side_effect=fake_response_pages):
result = jellyfin_client.get_all_album_ids()
assert isinstance(result, set)
assert result == {'guid-1', 'guid-2'}
Loading…
Cancel
Save