diora-web/tts/tests.py
marwin 05216a8613
All checks were successful
Build and push Docker image / build (push) Successful in 1m3s
Test / test (push) Successful in 1m32s
Vorlesen-Funktion im Reader: Piper/Thorsten-TTS (SW v42)
Serverseitige Sprachsynthese (deutsche Thorsten-Stimme, Piper) für den
EPUB-Reader: /tts/synthesize/ nimmt einen Satz (max. 500 Zeichen) entgegen,
synthetisiert und streamt WAV zurück, ohne zu persistieren, zu loggen oder zu
cachen — eine bewusste, eng begrenzte Ausnahme vom "Server sieht nie
Klartext"-Prinzip (siehe CLAUDE.md). Der neue ▶-Button im Reader-Header liest
ab der aktuellen Position satzweise vor, hebt den gerade gesprochenen Satz
hervor und scrollt mit; eine kleine Leiste bietet Pause/Stop.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xb6yX2S9aTGepYA9JFba9x
2026-08-31 22:29:13 +02:00

41 lines
1.7 KiB
Python

from unittest.mock import patch
from django.contrib.auth.models import User
from django.test import TestCase
from . import piper_engine
class TtsSynthesizeTests(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='alice', password='pw12345678')
def test_requires_auth(self):
resp = self.client.post('/tts/synthesize/', {'text': 'Hallo'}, content_type='application/json')
self.assertEqual(resp.status_code, 401)
def test_rejects_empty_text(self):
self.client.force_login(self.user)
resp = self.client.post('/tts/synthesize/', {'text': ' '}, content_type='application/json')
self.assertEqual(resp.status_code, 400)
def test_rejects_text_over_limit(self):
self.client.force_login(self.user)
resp = self.client.post(
'/tts/synthesize/', {'text': 'a' * 501}, content_type='application/json')
self.assertEqual(resp.status_code, 400)
def test_rejects_invalid_json(self):
self.client.force_login(self.user)
resp = self.client.post('/tts/synthesize/', 'not json', content_type='application/json')
self.assertEqual(resp.status_code, 400)
@patch.object(piper_engine, 'synthesize_wav', return_value=b'RIFF....WAVEfmt fake')
def test_synthesizes_audio(self, mock_synth):
self.client.force_login(self.user)
resp = self.client.post(
'/tts/synthesize/', {'text': 'Hallo Welt.'}, content_type='application/json')
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp['Content-Type'], 'audio/wav')
self.assertEqual(b''.join(resp.streaming_content), b'RIFF....WAVEfmt fake')
mock_synth.assert_called_once_with('Hallo Welt.')