codex author changes
This commit is contained in:
230
tests/test_apply_abs_mock_report.py
Normal file
230
tests/test_apply_abs_mock_report.py
Normal file
@@ -0,0 +1,230 @@
|
||||
import csv
|
||||
import io
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
import apply_abs_mock_report as apply_report
|
||||
|
||||
|
||||
class ApplyAbsMockReportTests(unittest.TestCase):
|
||||
def write_report(self, path: Path, rows: list[dict[str, str]]) -> None:
|
||||
fieldnames = [
|
||||
"verification_status",
|
||||
"verification_source",
|
||||
"verification_note",
|
||||
"status",
|
||||
"current_path",
|
||||
"audio_file_count",
|
||||
"sample_audio_file",
|
||||
"author",
|
||||
"author_confidence",
|
||||
"author_source",
|
||||
"series",
|
||||
"sequence",
|
||||
"publish_year",
|
||||
"title",
|
||||
"title_source",
|
||||
"narrator",
|
||||
"proposed_abs_path",
|
||||
"notes",
|
||||
]
|
||||
with path.open("w", encoding="utf-8", newline="") as handle:
|
||||
writer = csv.DictWriter(handle, fieldnames=fieldnames, delimiter="\t")
|
||||
writer.writeheader()
|
||||
writer.writerows(rows)
|
||||
|
||||
def create_book(self, root: Path, relative_path: str) -> Path:
|
||||
book_root = root / relative_path
|
||||
(book_root / "Disc 1").mkdir(parents=True)
|
||||
(book_root / "Disc 1" / "01.mp3").write_bytes(b"audio")
|
||||
(book_root / "cover.jpg").write_bytes(b"cover")
|
||||
return book_root
|
||||
|
||||
def test_copy_mode_recreates_report_structure(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
tmp = Path(tmpdir)
|
||||
source_root = tmp / "source"
|
||||
destination_root = tmp / "destination"
|
||||
report_path = tmp / "report.tsv"
|
||||
book_root = self.create_book(source_root, "Old Author/Old Book")
|
||||
|
||||
self.write_report(
|
||||
report_path,
|
||||
[
|
||||
{
|
||||
"status": "ready",
|
||||
"current_path": str(book_root),
|
||||
"proposed_abs_path": "New Author/New Series/Vol. 01 - New Book",
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
exit_code = apply_report.main(
|
||||
[
|
||||
"--report",
|
||||
str(report_path),
|
||||
"--destination-root",
|
||||
str(destination_root),
|
||||
"--mode",
|
||||
"copy",
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(exit_code, 0)
|
||||
copied_root = destination_root / "New Author" / "New Series" / "Vol. 01 - New Book"
|
||||
self.assertTrue((copied_root / "Disc 1" / "01.mp3").exists())
|
||||
self.assertTrue((copied_root / "cover.jpg").exists())
|
||||
self.assertTrue((book_root / "Disc 1" / "01.mp3").exists())
|
||||
|
||||
def test_move_mode_removes_source_tree(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
tmp = Path(tmpdir)
|
||||
source_root = tmp / "source"
|
||||
destination_root = tmp / "destination"
|
||||
report_path = tmp / "report.tsv"
|
||||
book_root = self.create_book(source_root, "Old Author/Old Book")
|
||||
|
||||
self.write_report(
|
||||
report_path,
|
||||
[
|
||||
{
|
||||
"status": "ready",
|
||||
"current_path": str(book_root),
|
||||
"proposed_abs_path": "Author/Book",
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
exit_code = apply_report.main(
|
||||
[
|
||||
"--report",
|
||||
str(report_path),
|
||||
"--destination-root",
|
||||
str(destination_root),
|
||||
"--mode",
|
||||
"move",
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(exit_code, 0)
|
||||
moved_root = destination_root / "Author" / "Book"
|
||||
self.assertTrue((moved_root / "Disc 1" / "01.mp3").exists())
|
||||
self.assertFalse(book_root.exists())
|
||||
|
||||
def test_dry_run_prints_plan_without_creating_destination(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
tmp = Path(tmpdir)
|
||||
source_root = tmp / "source"
|
||||
destination_root = tmp / "destination"
|
||||
report_path = tmp / "report.tsv"
|
||||
book_root = self.create_book(source_root, "Old Author/Old Book")
|
||||
|
||||
self.write_report(
|
||||
report_path,
|
||||
[
|
||||
{
|
||||
"status": "ready",
|
||||
"current_path": str(book_root),
|
||||
"proposed_abs_path": "Author/Book",
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
stdout = io.StringIO()
|
||||
with mock.patch("sys.stdout", stdout):
|
||||
exit_code = apply_report.main(
|
||||
[
|
||||
"--report",
|
||||
str(report_path),
|
||||
"--destination-root",
|
||||
str(destination_root),
|
||||
"--dry-run",
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(exit_code, 0)
|
||||
self.assertIn("plan\t", stdout.getvalue())
|
||||
self.assertFalse(destination_root.exists())
|
||||
|
||||
def test_duplicate_targets_fail_validation(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
tmp = Path(tmpdir)
|
||||
source_root = tmp / "source"
|
||||
report_path = tmp / "report.tsv"
|
||||
first_book = self.create_book(source_root, "Author A/Book One")
|
||||
second_book = self.create_book(source_root, "Author B/Book Two")
|
||||
|
||||
self.write_report(
|
||||
report_path,
|
||||
[
|
||||
{
|
||||
"status": "ready",
|
||||
"current_path": str(first_book),
|
||||
"proposed_abs_path": "Author/Shared",
|
||||
},
|
||||
{
|
||||
"status": "ready",
|
||||
"current_path": str(second_book),
|
||||
"proposed_abs_path": "Author/Shared",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
stderr = io.StringIO()
|
||||
with mock.patch("sys.stderr", stderr):
|
||||
exit_code = apply_report.main(
|
||||
[
|
||||
"--report",
|
||||
str(report_path),
|
||||
"--destination-root",
|
||||
str(tmp / "destination"),
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(exit_code, 1)
|
||||
self.assertIn("duplicate proposed_abs_path", stderr.getvalue())
|
||||
|
||||
def test_default_status_only_applies_ready_rows(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
tmp = Path(tmpdir)
|
||||
source_root = tmp / "source"
|
||||
destination_root = tmp / "destination"
|
||||
report_path = tmp / "report.tsv"
|
||||
ready_book = self.create_book(source_root, "Ready Author/Ready Book")
|
||||
review_book = self.create_book(source_root, "Review Author/Review Book")
|
||||
|
||||
self.write_report(
|
||||
report_path,
|
||||
[
|
||||
{
|
||||
"status": "ready",
|
||||
"current_path": str(ready_book),
|
||||
"proposed_abs_path": "Ready Author/Ready Book",
|
||||
},
|
||||
{
|
||||
"status": "review",
|
||||
"current_path": str(review_book),
|
||||
"proposed_abs_path": "Review Author/Review Book",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
exit_code = apply_report.main(
|
||||
[
|
||||
"--report",
|
||||
str(report_path),
|
||||
"--destination-root",
|
||||
str(destination_root),
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(exit_code, 0)
|
||||
self.assertTrue((destination_root / "Ready Author" / "Ready Book").exists())
|
||||
self.assertFalse((destination_root / "Review Author" / "Review Book").exists())
|
||||
self.assertTrue(review_book.exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user