feat: MbBrowser seam and FakeMbBrowser test double
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
|
from lyra_worker.browser import ArtistHit, ReleaseGroupInfo
|
||||||
from lyra_worker.types import Candidate, DownloadResult, MBTarget, Quality
|
from lyra_worker.types import Candidate, DownloadResult, MBTarget, Quality
|
||||||
|
|
||||||
_QUALITIES = {
|
_QUALITIES = {
|
||||||
@@ -66,3 +67,17 @@ class FailingAdapter(_BaseFake):
|
|||||||
self, candidate: Candidate, dest: str, on_progress: Callable[[float], None]
|
self, candidate: Candidate, dest: str, on_progress: Callable[[float], None]
|
||||||
) -> DownloadResult:
|
) -> DownloadResult:
|
||||||
return DownloadResult(ok=False, error="simulated download failure")
|
return DownloadResult(ok=False, error="simulated download failure")
|
||||||
|
|
||||||
|
|
||||||
|
class FakeMbBrowser:
|
||||||
|
"""In-memory MbBrowser for tests. `releases` maps artist mbid -> [ReleaseGroupInfo]."""
|
||||||
|
|
||||||
|
def __init__(self, artists=None, releases=None):
|
||||||
|
self._artists = list(artists or [])
|
||||||
|
self._releases = dict(releases or {})
|
||||||
|
|
||||||
|
def search_artist(self, name: str) -> list[ArtistHit]:
|
||||||
|
return list(self._artists)
|
||||||
|
|
||||||
|
def browse_release_groups(self, artist_mbid: str) -> list[ReleaseGroupInfo]:
|
||||||
|
return list(self._releases.get(artist_mbid, []))
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Protocol
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ArtistHit:
|
||||||
|
mbid: str
|
||||||
|
name: str
|
||||||
|
disambiguation: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ReleaseGroupInfo:
|
||||||
|
rg_mbid: str
|
||||||
|
title: str
|
||||||
|
primary_type: str = ""
|
||||||
|
secondary_types: tuple[str, ...] = ()
|
||||||
|
first_release_date: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class MbBrowser(Protocol):
|
||||||
|
def search_artist(self, name: str) -> list[ArtistHit]:
|
||||||
|
"""Artist name search → ranked hits (best first)."""
|
||||||
|
...
|
||||||
|
|
||||||
|
def browse_release_groups(self, artist_mbid: str) -> list[ReleaseGroupInfo]:
|
||||||
|
"""All official release-groups for an artist MBID."""
|
||||||
|
...
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
from lyra_worker.adapters.fakes import FakeMbBrowser
|
||||||
|
from lyra_worker.browser import ArtistHit, ReleaseGroupInfo
|
||||||
|
|
||||||
|
|
||||||
|
def test_fake_browser_returns_canned_artists_and_releases():
|
||||||
|
rg = ReleaseGroupInfo(rg_mbid="rg-1", title="Continuum", primary_type="Album",
|
||||||
|
secondary_types=(), first_release_date="2006-09-12")
|
||||||
|
browser = FakeMbBrowser(
|
||||||
|
artists=[ArtistHit(mbid="a1", name="John Mayer", disambiguation="")],
|
||||||
|
releases={"a1": [rg]},
|
||||||
|
)
|
||||||
|
assert browser.search_artist("john")[0].name == "John Mayer"
|
||||||
|
assert browser.browse_release_groups("a1") == [rg]
|
||||||
|
assert browser.browse_release_groups("unknown") == []
|
||||||
Reference in New Issue
Block a user