diff options
| author | historia <historiavg@proton.me> | 2026-08-24 03:41:57 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-24 03:41:57 -0400 |
| commit | 73b466fbc054e80b50e318b49643aee8a03c784b (patch) | |
| tree | df3d78efa84956bcf47586af736479f319a80abe /app/tests/test_hub.py | |
| parent | 471798cf5e967b2d1bceb02d12a47fe9ad1cbed1 (diff) | |
| download | tts-audiobook-generator-73b466fbc054e80b50e318b49643aee8a03c784b.tar.gz | |
feat: settings for ports in TUI
Diffstat (limited to 'app/tests/test_hub.py')
| -rw-r--r-- | app/tests/test_hub.py | 157 |
1 files changed, 132 insertions, 25 deletions
diff --git a/app/tests/test_hub.py b/app/tests/test_hub.py index 749d2e6..4b394e8 100644 --- a/app/tests/test_hub.py +++ b/app/tests/test_hub.py @@ -92,8 +92,7 @@ class HubMenuTests(unittest.TestCase): patch.object(hub, "detect_all", return_value=[]): hub._hub_menu(screen) labels = [label for label, _ in captured["options"]] - self.assertEqual(labels, ["Set up a backend...", "Settings...", - "Quit"]) + self.assertEqual(labels, ["Set up a backend", "Settings", "Quit"]) def test_menu_has_all_six_when_one_installed(self): captured = {} @@ -112,8 +111,9 @@ class HubMenuTests(unittest.TestCase): labels = [label for label, _ in captured["options"]] self.assertEqual( labels, - ["Convert books...", "Set up a backend...", - "Configure a backend...", "Server...", "Settings...", "Quit"]) + ["Convert books", "Set up a backend", + "Configure a backend", "Start/Stop Backend Servers", + "Settings", "Quit"]) # The status table is passed through, one row per backend. self.assertEqual(captured["rows"], [("qwen-tts", "installed", "warn", "body")]) @@ -157,8 +157,9 @@ class HubMenuTests(unittest.TestCase): labels = [label for label, _ in captured["options"]] self.assertEqual( labels, - ["Convert books...", "Set up a backend...", - "Configure a backend...", "Server...", "Settings...", "Quit"]) + ["Convert books", "Set up a backend", + "Configure a backend", "Start/Stop Backend Servers", + "Settings", "Quit"]) def test_ffmpeg_warning_shown_when_missing(self): # ffmpeg not on PATH → a red notice is passed above the table. @@ -194,7 +195,7 @@ class HubMenuTests(unittest.TestCase): def test_convert_with_no_available_backend_offers_setup(self): # One installed-but-not-ready backend → Convert is offered. The # convert menu lists no available backend, so only "Set up a - # backend..." is shown; Enter selects it → setup menu lists 3 + # backend" is shown; Enter selects it → setup menu lists 3 # backends; Esc goes back → convert returns None → main menu loops. # Then quit: main menu now has 5 options, Quit is the 5th (Down x4). from backends import BackendInfo, BackendStatus @@ -396,41 +397,53 @@ class SettingsTests(unittest.TestCase): original = {name: getattr(hub.config, name) for name in ("AUDIO_FORMAT", "AUDIO_BITRATE", "LANGUAGE", - "CHUNK_SIZE")} + "CHUNK_SIZE", "QWEN_API_URL", "CLONE_API_URL", + "FASTER_API_URL", "AUDIOCPP_API_URL")} self.addCleanup(lambda: [setattr(hub.config, name, value) for name, value in original.items()]) values = {"audio_format": "ogg", "audio_bitrate": " 192k ", - "language": "en", "chunk_size": "300"} - with patch.object(hub, "_write_config", fake_write): + "language": "en", "chunk_size": "300", + "qwen_custom_port": "7862", "qwen_clone_port": "7863", + "faster_port": "8001", "audiocpp_port": "8081"} + with patch.object(hub, "_write_config", fake_write), \ + patch.object(hub, "_sync_audiocpp_server_port"): hub._apply_settings(values) # Values are trimmed and language normalized to a display name. self.assertEqual(written, {"AUDIO_FORMAT": "ogg", "AUDIO_BITRATE": "192k", "LANGUAGE": "English", - "CHUNK_SIZE": 300}) + "CHUNK_SIZE": 300, + "QWEN_API_URL": "http://127.0.0.1:7862", + "CLONE_API_URL": "http://127.0.0.1:7863", + "FASTER_API_URL": "http://127.0.0.1:8001", + "AUDIOCPP_API_URL": + "http://127.0.0.1:8081"}) # In-memory config is reloaded so this session sees the change. self.assertEqual(hub.config.AUDIO_FORMAT, "ogg") self.assertEqual(hub.config.AUDIO_BITRATE, "192k") self.assertEqual(hub.config.LANGUAGE, "English") self.assertEqual(hub.config.CHUNK_SIZE, 300) + self.assertEqual(hub.config.QWEN_API_URL, "http://127.0.0.1:7862") + self.assertEqual(hub.config.FASTER_API_URL, "http://127.0.0.1:8001") def test_apply_settings_rejects_bad_values(self): original = {name: getattr(hub.config, name) for name in ("AUDIO_FORMAT", "AUDIO_BITRATE", "LANGUAGE", - "CHUNK_SIZE")} + "CHUNK_SIZE", "QWEN_API_URL", "CLONE_API_URL", + "FASTER_API_URL", "AUDIOCPP_API_URL")} self.addCleanup(lambda: [setattr(hub.config, name, value) for name, value in original.items()]) + base = {"audio_format": "m4b", "audio_bitrate": "128k", + "language": "English", "chunk_size": "250", + "qwen_custom_port": "7860", "qwen_clone_port": "7861", + "faster_port": "8000", "audiocpp_port": "8080"} with patch.object(hub, "_write_config") as mk_write: with self.assertRaises(ValueError): - hub._apply_settings({"audio_format": "m4b", - "audio_bitrate": "128k", - "language": "Klingon", - "chunk_size": "250"}) + hub._apply_settings({**base, "language": "Klingon"}) + with self.assertRaises(ValueError): + hub._apply_settings({**base, "chunk_size": "0"}) with self.assertRaises(ValueError): - hub._apply_settings({"audio_format": "m4b", - "audio_bitrate": "128k", - "language": "English", - "chunk_size": "0"}) + hub._apply_settings({**base, "audiocpp_port": "70000"}) mk_write.assert_not_called() def test_field_validators(self): @@ -442,6 +455,12 @@ class SettingsTests(unittest.TestCase): self.assertIsNone(hub._validate_chunk_size("250")) self.assertIsNotNone(hub._validate_chunk_size("abc")) self.assertIsNotNone(hub._validate_chunk_size("0")) + self.assertIsNone(hub._validate_port("8080")) + self.assertIsNone(hub._validate_port("1")) + self.assertIsNone(hub._validate_port("65535")) + self.assertIsNotNone(hub._validate_port("0")) + self.assertIsNotNone(hub._validate_port("70000")) + self.assertIsNotNone(hub._validate_port("abc")) def test_settings_menu_builds_form_and_saves(self): captured = {} @@ -449,7 +468,9 @@ class SettingsTests(unittest.TestCase): def fake_form(stdscr, title, fields, back_value=None): captured["fields"] = fields return {"audio_format": "ogg", "audio_bitrate": "192k", - "language": "English", "chunk_size": "300"} + "language": "English", "chunk_size": "300", + "qwen_custom_port": "7860", "qwen_clone_port": "7861", + "faster_port": "8000", "audiocpp_port": "8080"} applied = [] @@ -465,14 +486,20 @@ class SettingsTests(unittest.TestCase): hub._settings_menu(None) self.assertEqual([f["key"] for f in captured["fields"]], ["audio_format", "audio_bitrate", "language", - "chunk_size"]) + "chunk_size", "qwen_custom_port", "qwen_clone_port", + "faster_port", "audiocpp_port"]) kinds = {f["key"]: f["kind"] for f in captured["fields"]} self.assertEqual(kinds["audio_format"], "choice") self.assertEqual(kinds["audio_bitrate"], "text") + self.assertEqual(kinds["audiocpp_port"], "text") self.assertEqual(applied, [{"audio_format": "ogg", "audio_bitrate": "192k", "language": "English", - "chunk_size": "300"}]) + "chunk_size": "300", + "qwen_custom_port": "7860", + "qwen_clone_port": "7861", + "faster_port": "8000", + "audiocpp_port": "8080"}]) self.assertEqual(captured["flash"], ("Settings saved.", "ok")) def test_settings_menu_cancel_does_not_apply(self): @@ -500,7 +527,8 @@ class SettingsTests(unittest.TestCase): original = {name: getattr(hub.config, name) for name in ("AUDIO_FORMAT", "AUDIO_BITRATE", "LANGUAGE", - "CHUNK_SIZE")} + "CHUNK_SIZE", "QWEN_API_URL", "CLONE_API_URL", + "FASTER_API_URL", "AUDIOCPP_API_URL")} self.addCleanup(lambda: [setattr(hub.config, name, value) for name, value in original.items()]) @@ -512,7 +540,11 @@ class SettingsTests(unittest.TestCase): 'AUDIO_BITRATE = "128k"\n' 'LANGUAGE = "English"\n' "\n" - "CHUNK_SIZE = 250\n", + "CHUNK_SIZE = 250\n" + 'QWEN_API_URL = "http://127.0.0.1:7860"\n' + 'CLONE_API_URL = "http://127.0.0.1:7861"\n' + 'FASTER_API_URL = "http://127.0.0.1:8000"\n' + 'AUDIOCPP_API_URL = "http://127.0.0.1:8080"\n', encoding="utf-8") with patch.object(hub.config, "__file__", str(path)): # Down to Chunk size, Enter -> editor, Ctrl-U + '300', @@ -528,6 +560,81 @@ class SettingsTests(unittest.TestCase): # The running session also picked up the change in-memory. self.assertEqual(hub.config.CHUNK_SIZE, 300) + def test_settings_menu_updates_backend_ports(self): + import tempfile + original = {name: getattr(hub.config, name) for name in + ("QWEN_API_URL", "CLONE_API_URL", + "FASTER_API_URL", "AUDIOCPP_API_URL")} + self.addCleanup(lambda: [setattr(hub.config, name, value) + for name, value in original.items()]) + with tempfile.TemporaryDirectory() as td: + path = Path(td) / "config.py" + path.write_text( + 'QWEN_API_URL = "http://127.0.0.1:7860"\n' + 'CLONE_API_URL = "http://127.0.0.1:7861"\n' + 'FASTER_API_URL = "http://127.0.0.1:8000"\n' + 'AUDIOCPP_API_URL = "http://127.0.0.1:8080"\n', + encoding="utf-8") + with patch.object(hub.config, "__file__", str(path)), \ + patch.object(hub, "_sync_audiocpp_server_port"): + hub._write_config({ + "QWEN_API_URL": "http://127.0.0.1:7862", + "CLONE_API_URL": "http://127.0.0.1:7863", + "FASTER_API_URL": "http://127.0.0.1:8001", + "AUDIOCPP_API_URL": "http://127.0.0.1:8081", + }) + text = path.read_text(encoding="utf-8") + self.assertIn('QWEN_API_URL = "http://127.0.0.1:7862"', text) + self.assertIn('CLONE_API_URL = "http://127.0.0.1:7863"', text) + self.assertIn('FASTER_API_URL = "http://127.0.0.1:8001"', text) + self.assertIn('AUDIOCPP_API_URL = "http://127.0.0.1:8081"', text) + + +class AudiocppServerConfigTests(unittest.TestCase): + """update_server_config_port: rewriting the checkout's server.json.""" + + def _make_checkout(self, td, port=8080): + from backends import audiocpp as audiocpp_backend + import json + checkout = Path(td) / "audio.cpp" + checkout.mkdir() + server_json = checkout / "server.json" + server_json.write_text( + json.dumps({"host": "127.0.0.1", "port": port, + "models": [{"id": "qwen"}]}, indent=2), + encoding="utf-8") + return audiocpp_backend, checkout, server_json + + def test_rewrites_existing_server_json_port(self): + import tempfile + import json + with tempfile.TemporaryDirectory() as td: + mod, checkout, server_json = self._make_checkout(td, port=8080) + with patch.object(mod, "find_local_checkout", + return_value=checkout): + self.assertTrue(mod.update_server_config_port(9090)) + data = json.loads(server_json.read_text(encoding="utf-8")) + self.assertEqual(data["port"], 9090) + # Other keys are preserved. + self.assertEqual(data["host"], "127.0.0.1") + self.assertEqual(data["models"], [{"id": "qwen"}]) + + def test_noop_when_port_unchanged(self): + import tempfile + with tempfile.TemporaryDirectory() as td: + mod, checkout, server_json = self._make_checkout(td, port=8080) + before = server_json.read_text(encoding="utf-8") + with patch.object(mod, "find_local_checkout", + return_value=checkout): + self.assertTrue(mod.update_server_config_port(8080)) + self.assertEqual(server_json.read_text(encoding="utf-8"), before) + + def test_false_when_no_checkout(self): + from backends import audiocpp as audiocpp_backend + with patch.object(audiocpp_backend, "find_local_checkout", + return_value=None): + self.assertFalse(audiocpp_backend.update_server_config_port(9090)) + if __name__ == "__main__": unittest.main() |
