"""Tests for conservative Spotify candidate matching.""" from app.domain.matching import judge_candidate_match, normalize_text, title_similarity from app.domain.models import Track, TrackCandidate def test_normalization_removes_case_punctuation_marks_and_suffixes() -> None: value = " H\u00e9llo, WORLD! (2011 Remaster) [Deluxe] " assert normalize_text(value) == "hello world" def test_title_similarity_uses_normalized_values() -> None: assert title_similarity("Signal Fire", "Signal Fire (Remastered)") == 1.0 def test_matching_accepts_a_similar_title_with_the_requested_artist() -> None: candidate = TrackCandidate(title="The Night Drive", artist="Example Artist") track = _track(title="The Night Drive (Radio Edit)", artist="Example Artist") verdict = judge_candidate_match(candidate, track, title_threshold=0.82) assert verdict.is_match assert verdict.is_artist_match def test_matching_drops_a_title_substitution_from_another_artist() -> None: candidate = TrackCandidate(title="The Night Drive", artist="Requested Artist") substitution = _track(title="The Night Drive", artist="Different Artist") verdict = judge_candidate_match(candidate, substitution, title_threshold=0.82) assert not verdict.is_match assert verdict.title_similarity == 1.0 assert not verdict.is_artist_match def test_matching_drops_a_weak_title_even_for_the_right_artist() -> None: candidate = TrackCandidate(title="The Night Drive", artist="Requested Artist") substitution = _track(title="Morning Train", artist="Requested Artist") assert not judge_candidate_match(candidate, substitution, title_threshold=0.82).is_match def _track(*, title: str, artist: str) -> Track: return Track( id="track-id", uri="spotify:track:track-id", title=title, artists=(artist,), album_name="Album", album_art_url=None, external_url=None, ) def test_title_similarity_tolerates_version_dash_suffix() -> None: assert title_similarity("Immunity", "Immunity - Remaster 2023") > 0.95 assert title_similarity("Nightcall", "Nightcall - Breakbot Remix") > 0.95 def test_title_similarity_prefers_the_unsuffixed_release() -> None: plain = title_similarity("Immunity", "Immunity") suffixed = title_similarity("Immunity", "Immunity - Remaster 2023") assert plain > suffixed