import tempfile import unittest from pathlib import Path import generate_abs_mock_report as report class InferBookTests(unittest.TestCase): def infer_row(self, relative_book_path: str, filenames: list[str]) -> dict[str, str]: with tempfile.TemporaryDirectory() as tmpdir: library_root = Path(tmpdir) / "library" book_root = library_root / relative_book_path book_root.mkdir(parents=True) for filename in filenames: (book_root / filename).write_bytes(b"") audio_files = sorted(book_root.glob("*.mp3")) return report.infer_book(book_root, library_root, audio_files) def test_splits_author_from_title_context_in_folder_name(self) -> None: row = self.infer_row( "Biblioteka 2024/Bartos_Jolanta_Krzyk_Ciszy", ["001_Krzyk_ciszy.mp3", "002_Krzyk_ciszy.mp3"], ) self.assertEqual(report.signature(row["title"]), "krzyk ciszy") self.assertNotIn("krzyk", report.signature(row["author"])) self.assertTrue(row["proposed_abs_path"].endswith("/Krzyk Ciszy")) def test_normalizes_author_order_from_current_directory(self) -> None: row = self.infer_row( "Ahnhem Stefan/Stefan Ahnhem - Kain I Abel", ["001_Kain_I_Abel.mp3"], ) self.assertEqual(row["author"], "Stefan Ahnhem") self.assertTrue(row["proposed_abs_path"].startswith("Stefan Ahnhem/")) def test_normalizes_author_order_from_audio_filename(self) -> None: row = self.infer_row( "Archer_Jeffrey/Kain_I_Abel", [ "001_Jeffrey_Archer_-_Kain_I_Abel.mp3", "002_Jeffrey_Archer_-_Kain_I_Abel.mp3", ], ) self.assertEqual(row["author"], "Jeffrey Archer") self.assertTrue(row["proposed_abs_path"].startswith("Jeffrey Archer/")) def test_handles_hyphenated_surname_in_mixed_folder_name(self) -> None: row = self.infer_row( "Adler-Olsen/Jussi Adler-Olsen - Departament Q tom 1-8/Adler-Olsen Jussi - Departament Q 04. Kartoteka 64", ["01 - Kartoteka_64.mp3"], ) self.assertEqual(row["author"], "Jussi Adler-Olsen") self.assertEqual(row["series"], "Departament Q") self.assertEqual(row["sequence"], "04") self.assertEqual(row["title"], "Kartoteka 64") self.assertTrue(row["proposed_abs_path"].startswith("Jussi Adler-Olsen/")) def test_extracts_series_from_nested_mixed_folder(self) -> None: row = self.infer_row( "Adler-Olsen/Jussi Adler-Olsen - Departament Q tom 1-8/Adler-Olsen Jussi - Departament Q Tom 01 Kobieta w klatce/Adler - Olsen Jussi - Kobieta w klatce (czyta Janusz Zadura)", ["01.mp3"], ) self.assertEqual(row["author"], "Jussi Adler-Olsen") self.assertEqual(row["series"], "Departament Q") self.assertEqual(row["sequence"], "01") self.assertEqual(row["title"], "Kobieta w klatce") def test_extracts_series_from_inline_series_number_title(self) -> None: row = self.infer_row( "Adler-Olsen/Jussi Adler-Olsen - Departament Q tom 1-8/Adler-Olsen Jussi - Departament Q 05 Pogrzebany", ["01.mp3"], ) self.assertEqual(row["author"], "Jussi Adler-Olsen") self.assertEqual(row["series"], "Departament Q") self.assertEqual(row["sequence"], "05") self.assertEqual(row["title"], "Pogrzebany") def test_build_proposed_path_omits_author_from_subfolders(self) -> None: proposed_path = report.build_proposed_abs_path( "Jussi Adler-Olsen", "Adler-Olsen Jussi - Departament Q", "04", "", "Kartoteka 64 - Jussi Adler-Olsen", "", ) self.assertEqual( proposed_path, "Jussi Adler-Olsen/Departament Q/Vol. 04 - Kartoteka 64", ) def test_build_proposed_path_omits_author_only_series_folder(self) -> None: proposed_path = report.build_proposed_abs_path( "Jeffrey Archer", "Archer", "", "", "Kain I Abel", "", ) self.assertEqual(proposed_path, "Jeffrey Archer/Kain I Abel") def test_strips_nearly_matching_author_prefix_from_title(self) -> None: row = self.infer_row( "Abmercombie Joe/Abercrombie Joe - Czerwona kraina (Audiobooki2.pl)", ["Czerwona kraina (01).mp3"], ) self.assertEqual(row["author"], "Abmercombie Joe") self.assertEqual(row["title"], "Czerwona kraina (Audiobooki2 pl)") self.assertEqual( row["proposed_abs_path"], "Abmercombie Joe/Czerwona kraina (Audiobooki2 pl)", ) def test_strips_nearly_matching_author_prefix_from_nested_title(self) -> None: row = self.infer_row( "Dan Simons/Dan Simmons - cykl Hyperion (tom 3) Endymion (Audiobooki2.pl)", ["001 Endymion.mp3"], ) self.assertEqual(row["author"], "Dan Simons") self.assertEqual(row["title"], "cykl Hyperion (tom 3) Endymion (Audiobooki2 pl)") self.assertEqual( row["proposed_abs_path"], "Dan Simons/cykl Hyperion (tom 3) Endymion (Audiobooki2 pl)", ) def test_strips_multi_author_prefix_when_current_author_is_in_root(self) -> None: row = self.infer_row( "Chmielarz Wojciech/Ćwiek Jakub i Chmielarz Wojciech - Skowyt", ["1.mp3"], ) self.assertEqual(row["author"], "Chmielarz Wojciech") self.assertEqual(row["title"], "Skowyt") self.assertEqual(row["proposed_abs_path"], "Chmielarz Wojciech/Skowyt") if __name__ == "__main__": unittest.main()