The session held a wallet of up to six accounts, and a request picked one by a header or an ?account= parameter. It now holds one: user_id and its epoch. A sign-in replaces whoever was signed in, sign-out and account deletion end the session, and an account refused mid-session (revoked, suspended, deactivated) clears it. /api/me/accounts and /api/me/switch are gone, and with them their refusal codes and the UI copy for them. A cookie the multi-account build wrote carries no single epoch and is refused: its holder signs in once more. A Google link finishing in a browser now signed in as someone else is refused, as before for an account outside the wallet. A test holds that no app code reads the wallet keys or the account header again.
78 lines
2.8 KiB
Python
78 lines
2.8 KiB
Python
"""A card asks the Plex image proxy for a small cut; a detail page keeps the full one.
|
||
|
||
Cards fetched the 400×600 poster for a ~144px picture and the 1280×720 backdrop for a ~212px shelf
|
||
picture. The `_sm` variants are cut by Plex at a card's size and cached apart from the full ones; an
|
||
unknown variant still gets the full poster. DB lane (the proxy opens its own short session).
|
||
"""
|
||
|
||
from fastapi.testclient import TestClient
|
||
|
||
import app.state as app_state
|
||
from app.main import app
|
||
from app.plex.models import PlexItem, PlexLibrary
|
||
from app.plex import imgcache
|
||
from app.routes.plex import playback
|
||
|
||
|
||
class _FakePlex:
|
||
calls: list[tuple[str, int | None, int | None]] = []
|
||
|
||
def __init__(self, db) -> None:
|
||
pass
|
||
|
||
def __enter__(self):
|
||
return self
|
||
|
||
def __exit__(self, *exc) -> None:
|
||
return None
|
||
|
||
def image_bytes(self, key, width=None, height=None):
|
||
_FakePlex.calls.append((key, width, height))
|
||
return b"\xff\xd8jpeg", "image/jpeg"
|
||
|
||
|
||
def _setup(db, make_user, monkeypatch, tmp_path) -> TestClient:
|
||
user = make_user()
|
||
lib = PlexLibrary(plex_key="90", title="Movies", kind="movie", enabled=True)
|
||
db.add(lib)
|
||
db.flush()
|
||
db.add(
|
||
PlexItem(
|
||
rating_key="pm1",
|
||
library_id=lib.id,
|
||
kind="movie",
|
||
title="A Movie",
|
||
thumb_key="/library/metadata/pm1/thumb/1",
|
||
art_key="/library/metadata/pm1/art/1",
|
||
)
|
||
)
|
||
db.commit()
|
||
monkeypatch.setattr(app_state, "_configured_cache", True)
|
||
monkeypatch.setattr(playback, "session_user_id", lambda request: user.id)
|
||
monkeypatch.setattr(playback, "PlexClient", _FakePlex)
|
||
monkeypatch.setattr(imgcache, "CACHE_DIR", tmp_path)
|
||
_FakePlex.calls = []
|
||
return TestClient(app)
|
||
|
||
|
||
def test_each_variant_is_cut_at_its_own_size(db, make_user, monkeypatch, tmp_path):
|
||
client = _setup(db, make_user, monkeypatch, tmp_path)
|
||
for variant in ("thumb", "thumb_sm", "art", "art_sm"):
|
||
assert client.get(f"/api/plex/image/pm1?variant={variant}").status_code == 200
|
||
assert _FakePlex.calls == [
|
||
("/library/metadata/pm1/thumb/1", 400, 600),
|
||
("/library/metadata/pm1/thumb/1", 240, 360),
|
||
("/library/metadata/pm1/art/1", 1280, 720),
|
||
("/library/metadata/pm1/art/1", 480, 270),
|
||
]
|
||
# Each cut is cached under its own name: asking again reaches Plex no more.
|
||
for variant in ("thumb", "thumb_sm", "art", "art_sm"):
|
||
assert client.get(f"/api/plex/image/pm1?variant={variant}").status_code == 200
|
||
assert len(_FakePlex.calls) == 4
|
||
|
||
|
||
def test_an_unknown_variant_gets_the_full_poster(db, make_user, monkeypatch, tmp_path):
|
||
client = _setup(db, make_user, monkeypatch, tmp_path)
|
||
assert client.get("/api/plex/image/pm1?variant=huge").status_code == 200
|
||
assert _FakePlex.calls == [("/library/metadata/pm1/thumb/1", 400, 600)]
|