From db38085d07ce75f8961eecdc1919e98748254c53 Mon Sep 17 00:00:00 2001 From: historia Date: Fri, 28 Aug 2026 14:57:48 -0400 Subject: refactor: overhaul config.py, remove cli default options --- app/tests/test_converter.py | 57 ++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 19 deletions(-) (limited to 'app/tests/test_converter.py') diff --git a/app/tests/test_converter.py b/app/tests/test_converter.py index 4d7a064..eaf96ef 100644 --- a/app/tests/test_converter.py +++ b/app/tests/test_converter.py @@ -64,20 +64,29 @@ class ConfigurationValidationTests(unittest.TestCase): def test_language_defaults_to_config(self): with patch("converter.converter.QwenTTSClient") as mock_tts: - AudiobookConverter(backend=BACKEND_QWEN) + AudiobookConverter(backend=BACKEND_QWEN, voice="Vivian") self.assertEqual(mock_tts.call_args.kwargs["language"], config.LANGUAGE) def test_output_format_defaults_to_config(self): with patch("converter.converter.QwenTTSClient"): - converter = AudiobookConverter(backend=BACKEND_QWEN) + converter = AudiobookConverter(backend=BACKEND_QWEN, + voice="Vivian") self.assertEqual(converter.output_format, config.AUDIO_FORMAT) def test_language_normalized_before_tts_client(self): with patch("converter.converter.QwenTTSClient") as mock_tts: - converter = AudiobookConverter(language="ja", backend=BACKEND_QWEN) + converter = AudiobookConverter(language="ja", backend=BACKEND_QWEN, + voice="Vivian") self.assertEqual(converter.language, "Japanese") self.assertEqual(mock_tts.call_args.kwargs["language"], "Japanese") + def test_qwen_custom_voice_requires_a_speaker(self): + # There is no configured default speaker: a qwen built-in-speaker + # run must be told which one to use. + with self.assertRaises(ValueError) as ctx: + AudiobookConverter(backend=BACKEND_QWEN) + self.assertIn("requires a speaker", str(ctx.exception)) + class FindExistingOutputsTests(unittest.TestCase): def setUp(self): @@ -133,23 +142,23 @@ class FindExistingOutputsTests(unittest.TestCase): class NarratorTagTests(unittest.TestCase): - def _converter(self, voice_mode, ref_audio=None, instructions=None): + def _converter(self, voice_mode, ref_audio=None, instructions=None, + voice=None): converter = AudiobookConverter.__new__(AudiobookConverter) converter.voice_mode = voice_mode converter.voice_clone_ref_audio = ref_audio converter.backend = BACKEND_QWEN - converter.voice = None + converter.voice = voice converter.instructions = instructions return converter def test_custom_voice_uses_speaker_display_name(self): - self.assertEqual(self._converter(VOICE_MODE_CUSTOM)._narrator_tag(), - "Vivian") + converter = self._converter(VOICE_MODE_CUSTOM, voice="Vivian") + self.assertEqual(converter._narrator_tag(), "Vivian") def test_multi_word_display_name_gets_underscores(self): - with patch.object(config, "SPEAKER", "uncle_fu"): - self.assertEqual(self._converter(VOICE_MODE_CUSTOM)._narrator_tag(), - "Uncle_Fu") + converter = self._converter(VOICE_MODE_CUSTOM, voice="uncle_fu") + self.assertEqual(converter._narrator_tag(), "Uncle_Fu") def test_clone_uses_reference_audio_stem(self): self.assertEqual(self._converter(VOICE_MODE_CLONE, "/x/ref.wav")._narrator_tag(), @@ -186,14 +195,21 @@ class NarratorTagTests(unittest.TestCase): self.assertEqual(converter._narrator_tag(), "narrator") def test_audiocpp_speaker_mode_keeps_speaker_tag(self): - converter = self._audiocpp_converter() + converter = self._audiocpp_converter(voice="Vivian") self.assertEqual(converter._narrator_tag(), "Vivian") def test_audiocpp_explicit_speaker_uses_speaker_tag(self): - # A chosen CustomVoice speaker names the output, not config.SPEAKER. + # A chosen CustomVoice speaker names the output. converter = self._audiocpp_converter(voice="Ryan") self.assertEqual(converter._narrator_tag(), "Ryan") + def test_audiocpp_without_voice_or_instruction_uses_fallback_tag(self): + # A run like this fails at connect time (the client refuses a + # speaker-capable entry without --voice); the pre-flight still + # needs a stable tag for it. + converter = self._audiocpp_converter() + self.assertEqual(converter._narrator_tag(), "narrator") + def test_audiocpp_explicit_speaker_normalizes_display_name(self): converter = self._audiocpp_converter(voice="Uncle_Fu") self.assertEqual(converter._narrator_tag(), "Uncle_Fu") @@ -332,8 +348,11 @@ class DebugDumpTests(unittest.TestCase): def test_debug_flag_wiring(self): with patch("converter.converter.QwenTTSClient"): - self.assertFalse(AudiobookConverter(backend=BACKEND_QWEN).debug) - self.assertTrue(AudiobookConverter(debug=True, backend=BACKEND_QWEN).debug) + self.assertFalse(AudiobookConverter(backend=BACKEND_QWEN, + voice="Vivian").debug) + self.assertTrue(AudiobookConverter(debug=True, + backend=BACKEND_QWEN, + voice="Vivian").debug) class SetupLoggingTests(unittest.TestCase): @@ -549,14 +568,14 @@ class PreflightOverwritesTests(unittest.TestCase): (converter_mod.BOOKS_FOLDER / "book.txt").unlink() with patch("builtins.input", side_effect=AssertionError("should not prompt")): book_files, planned = AudiobookConverter.preflight_overwrites( - BACKEND_QWEN, None, VOICE_MODE_CUSTOM, None, "mp3") + BACKEND_QWEN, "Vivian", VOICE_MODE_CUSTOM, None, "mp3") self.assertEqual(book_files, []) self.assertEqual(planned, []) def test_new_book_planned_without_prompt(self): with patch("builtins.input", side_effect=AssertionError("should not prompt")): book_files, planned = AudiobookConverter.preflight_overwrites( - BACKEND_QWEN, None, VOICE_MODE_CUSTOM, None, "mp3") + BACKEND_QWEN, "Vivian", VOICE_MODE_CUSTOM, None, "mp3") self.assertEqual(len(book_files), 1) self.assertEqual(planned, [(book_files[0], "book_Vivian")]) @@ -564,14 +583,14 @@ class PreflightOverwritesTests(unittest.TestCase): (converter_mod.AUDIOBOOKS_FOLDER / "book_Vivian.mp3").write_bytes(b"existing") with patch("builtins.input", return_value=""): book_files, planned = AudiobookConverter.preflight_overwrites( - BACKEND_QWEN, None, VOICE_MODE_CUSTOM, None, "mp3") + BACKEND_QWEN, "Vivian", VOICE_MODE_CUSTOM, None, "mp3") self.assertEqual(planned, [(book_files[0], "book_Vivian")]) def test_existing_output_declined_is_skipped(self): (converter_mod.AUDIOBOOKS_FOLDER / "book_Vivian.mp3").write_bytes(b"existing") with patch("builtins.input", return_value="n"): book_files, planned = AudiobookConverter.preflight_overwrites( - BACKEND_QWEN, None, VOICE_MODE_CUSTOM, None, "mp3") + BACKEND_QWEN, "Vivian", VOICE_MODE_CUSTOM, None, "mp3") self.assertEqual(len(book_files), 1) self.assertEqual(planned, []) @@ -590,7 +609,7 @@ class RunOverwritePromptTests(unittest.TestCase): self.converter.voice_mode = VOICE_MODE_CUSTOM self.converter.voice_clone_ref_audio = None self.converter.backend = BACKEND_QWEN - self.converter.voice = None + self.converter.voice = "Vivian" self.converter.instructions = None self.converter.speed = 1.0 self.converter.single_file = False -- cgit v1.2.3