aboutsummaryrefslogtreecommitdiff
path: root/app/tests/test_runview.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-25 20:10:40 -0400
committerhistoria <historiavg@proton.me>2026-08-25 20:10:40 -0400
commitca3c78ef577f5d8435dd10db0296c3e2fd8e69e2 (patch)
treecff4b84c14d0ac88bc53f2aef63115352d57de90 /app/tests/test_runview.py
parent757588321d4c27889be6e8e3c12b75873ad1218d (diff)
downloadtts-audiobook-generator-ca3c78ef577f5d8435dd10db0296c3e2fd8e69e2.tar.gz
feat: stop server and exit after generating
Diffstat (limited to 'app/tests/test_runview.py')
-rw-r--r--app/tests/test_runview.py81
1 files changed, 81 insertions, 0 deletions
diff --git a/app/tests/test_runview.py b/app/tests/test_runview.py
index 556cb52..31a8ebe 100644
--- a/app/tests/test_runview.py
+++ b/app/tests/test_runview.py
@@ -171,6 +171,10 @@ class RenderTests(_FakeTui, unittest.TestCase):
text = self._strings(screen)
self.assertIn("stopping", text)
self.assertIn("(1s)", text)
+ # The stop wait ignores keys, so the footer must not promise that
+ # pressing one returns to the menu.
+ self.assertNotIn("press any key", text)
+ self.assertIn("stopping the audiocpp server...", text)
def test_error_screen_shows_detail_and_log(self):
view, screen = self.make_view(log_path="/tmp/audiobook.log")
@@ -236,6 +240,83 @@ class RunLoopTests(_FakeTui, unittest.TestCase):
view.run()
mk_stop.assert_not_called()
+ def test_finished_run_toggle_off_waits_for_key_then_menu(self):
+ # Toggle off: a key on the summary screen returns to the menu; no
+ # prompt is asked and the server keeps running.
+ with patch.object(runview.tui, "confirm") as mk_confirm, \
+ patch.object(runview.servers, "alive", return_value=True), \
+ patch.object(runview.servers, "stop") as mk_stop:
+ view, screen = self.make_view(keys=[ord("x")],
+ autostart_spec="SPEC")
+ view.started_server = True
+ view._queue.put({"kind": "done", "ok": 1, "total": 1})
+ result = view.run()
+ self.assertFalse(result)
+ mk_confirm.assert_not_called()
+ mk_stop.assert_not_called()
+
+ def test_stop_and_exit_stops_server_and_quits_without_keys(self):
+ # Toggle on: the moment the run ends the server is stopped and the
+ # view reports quit — no key press and no prompt anywhere.
+ with patch.object(runview.servers, "alive", return_value=True), \
+ patch.object(runview.servers, "stop") as mk_stop, \
+ patch.object(runview.common,
+ "record_post_tui_notice") as mk_notice:
+ view, screen = self.make_view([], autostart_spec="SPEC",
+ stop_and_exit=True)
+ view.started_server = True
+ view._queue.put({"kind": "book", "index": 1, "total": 1,
+ "name": "book.txt"})
+ view._queue.put({"kind": "book_done", "name": "book.txt",
+ "ok": True,
+ "files": ["book_test_michael.mp3"]})
+ view._queue.put({"kind": "done", "ok": 1, "total": 1})
+ result = view.run()
+ self.assertTrue(result)
+ mk_stop.assert_called_once_with("audiocpp")
+ text = mk_notice.call_args[0][0]
+ self.assertIn("Output directory:", text)
+ self.assertIn("[OK] book.txt: book_test_michael.mp3", text)
+ self.assertIn("1 of 1 book(s) generated successfully", text)
+ self.assertIn("Elapsed time:", text)
+
+ def test_stop_and_exit_leaves_external_servers_alone(self):
+ # A server this run did not start is never stopped; the TUI still
+ # quits and the summary is still printed.
+ with patch.object(runview.servers, "stop") as mk_stop, \
+ patch.object(runview.common,
+ "record_post_tui_notice") as mk_notice:
+ view, screen = self.make_view([], server_name=None,
+ stop_and_exit=True)
+ view.started_server = False
+ view._queue.put({"kind": "done", "ok": 1, "total": 1})
+ result = view.run()
+ self.assertTrue(result)
+ mk_stop.assert_not_called()
+ self.assertIn("No books were converted",
+ mk_notice.call_args[0][0])
+
+ def test_stop_and_exit_failure_summary_lists_the_error(self):
+ # A failed ending also auto-exits; the failing book's detail line
+ # lands in the post-TUI summary.
+ with patch.object(runview.servers, "alive", return_value=True), \
+ patch.object(runview.servers, "stop"), \
+ patch.object(runview.common,
+ "record_post_tui_notice") as mk_notice:
+ view, screen = self.make_view([], autostart_spec="SPEC",
+ stop_and_exit=True)
+ view.started_server = True
+ view._queue.put({"kind": "book_failed", "name": "bad.txt",
+ "error": "chunk 3 failed",
+ "files": ["bad_x.mp3"]})
+ view._queue.put({"kind": "done", "ok": 0, "total": 1})
+ result = view.run()
+ self.assertTrue(result)
+ text = mk_notice.call_args[0][0]
+ self.assertIn("[FAIL] bad.txt: bad_x.mp3", text)
+ self.assertIn("chunk 3 failed", text)
+ self.assertIn("0 of 1 book(s) generated successfully", text)
+
class WorkerTests(_FakeTui, unittest.TestCase):
"""The worker thread's handoff into audiobook.convert."""