mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-04 22:02:16 +02:00
test(podcasts): cover voice catalog
This commit is contained in:
parent
e926990d8e
commit
0c92ee963e
1 changed files with 103 additions and 0 deletions
103
surfsense_backend/tests/unit/podcasts/test_voice_catalog.py
Normal file
103
surfsense_backend/tests/unit/podcasts/test_voice_catalog.py
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
"""The voice catalog and provider identification.
|
||||||
|
|
||||||
|
The catalog is the single source of truth for which voices exist; resolution,
|
||||||
|
the API picker, and the renderer all depend on its lookups behaving correctly.
|
||||||
|
These tests build a small catalog of their own so they assert on the lookup
|
||||||
|
behavior, not on which specific voices ship.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from app.podcasts.voices import (
|
||||||
|
ANY_LANGUAGE,
|
||||||
|
CatalogVoice,
|
||||||
|
TtsProvider,
|
||||||
|
VoiceCatalog,
|
||||||
|
VoiceGender,
|
||||||
|
provider_from_service,
|
||||||
|
)
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.unit
|
||||||
|
|
||||||
|
|
||||||
|
def _voice(
|
||||||
|
voice_id: str,
|
||||||
|
*,
|
||||||
|
provider: TtsProvider = TtsProvider.KOKORO,
|
||||||
|
language: str = "en-US",
|
||||||
|
gender: VoiceGender = VoiceGender.MALE,
|
||||||
|
) -> CatalogVoice:
|
||||||
|
return CatalogVoice(
|
||||||
|
voice_id=voice_id,
|
||||||
|
provider=provider,
|
||||||
|
language=language,
|
||||||
|
display_name=voice_id,
|
||||||
|
gender=gender,
|
||||||
|
native_ref=voice_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_for_provider_returns_only_that_providers_voices():
|
||||||
|
catalog = VoiceCatalog(
|
||||||
|
[
|
||||||
|
_voice("k1", provider=TtsProvider.KOKORO),
|
||||||
|
_voice("o1", provider=TtsProvider.OPENAI),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
assert [v.voice_id for v in catalog.for_provider(TtsProvider.KOKORO)] == ["k1"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_for_language_matches_on_the_primary_subtag():
|
||||||
|
"""A request for 'en' should match an 'en-US' voice (region-insensitive)."""
|
||||||
|
catalog = VoiceCatalog([_voice("k1", language="en-US")])
|
||||||
|
assert [v.voice_id for v in catalog.for_language(TtsProvider.KOKORO, "en")] == ["k1"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_for_language_excludes_other_languages():
|
||||||
|
catalog = VoiceCatalog([_voice("k1", language="en-US")])
|
||||||
|
assert catalog.for_language(TtsProvider.KOKORO, "fr") == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_an_any_language_voice_speaks_every_language():
|
||||||
|
"""Provider-agnostic voices (e.g. OpenAI) match whatever the text is in."""
|
||||||
|
voice = _voice("o1", provider=TtsProvider.OPENAI, language=ANY_LANGUAGE)
|
||||||
|
assert voice.speaks("ja")
|
||||||
|
assert voice.speaks("pt-BR")
|
||||||
|
|
||||||
|
|
||||||
|
def test_supports_language_reports_availability():
|
||||||
|
catalog = VoiceCatalog([_voice("k1", language="en-US")])
|
||||||
|
assert catalog.supports_language(TtsProvider.KOKORO, "en")
|
||||||
|
assert not catalog.supports_language(TtsProvider.KOKORO, "de")
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_raises_for_an_unknown_voice():
|
||||||
|
catalog = VoiceCatalog([_voice("k1")])
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
catalog.get("nope")
|
||||||
|
|
||||||
|
|
||||||
|
def test_a_catalog_rejects_duplicate_voice_ids():
|
||||||
|
"""Stored ids must be unique so a brief's voice_id resolves unambiguously."""
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
VoiceCatalog([_voice("dup"), _voice("dup")])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("service", "expected"),
|
||||||
|
[
|
||||||
|
("openai/tts-1", TtsProvider.OPENAI),
|
||||||
|
("azure/neural", TtsProvider.AZURE),
|
||||||
|
("vertex_ai/some-model", TtsProvider.VERTEX_AI),
|
||||||
|
("local/kokoro", TtsProvider.KOKORO),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_provider_is_identified_from_the_config_string(service, expected):
|
||||||
|
assert provider_from_service(service) == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_unknown_provider_prefix_is_rejected():
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
provider_from_service("madeup/model")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue