aboutsummaryrefslogtreecommitdiff
path: root/app/tests/test_runview.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/tests/test_runview.py')
-rw-r--r--app/tests/test_runview.py65
1 files changed, 65 insertions, 0 deletions
diff --git a/app/tests/test_runview.py b/app/tests/test_runview.py
index f2d5180..8feeee1 100644
--- a/app/tests/test_runview.py
+++ b/app/tests/test_runview.py
@@ -10,6 +10,7 @@ cancel → stop-server flow.
import os
import sys
import tempfile
+import types
import unittest
from queue import Empty
from unittest.mock import patch
@@ -129,6 +130,70 @@ class StateTransitionTests(_FakeTui, unittest.TestCase):
self.assertEqual(view.server, "stopped")
+class LogAppenderTests(_FakeTui, unittest.TestCase):
+ """_LogAppender: stray console output survives in the run's log file."""
+
+ def _appender(self):
+ tmp = tempfile.TemporaryDirectory()
+ self.addCleanup(tmp.cleanup)
+ path = os.path.join(tmp.name, "audiobook_20260828.log")
+ return path, runview._LogAppender(path)
+
+ def test_write_splits_lines_into_the_file(self):
+ path, appender = self._appender()
+ appender.write("one\ntwo\n")
+ appender.write("three")
+ appender.flush()
+ with open(path, encoding="utf-8") as handle:
+ lines = handle.read().splitlines()
+ self.assertEqual(len(lines), 3)
+ self.assertTrue(lines[0].endswith(" - one"))
+ self.assertTrue(lines[2].endswith(" - three"))
+
+ def test_blank_lines_and_empty_path_are_skipped(self):
+ path, appender = self._appender()
+ appender.write("\n\n")
+ appender.flush()
+ appender.write("x")
+ appender.flush()
+ empty = runview._LogAppender("")
+ empty.write("ignored\n") # must not raise
+ with open(path, encoding="utf-8") as handle:
+ self.assertEqual(len(handle.read().splitlines()), 1)
+
+ def test_unwritable_path_never_raises(self):
+ appender = runview._LogAppender("/nonexistent-dir-zz/log.log")
+ appender.write("boom\n") # must not raise
+ appender.flush()
+
+ def test_worker_stdout_is_mirrored_to_the_run_log(self):
+ tmp = tempfile.TemporaryDirectory()
+ self.addCleanup(tmp.cleanup)
+ log_path = os.path.join(tmp.name, "audiobook_20260828.log")
+ view, _ = self.make_view(log_path=log_path)
+
+ fake = types.ModuleType("audiobook")
+
+ def convert(**_kwargs):
+ print("[INFO] stray console output")
+
+ fake.convert = convert
+ with patch.dict(sys.modules, {"audiobook": fake}):
+ view._worker_main()
+
+ with open(log_path, encoding="utf-8") as handle:
+ text = handle.read()
+ self.assertIn("[INFO] stray console output", text)
+ # The worker signed off normally through the event queue.
+ kinds = []
+ while True:
+ try:
+ kinds.append(view._queue.get_nowait()["kind"])
+ except Empty:
+ break
+ self.assertEqual(kinds, ["worker_exit"])
+
+
class RenderTests(_FakeTui, unittest.TestCase):
def _strings(self, screen):
return " ".join(text for _, _, text, _ in screen.strings)