aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-18 02:18:17 -0400
committerhistoria <historiavg@proton.me>2026-08-18 02:18:17 -0400
commitcacc2064aa1e7c81436862db4be6cb8fc836a5cd (patch)
tree8a8aeb7844338479ab8f476e1827ed2d5caa15c8 /tests
parente650d17b07cceb660ef8686fd1f122d50fa3a05c (diff)
downloadtts-audiobook-generator-cacc2064aa1e7c81436862db4be6cb8fc836a5cd.tar.gz
test(converter): ffmetadata escaping and chunk collection
Diffstat (limited to 'tests')
-rw-r--r--tests/test_audio.py58
-rw-r--r--tests/test_converter.py14
2 files changed, 72 insertions, 0 deletions
diff --git a/tests/test_audio.py b/tests/test_audio.py
index f36ed54..7e782cc 100644
--- a/tests/test_audio.py
+++ b/tests/test_audio.py
@@ -8,6 +8,7 @@ from pathlib import Path
from converter import audio
from converter import config
from converter.audio import (
+ _collect_chunk_files,
_encode_args,
build_concat_command,
build_ffmetadata,
@@ -142,6 +143,43 @@ class BuildConcatCommandTests(unittest.TestCase):
self.assertIn("pcm_s16le", cmd)
self.assertNotIn("-movflags", cmd)
+ def test_speed_without_speed_path_rejected(self):
+ with self.assertRaises(ValueError):
+ build_concat_command(Path("list.txt"), Path("out.mp3"), "mp3", speed=1.5)
+
+
+class CollectChunkFilesTests(unittest.TestCase):
+ def test_uses_recorded_paths_exactly(self):
+ with tempfile.TemporaryDirectory() as tmp:
+ present = Path(tmp) / "chunk_0001.wav"
+ present.write_bytes(b"audio")
+ chunk_results = {
+ 1: present,
+ 2: None, # failed chunk
+ 3: Path(tmp) / "chunk_0003.wav", # recorded but deleted
+ }
+ files, missing = _collect_chunk_files(3, chunk_results)
+
+ self.assertEqual(files, [present])
+ self.assertEqual(missing, [2, 3])
+
+ def test_glob_fallback_without_results(self):
+ with tempfile.TemporaryDirectory() as tmp:
+ chunks_dir = Path(tmp)
+ (chunks_dir / "chunk_0002.wav").write_bytes(b"audio")
+ (chunks_dir / "chunk_0001.wav").write_bytes(b"audio")
+
+ original = config.CHUNKS_FOLDER
+ config.CHUNKS_FOLDER = chunks_dir
+ try:
+ files, missing = _collect_chunk_files(3)
+ finally:
+ config.CHUNKS_FOLDER = original
+
+ self.assertEqual(files, [chunks_dir / "chunk_0001.wav",
+ chunks_dir / "chunk_0002.wav"])
+ self.assertEqual(missing, [3])
+
class BuildM4bChaptersCommandTests(unittest.TestCase):
def setUp(self):
@@ -222,6 +260,26 @@ class BuildFFMetadataTests(unittest.TestCase):
self.assertIn("START=1200", content)
self.assertIn("title=Two", content)
+ def test_escapes_special_characters(self):
+ # ffmpeg's FFMETADATA format treats = ; # and \ as structural.
+ chapters = [(0, 1000, "A = B; C# D\\E")]
+ with tempfile.TemporaryDirectory() as tmp:
+ path = Path(tmp) / "meta.txt"
+ build_ffmetadata(chapters, path)
+ content = path.read_text(encoding="utf-8")
+
+ self.assertIn(r"title=A \= B\; C\# D\\E", content)
+
+ def test_collapses_newlines_in_titles(self):
+ chapters = [(0, 1000, "Two\nLines")]
+ with tempfile.TemporaryDirectory() as tmp:
+ path = Path(tmp) / "meta.txt"
+ build_ffmetadata(chapters, path)
+ content = path.read_text(encoding="utf-8")
+
+ self.assertIn("title=Two Lines\n", content)
+ self.assertNotIn("title=Two\n", content)
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/test_converter.py b/tests/test_converter.py
index 1235dda..9c03e30 100644
--- a/tests/test_converter.py
+++ b/tests/test_converter.py
@@ -17,5 +17,19 @@ class SanitizeFilenameTests(unittest.TestCase):
self.assertEqual(AudiobookConverter._sanitize_filename("///"), "chapter")
+class ConfigurationValidationTests(unittest.TestCase):
+ def test_invalid_voice_mode_rejected(self):
+ with self.assertRaises(ValueError):
+ AudiobookConverter(voice_mode="custon_voice")
+
+ def test_nonpositive_speed_rejected(self):
+ with self.assertRaises(ValueError):
+ AudiobookConverter(speed=0)
+
+ def test_unknown_format_rejected(self):
+ with self.assertRaises(ValueError):
+ AudiobookConverter(output_format="ogg")
+
+
if __name__ == "__main__":
unittest.main()