Kokoro-FastAPI/ui/depr_tests/test_api.py

168 lines
5.3 KiB
Python
Raw Normal View History

2025-04-04 16:50:46 -06:00
from unittest.mock import mock_open, patch
2025-01-01 21:50:41 -07:00
2025-01-01 21:50:00 -07:00
import pytest
import requests
2025-01-01 21:50:41 -07:00
2025-01-01 21:50:00 -07:00
from ui.lib import api
@pytest.fixture
def mock_response():
class MockResponse:
def __init__(self, json_data, status_code=200, content=b"audio data"):
self._json = json_data
self.status_code = status_code
self.content = content
def json(self):
return self._json
def raise_for_status(self):
if self.status_code != 200:
raise requests.exceptions.HTTPError(f"HTTP {self.status_code}")
return MockResponse
def test_check_api_status_success(mock_response):
"""Test successful API status check"""
mock_data = {"voices": ["voice1", "voice2"]}
with patch("requests.get", return_value=mock_response(mock_data)):
status, voices = api.check_api_status()
assert status is True
assert voices == ["voice1", "voice2"]
def test_check_api_status_no_voices(mock_response):
"""Test API response with no voices"""
with patch("requests.get", return_value=mock_response({"voices": []})):
status, voices = api.check_api_status()
assert status is False
assert voices == []
def test_check_api_status_timeout():
"""Test API timeout"""
with patch("requests.get", side_effect=requests.exceptions.Timeout):
status, voices = api.check_api_status()
assert status is False
assert voices == []
def test_check_api_status_connection_error():
"""Test API connection error"""
with patch("requests.get", side_effect=requests.exceptions.ConnectionError):
status, voices = api.check_api_status()
assert status is False
assert voices == []
def test_text_to_speech_success(mock_response, tmp_path):
"""Test successful speech generation"""
2025-04-04 16:58:07 -06:00
with (
patch("requests.post", return_value=mock_response({})),
patch("ui.lib.api.OUTPUTS_DIR", str(tmp_path)),
patch("builtins.open", mock_open()) as mock_file,
):
2025-01-01 21:50:00 -07:00
result = api.text_to_speech("test text", "voice1", "mp3", 1.0)
2025-01-01 21:50:41 -07:00
2025-01-01 21:50:00 -07:00
assert result is not None
assert "output_" in result
assert result.endswith(".mp3")
mock_file.assert_called_once()
def test_text_to_speech_empty_text():
"""Test speech generation with empty text"""
result = api.text_to_speech("", "voice1", "mp3", 1.0)
assert result is None
def test_text_to_speech_timeout():
"""Test speech generation timeout"""
with patch("requests.post", side_effect=requests.exceptions.Timeout):
result = api.text_to_speech("test", "voice1", "mp3", 1.0)
assert result is None
def test_text_to_speech_request_error():
"""Test speech generation request error"""
with patch("requests.post", side_effect=requests.exceptions.RequestException):
result = api.text_to_speech("test", "voice1", "mp3", 1.0)
assert result is None
def test_get_status_html_available():
"""Test status HTML generation for available service"""
html = api.get_status_html(True)
assert "green" in html
assert "Available" in html
def test_get_status_html_unavailable():
"""Test status HTML generation for unavailable service"""
html = api.get_status_html(False)
assert "red" in html
assert "Unavailable" in html
def test_text_to_speech_api_params(mock_response, tmp_path):
"""Test correct API parameters are sent"""
test_cases = [
# Single voice as string
("voice1", "voice1"),
# Multiple voices as list
(["voice1", "voice2"], "voice1+voice2"),
# Single voice as list
(["voice1"], "voice1"),
]
for input_voice, expected_voice in test_cases:
2025-04-04 16:58:07 -06:00
with (
patch("requests.post") as mock_post,
patch("ui.lib.api.OUTPUTS_DIR", str(tmp_path)),
patch("builtins.open", mock_open()),
):
mock_post.return_value = mock_response({})
api.text_to_speech("test text", input_voice, "mp3", 1.5)
mock_post.assert_called_once()
args, kwargs = mock_post.call_args
# Check request body
assert kwargs["json"] == {
"model": "kokoro",
"input": "test text",
"voice": expected_voice,
"response_format": "mp3",
"speed": 1.5,
}
# Check headers and timeout
assert kwargs["headers"] == {"Content-Type": "application/json"}
assert kwargs["timeout"] == 300
def test_text_to_speech_output_filename(mock_response, tmp_path):
"""Test output filename contains correct voice identifier"""
test_cases = [
# Single voice
("voice1", lambda f: "voice-voice1" in f),
# Multiple voices
(["voice1", "voice2"], lambda f: "voice-voice1+voice2" in f),
]
for input_voice, filename_check in test_cases:
2025-04-04 16:58:07 -06:00
with (
patch("requests.post", return_value=mock_response({})),
patch("ui.lib.api.OUTPUTS_DIR", str(tmp_path)),
patch("builtins.open", mock_open()) as mock_file,
):
result = api.text_to_speech("test text", input_voice, "mp3", 1.0)
assert result is not None
2025-04-04 16:58:07 -06:00
assert filename_check(result), (
f"Expected voice pattern not found in filename: {result}"
)
mock_file.assert_called_once()