SurfSense/surfsense_backend/tests/unit/podcasts/test_resolution.py
DESKTOP-RTLN3BA\$punk 05190da0a9 chore: linting
2026-06-11 15:31:43 -07:00

98 lines
3 KiB
Python

"""Default language and voice selection for a fresh brief.
Resolution is what lets most briefs need no edits: it proposes a sensible
language and a distinct voice per speaker. These tests state the policy
("reuse what the user last chose, else English"; "two speakers should sound
like two people") through the public resolver functions and the real catalog.
We never guess the language from source content.
"""
from __future__ import annotations
import pytest
from app.podcasts.resolution import (
DEFAULT_LANGUAGE,
LanguageContext,
VoiceResolutionError,
resolve_language,
resolve_voices,
)
from app.podcasts.voices import TtsProvider, get_voice_catalog
pytestmark = pytest.mark.unit
def test_last_used_language_is_reused():
context = LanguageContext(last_used="fr")
assert resolve_language(context) == "fr"
def test_first_time_user_with_no_signal_gets_the_default():
assert resolve_language(LanguageContext()) == DEFAULT_LANGUAGE
def test_two_speakers_get_distinct_voices():
"""A two-speaker episode should not voice both with the same person."""
catalog = get_voice_catalog()
voices = resolve_voices(
catalog=catalog, provider=TtsProvider.KOKORO, language="en", speaker_count=2
)
assert len(voices) == 2
assert voices[0].voice_id != voices[1].voice_id
def test_a_users_preferred_voice_is_reused_when_still_valid():
catalog = get_voice_catalog()
voices = resolve_voices(
catalog=catalog,
provider=TtsProvider.KOKORO,
language="en",
speaker_count=2,
preferred=["kokoro:af_bella"],
)
assert voices[0].voice_id == "kokoro:af_bella"
def test_a_preferred_voice_invalid_for_the_language_is_replaced():
"""A stale preference (wrong provider/language) is silently dropped."""
catalog = get_voice_catalog()
voices = resolve_voices(
catalog=catalog,
provider=TtsProvider.KOKORO,
language="en",
speaker_count=1,
preferred=["kokoro:does-not-exist"],
)
assert voices[0].voice_id in {
v.voice_id for v in catalog.for_provider(TtsProvider.KOKORO)
}
def test_resolution_fails_when_no_voice_speaks_the_language():
"""If a provider can't speak the language at all, that is surfaced loudly."""
catalog = get_voice_catalog()
with pytest.raises(VoiceResolutionError):
resolve_voices(
catalog=catalog,
provider=TtsProvider.KOKORO,
language="xx",
speaker_count=1,
)
def test_every_speaker_is_assigned_even_when_voices_run_out():
"""With one available voice, both speakers still get one rather than failing."""
catalog = get_voice_catalog()
voices = resolve_voices(
catalog=catalog, provider=TtsProvider.KOKORO, language="fr", speaker_count=2
)
assert len(voices) == 2
def test_speaker_count_must_be_positive():
catalog = get_voice_catalog()
with pytest.raises(ValueError):
resolve_voices(
catalog=catalog, provider=TtsProvider.KOKORO, language="en", speaker_count=0
)