aboutsummaryrefslogtreecommitdiff
path: root/app/tests/test_hub.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/tests/test_hub.py')
-rw-r--r--app/tests/test_hub.py50
1 files changed, 50 insertions, 0 deletions
diff --git a/app/tests/test_hub.py b/app/tests/test_hub.py
index 6657540..73ef075 100644
--- a/app/tests/test_hub.py
+++ b/app/tests/test_hub.py
@@ -856,6 +856,56 @@ class ConvertFlowTests(unittest.TestCase):
instr = self._field("instructions")
self.assertFalse(instr["visible"](fields))
+ def test_audiocpp_remote_without_voices_refuses_generate_with_hint(self):
+ # A clone-capable entry (e.g. Qwen Base) whose server lists no
+ # voices at all: the Voice picker stays visible but is empty —
+ # opening it flashes where to configure voices instead of
+ # crashing — and Generate! refuses with the same hint.
+ self._patch_remote(
+ [{"id": "Qwen3-TTS-12Hz-1.7B-Base-GGUF",
+ "family": "qwen3_tts", "task": "tts"}],
+ voices=[])
+ with patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ self._answer_form(
+ backend="audiocpp-remote",
+ model_id="Qwen3-TTS-12Hz-1.7B-Base-GGUF",
+ audiocpp_voice="", instructions="")
+ self._convert(None, [self._remote("audiocpp", "audio.cpp")])
+ fields = self.tui.forms_seen[0][1]
+ voice_field = self._field("audiocpp_voice")
+ self.assertTrue(voice_field["visible"](fields))
+ self.assertEqual(voice_field["choices"](fields), [])
+ error = voice_field["validate"]("")
+ self.assertIsNotNone(error)
+ self.assertIn(".wav", error)
+ self.assertIn("server", error)
+
+ def test_audiocpp_local_without_voice_dir_points_at_configure(self):
+ # The managed entry's server.json has no voice_dir: clone-capable
+ # models get an empty Voice picker whose hint sends the user to
+ # Configure backends instead of crashing on menu().
+ with tempfile.TemporaryDirectory() as td:
+ root = Path(td)
+ (root / "server.json").write_text(json.dumps({
+ "models": [{"id": "qwen", "family": "qwen3_tts",
+ "task": "tts"}],
+ }), encoding="utf-8")
+ with patch.object(hub.audiocpp_backend, "find_local_checkout",
+ return_value=root), \
+ patch.object(hub.config, "AUDIOCPP_INSTRUCTIONS", ""):
+ self._answer_form(backend="audiocpp", model_id="qwen",
+ audiocpp_voice="", instructions="")
+ self._convert(None,
+ [self._ready("audiocpp", "audio.cpp")])
+ fields = self.tui.forms_seen[0][1]
+ voice_field = self._field("audiocpp_voice")
+ self.assertTrue(voice_field["visible"](fields))
+ self.assertEqual(voice_field["choices"](fields), [])
+ error = voice_field["validate"]("")
+ self.assertIsNotNone(error)
+ self.assertIn(".wav", error)
+ self.assertIn("Configure backends", error)
+
def test_audiocpp_remote_missing_family_is_clone_capable(self):
# A missing family is unknown — not guessed as qwen3_tts — so the
# entry is clone-only: it needs a --voice rather than offering a