""" Bug found live, 2026-08-24: `_fetch_and_cache_poster` downloaded a TMDB poster/backdrop from `image.tmdb.org` on *every* `media_meta_req`, even for a file whose TMDB match was already cached — the content-addressed `thumb_hash` isn't known until the bytes are downloaded, so nothing had ever checked "have I already fetched this poster_path" first. On a group with a show split across release folders (§V6), one Videos-tab visit triggered four to six redundant image downloads; compounded with TMDB latency (or a stall), this is what an operator saw as posters that "never finish loading" on a second visit. Fixed by keying the `thumbs` cache by a synthetic `tmdb:{poster_path}` id *before* the network call, mirroring the `file_id` convention `_do_file_request` already uses to resolve a thumbnail by id. """ import pytest from meshbay_node.media_cache import MediaCache from meshbay_node.transport.webrtc_server import WebRTCPeerSession pytestmark = pytest.mark.asyncio @pytest.fixture async def media_cache(tmp_path): c = MediaCache(db_path=tmp_path / "media_cache.db") await c.open() yield c await c.close() class FakeTmdbClient: def __init__(self): self.fetch_calls = 0 @staticmethod def poster_url(path): return f"https://image.tmdb.org/t/p/w500{path}" async def fetch_image(self, url): self.fetch_calls += 1 return b"jpeg-bytes-for-" + url.encode() async def test_second_fetch_for_the_same_poster_path_skips_the_network(media_cache): client = FakeTmdbClient() first = await WebRTCPeerSession._fetch_and_cache_poster( media_cache, client, "/poster.jpg") second = await WebRTCPeerSession._fetch_and_cache_poster( media_cache, client, "/poster.jpg") assert first == second, "the same poster_path must yield the same thumb_hash" assert client.fetch_calls == 1, ( "a poster already cached must never be re-downloaded from TMDB") async def test_different_poster_paths_are_each_fetched_once(media_cache): client = FakeTmdbClient() poster_hash = await WebRTCPeerSession._fetch_and_cache_poster( media_cache, client, "/poster.jpg") backdrop_hash = await WebRTCPeerSession._fetch_and_cache_poster( media_cache, client, "/backdrop.jpg") poster_hash_again = await WebRTCPeerSession._fetch_and_cache_poster( media_cache, client, "/poster.jpg") assert poster_hash != backdrop_hash assert poster_hash == poster_hash_again assert client.fetch_calls == 2, "one network fetch per distinct poster_path" async def test_none_path_is_a_no_op(media_cache): client = FakeTmdbClient() result = await WebRTCPeerSession._fetch_and_cache_poster(media_cache, client, None) assert result is None assert client.fetch_calls == 0 async def test_cached_hash_actually_serves_the_downloaded_bytes(media_cache): client = FakeTmdbClient() thumb_hash = await WebRTCPeerSession._fetch_and_cache_poster( media_cache, client, "/poster.jpg") await WebRTCPeerSession._fetch_and_cache_poster(media_cache, client, "/poster.jpg") stored = await media_cache.get_thumb(thumb_hash) assert stored == b"jpeg-bytes-for-https://image.tmdb.org/t/p/w500/poster.jpg"