mirror of https://github.com/Nezreka/SoulSync.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
2.7 KiB
73 lines
2.7 KiB
"""Pin the structural conformance of every media server client to
|
|
``MediaServerClient``. Mirrors the download plugin conformance test
|
|
shape — class-level checks (not instance-level) so importing the
|
|
test doesn't drag every server's heavy auth init into the test
|
|
collection phase.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from core.media_server.contract import REQUIRED_METHODS
|
|
|
|
|
|
def _import_server_classes():
|
|
"""Import every server client class lazily inside tests so
|
|
auth-init-heavy modules (Plex, Jellyfin) aren't imported at test
|
|
collection."""
|
|
from core.jellyfin_client import JellyfinClient
|
|
from core.navidrome_client import NavidromeClient
|
|
from core.plex_client import PlexClient
|
|
from core.soulsync_client import SoulSyncClient
|
|
|
|
return {
|
|
'plex': PlexClient,
|
|
'jellyfin': JellyfinClient,
|
|
'navidrome': NavidromeClient,
|
|
'soulsync': SoulSyncClient,
|
|
}
|
|
|
|
|
|
def test_default_registry_registers_all_four_servers():
|
|
"""Smoke check that the foundation registry knows about every
|
|
server SoulSync historically dispatched to."""
|
|
from core.media_server.registry import build_default_registry
|
|
|
|
registry = build_default_registry()
|
|
expected = {'plex', 'jellyfin', 'navidrome', 'soulsync'}
|
|
assert set(registry.names()) == expected
|
|
|
|
|
|
@pytest.mark.parametrize('server_name', ['plex', 'jellyfin', 'navidrome', 'soulsync'])
|
|
def test_server_class_has_all_required_methods(server_name):
|
|
"""Every registered server class exposes every required protocol
|
|
method by name. Diagnostic-friendly: tells you WHICH method is
|
|
missing when a new server is added without all the required
|
|
methods."""
|
|
classes = _import_server_classes()
|
|
cls = classes[server_name]
|
|
|
|
missing = [m for m in REQUIRED_METHODS if not hasattr(cls, m)]
|
|
assert not missing, (
|
|
f"{server_name} ({cls.__name__}) missing required methods: {missing}"
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize('server_name', ['plex', 'jellyfin', 'navidrome', 'soulsync'])
|
|
def test_server_class_explicitly_inherits_contract(server_name):
|
|
"""Per Cin's standard from the download refactor: clients must
|
|
explicitly inherit ``MediaServerClient`` so the contract conformance
|
|
is obvious from reading the class declaration. Structural
|
|
typing alone (which would still pass `hasattr` checks) leaves
|
|
the contract invisible to anyone reading the code — drift in a
|
|
future client class wouldn't fail at the contract boundary."""
|
|
from core.media_server.contract import MediaServerClient
|
|
|
|
classes = _import_server_classes()
|
|
cls = classes[server_name]
|
|
assert issubclass(cls, MediaServerClient), (
|
|
f"{cls.__name__} must explicitly inherit MediaServerClient — "
|
|
f"structural typing isn't enough"
|
|
)
|