"""Fallback Supertonic pentru voice mode când modelul răspunde în română pe o voce pocket-tts (English-only). Fără fallback, fiecare clauză ar fi respinsă de pocket-tts (diacritice RO) și turnul ar fi tăcere totală — bug observat 2026-07-11 („cât este ora" → răspuns RO scris, zero audio). """ import queue from unittest.mock import patch from src.voice.tts_stream import TTSQueue from tools.tts import DEFAULT_VOICE def _drain_items(q: queue.Queue) -> list: items = [] while True: try: items.append(q.get_nowait()) except queue.Empty: return items class TestPushTextLangRouting: @patch("src.voice.tts_stream.engine_for_voice", return_value="pockettts") def test_romanian_text_on_pockettts_falls_back_to_supertonic(self, _eng): ttsq = TTSQueue(voice_id="Marius 4") ttsq.push_text("Ora acum e nouă și cinci minute dimineața.") items = _drain_items(ttsq._text_queue) assert items, "clauzele trebuie să ajungă în coadă, nu să fie respinse" for clause, voice, lang in items: assert voice == DEFAULT_VOICE assert lang == "ro" @patch("src.voice.tts_stream.engine_for_voice", return_value="pockettts") def test_english_text_on_pockettts_keeps_cloned_voice(self, _eng): ttsq = TTSQueue(voice_id="Marius 4") ttsq.push_text("It's five past nine in the morning, Bucharest time.") items = _drain_items(ttsq._text_queue) assert items for clause, voice, lang in items: assert voice == "Marius 4" assert lang == "en" @patch("src.voice.tts_stream.engine_for_voice", return_value="supertonic") def test_supertonic_voice_unaffected(self, _eng): ttsq = TTSQueue(voice_id="M2") ttsq.push_text("Ora acum e nouă și cinci minute dimineața.") items = _drain_items(ttsq._text_queue) assert items for clause, voice, lang in items: assert voice == "M2" assert lang == "ro" class TestWorkerConsumesTuples: @patch("src.voice.tts_stream.synthesize", return_value={"ok": False, "error": "x"}) def test_worker_unpacks_clause_voice_lang(self, mock_synth): ttsq = TTSQueue(voice_id="Marius 4") ttsq._text_queue.put(("Hello there.", "Marius 4", "en")) ttsq.start() try: import time deadline = time.monotonic() + 2.0 while not mock_synth.called and time.monotonic() < deadline: time.sleep(0.02) finally: ttsq.stop() mock_synth.assert_called_once_with("Hello there.", voice="Marius 4", lang="en")