Voice libary data presistence after codex

This commit is contained in:
Xin Wang
2026-02-08 22:39:55 +08:00
parent 8069a16227
commit 68f69f9b09
7 changed files with 663 additions and 55 deletions

View File

@@ -1,4 +1,5 @@
"""Tests for Voice API endpoints"""
import base64
import pytest
@@ -130,3 +131,110 @@ class TestVoiceAPI:
data = response.json()
for voice in data["list"]:
assert voice["gender"] == "Female"
def test_preview_voice_success(self, client, monkeypatch):
"""Test preview voice endpoint returns audio data URL"""
from app.routers import voices as voice_router
class DummyResponse:
status_code = 200
content = b"fake-mp3-bytes"
text = "ok"
def json(self):
return {}
class DummyClient:
def __init__(self, *args, **kwargs):
pass
def __enter__(self):
return self
def __exit__(self, exc_type, exc, tb):
return False
def post(self, *args, **kwargs):
return DummyResponse()
monkeypatch.setenv("SILICONFLOW_API_KEY", "test-key")
monkeypatch.setattr(voice_router.httpx, "Client", DummyClient)
create_resp = client.post("/api/voices", json={
"id": "anna",
"name": "Anna",
"vendor": "SiliconFlow",
"gender": "Female",
"language": "zh",
"description": "system voice",
"model": "FunAudioLLM/CosyVoice2-0.5B",
"voice_key": "FunAudioLLM/CosyVoice2-0.5B:anna"
})
assert create_resp.status_code == 200
preview_resp = client.post("/api/voices/anna/preview", json={"text": "你好"})
assert preview_resp.status_code == 200
payload = preview_resp.json()
assert payload["success"] is True
assert payload["audio_url"].startswith("data:audio/mpeg;base64,")
encoded = payload["audio_url"].split(",", 1)[1]
assert base64.b64decode(encoded) == b"fake-mp3-bytes"
def test_vendor_credential_persist_and_preview_use_db_key(self, client, monkeypatch):
"""Test vendor credential persisted in DB and used by preview endpoint"""
from app.routers import voices as voice_router
captured_auth = {"value": ""}
class DummyResponse:
status_code = 200
content = b"fake-mp3"
text = "ok"
def json(self):
return {}
class DummyClient:
def __init__(self, *args, **kwargs):
pass
def __enter__(self):
return self
def __exit__(self, exc_type, exc, tb):
return False
def post(self, *args, **kwargs):
headers = kwargs.get("headers", {})
captured_auth["value"] = headers.get("Authorization", "")
return DummyResponse()
monkeypatch.delenv("SILICONFLOW_API_KEY", raising=False)
monkeypatch.setattr(voice_router.httpx, "Client", DummyClient)
save_cred = client.put(
"/api/voices/vendors/credentials/siliconflow",
json={
"vendor_name": "SiliconFlow",
"api_key": "db-key-123",
"base_url": "https://api.siliconflow.cn/v1"
},
)
assert save_cred.status_code == 200
assert save_cred.json()["vendor_key"] == "siliconflow"
create_resp = client.post("/api/voices", json={
"id": "anna2",
"name": "Anna 2",
"vendor": "SiliconFlow",
"gender": "Female",
"language": "zh",
"description": "voice",
"model": "FunAudioLLM/CosyVoice2-0.5B",
"voice_key": "FunAudioLLM/CosyVoice2-0.5B:anna"
})
assert create_resp.status_code == 200
preview_resp = client.post("/api/voices/anna2/preview", json={"text": "hello"})
assert preview_resp.status_code == 200
assert captured_auth["value"] == "Bearer db-key-123"