Files
UmbraAudio/tests/test_voices/test_registry.py
B.D. Murphy c86e323d7a Initial commit: UmbraAudio audiobook generation program
Quality-first multi-pass audiobook generation from English manuscripts.

Includes:
- umbraaudio/ core package (pipeline, config, voices, web review UI)
- scripts/ CLI utilities + model download script
- tts_server/ remote TTS server
- specs/ design docs, tests/, pyproject.toml + uv.lock
- Qwen3-TTS git submodule (pinned 022e286) with local demo.py UI patch
  saved at scripts/qwen3_tts_demo_umbra_patch.patch
- .env with runtime config/secrets

Excluded (see .gitignore): models/ (downloaded via scripts/download_models.sh),
output/, logs/, .venv, .umbra runtime data, and book projects
(DealHunterShip_*), which are committed separately.
2026-08-30 07:58:24 -07:00

147 lines
5.0 KiB
Python

from __future__ import annotations
from pathlib import Path
import pytest
from umbraaudio.analysis import CharacterProfile
from umbraaudio.voices.registry import VoiceRegistry
@pytest.mark.asyncio
async def test_connect_creates_db(registry_db_path: Path):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
assert registry_db_path.exists()
await registry.close()
@pytest.mark.asyncio
async def test_find_or_create_new(registry_db_path: Path, character_profile: CharacterProfile):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
reg_id, created = await registry.find_or_create(character_profile, source_project="test")
assert created is True
assert reg_id > 0
await registry.close()
@pytest.mark.asyncio
async def test_find_or_create_duplicate(
registry_db_path: Path, character_profile: CharacterProfile
):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
reg_id1, created1 = await registry.find_or_create(character_profile, source_project="test")
reg_id2, created2 = await registry.find_or_create(character_profile, source_project="test2")
assert created1 is True
assert created2 is False
assert reg_id1 == reg_id2
await registry.close()
@pytest.mark.asyncio
async def test_find_by_name(registry_db_path: Path, character_profile: CharacterProfile):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
reg_id, _ = await registry.find_or_create(character_profile)
found = await registry.find_by_name("John Smith")
assert found is not None
assert found["id"] == reg_id
await registry.close()
@pytest.mark.asyncio
async def test_find_by_alias(registry_db_path: Path, character_profile: CharacterProfile):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
await registry.find_or_create(character_profile)
found = await registry.find_by_name("John")
assert found is not None
assert found["character_name"] == "John Smith"
await registry.close()
@pytest.mark.asyncio
async def test_find_by_unknown_name(registry_db_path: Path):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
found = await registry.find_by_name("Nobody")
assert found is None
await registry.close()
@pytest.mark.asyncio
async def test_update_voice_ref(registry_db_path: Path, character_profile: CharacterProfile):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
reg_id, _ = await registry.find_or_create(character_profile)
await registry.update_voice_ref(reg_id, "/path/to/ref.wav")
found = await registry.find_by_name("John Smith")
assert found is not None
assert found["voice_ref_path"] == "/path/to/ref.wav"
assert found["status"] == "voiced"
await registry.close()
@pytest.mark.asyncio
async def test_update_profile(registry_db_path: Path, character_profile: CharacterProfile):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
reg_id, _ = await registry.find_or_create(character_profile)
updated = CharacterProfile(
name="John Smith",
aliases=["John", "Johnny"],
gender="male",
age_range="adult",
energy="high",
timbre="bright",
)
await registry.update_profile(reg_id, updated)
found = await registry.find_by_name("John Smith")
assert found is not None
assert found["energy"] == "high"
assert found["timbre"] == "bright"
# new alias should be findable
found_by_new = await registry.find_by_name("Johnny")
assert found_by_new is not None
await registry.close()
@pytest.mark.asyncio
async def test_get_all_and_voiced(
registry_db_path: Path, character_profile: CharacterProfile, narrator_profile: CharacterProfile
):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
await registry.find_or_create(character_profile)
await registry.find_or_create(narrator_profile)
all_chars = await registry.get_all()
assert len(all_chars) >= 2
voiced = await registry.get_all_voiced()
assert len(voiced) == 0 # none voiced yet
await registry.close()
@pytest.mark.asyncio
async def test_search(registry_db_path: Path, character_profile: CharacterProfile):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
await registry.find_or_create(character_profile)
results = await registry.search("Smith")
assert len(results) >= 1
assert results[0]["character_name"] == "John Smith"
results_none = await registry.search("xyzzy")
assert len(results_none) == 0
await registry.close()
@pytest.mark.asyncio
async def test_link_to_project(registry_db_path: Path, character_profile: CharacterProfile):
registry = VoiceRegistry(registry_db_path)
await registry.connect()
reg_id, _ = await registry.find_or_create(character_profile)
await registry.link_to_project(reg_id, 1, role_in_book="Protagonist")
await registry.link_to_project(reg_id, 2)
await registry.close()