"""DB-backed regression (E5 S4): GET /api/plex/person/{name} returns a cast/crew member's filmography — movies + shows in the ENABLED libraries whose cast OR directors include the name, each carrying the caller's watch-state, plus the cached headshot. Also covers `content_libs` scoping (disabled libraries excluded) and the kind filter (episodes are not movies). Uses the DB lane (`db` fixture) — skipped when no Postgres is reachable. """ from fastapi.testclient import TestClient import app.state as state from app.auth import current_user from app.db import get_db from app.main import app from app.models import ( PlexItem, PlexLibrary, PlexPerson, PlexShow, PlexState, User, ) from app.plex.query import content_libs NAME = "Robert De Niro" def _get(db, user, monkeypatch, override_dep, path): monkeypatch.setattr(state, "_configured_cache", True) # pass the request gate override_dep(get_db, db.info["request"]) override_dep(current_user, lambda: user) return TestClient(app).get(path) # no lifespan (skip scheduler/HLS sweep) def test_person_detail_returns_cast_and_director_credits(db, monkeypatch, override_dep): movies_lib = PlexLibrary(plex_key="1", title="Movies", kind="movie", enabled=True) shows_lib = PlexLibrary(plex_key="2", title="Shows", kind="show", enabled=True) off_lib = PlexLibrary(plex_key="3", title="Off", kind="movie", enabled=False) db.add_all([movies_lib, shows_lib, off_lib]) db.flush() heat = PlexItem( rating_key="m1", library_id=movies_lib.id, kind="movie", title="Heat", year=1995, cast_names=[NAME, "Al Pacino"], ) # Director-only credit: the name is NOT in cast_names, only directors → the OR must still catch it. directed = PlexItem( rating_key="m2", library_id=movies_lib.id, kind="movie", title="A Bronx Tale", year=1993, cast_names=["Chazz Palminteri"], directors=[NAME], ) # Excluded: a movie in a DISABLED library. hidden = PlexItem( rating_key="m3", library_id=off_lib.id, kind="movie", title="Hidden", year=2000, cast_names=[NAME], ) # Excluded: an episode (kind != "movie") that happens to list the name. episode = PlexItem( rating_key="e1", library_id=movies_lib.id, kind="episode", title="An Episode", year=2001, cast_names=[NAME], ) show = PlexShow(rating_key="s1", library_id=shows_lib.id, title="A Show", cast_names=[NAME]) db.add_all([heat, directed, hidden, episode, show]) db.add(PlexPerson(name=NAME, photo_thumb="/img/deniro.jpg")) db.flush() user = User(email="person@example.com") db.add(user) db.flush() db.add(PlexState(user_id=user.id, item_id=heat.id, status="watched")) db.commit() resp = _get(db, user, monkeypatch, override_dep, f"/api/plex/person/{NAME.replace(' ', '%20')}") assert resp.status_code == 200, resp.text body = resp.json() assert body["name"] == NAME assert body["photo"] == "/img/deniro.jpg" # Both the cast credit (Heat) and the director-only credit (A Bronx Tale), year desc; NOT the # disabled-library movie and NOT the episode. assert [m["title"] for m in body["movies"]] == ["Heat", "A Bronx Tale"] assert body["movies"][0]["status"] == "watched" # from the caller's PlexState assert body["movies"][1]["status"] == "new" assert all(m["type"] == "movie" for m in body["movies"]) # The show credit. assert [s["title"] for s in body["shows"]] == ["A Show"] assert body["shows"][0]["type"] == "show" def test_person_detail_unknown_name_is_empty(db, monkeypatch, override_dep): lib = PlexLibrary(plex_key="1", title="Movies", kind="movie", enabled=True) db.add(lib) db.flush() db.add( PlexItem( rating_key="m1", library_id=lib.id, kind="movie", title="Solo", cast_names=["Nobody Else"], ) ) user = User(email="empty@example.com") db.add(user) db.commit() resp = _get(db, user, monkeypatch, override_dep, "/api/plex/person/Ghost%20Actor") assert resp.status_code == 200, resp.text body = resp.json() # An unknown name has no plex_people row → no bio, no titles (E5 S6 added the bio fields, all null). assert body == { "name": "Ghost Actor", "photo": None, "biography": None, "birthday": None, "deathday": None, "place_of_birth": None, "known_for_department": None, "also_known_as": [], "enriching": False, "known_for": [], "movies": [], "shows": [], } def test_content_libs_partitions_only_enabled(db): db.add_all( [ PlexLibrary(plex_key="1", title="Movies", kind="movie", enabled=True), PlexLibrary(plex_key="2", title="Shows", kind="show", enabled=True), PlexLibrary(plex_key="3", title="OffMovie", kind="movie", enabled=False), ] ) db.commit() movie_ids, show_ids = content_libs(db) assert len(movie_ids) == 1 and len(show_ids) == 1 # the disabled movie lib is excluded