Kopiert die korrigierte(n) Abschrift(en) eines Arbeitsordners mit Quellenkopf (Titel, Kanal, Datum, URL, Abschlussdatum) nach fertig/, listet Einträge des Video-Glossars, die in keinem gemeinsamen Glossar stehen, und löscht den Ordner nach Rückfrage (--ja ohne). Schutz: Abbruch bei offenen Prüfmarken (--trotzdem) und ungeklärten *.neu.korrigiert.txt; fertig/ wird nie überschrieben; nicht gelöscht werden Ordner mit fremden Dateien, das Aufrufverzeichnis und alles in testdaten/, glossare/, tests/, fertig/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
162 lines
6.5 KiB
Python
162 lines
6.5 KiB
Python
"""Tests for abschliessen.py (finish a video: result to fertig/, delete working folder)."""
|
|
import json
|
|
import sys
|
|
from datetime import date
|
|
|
|
import pytest
|
|
|
|
import abschliessen as ab
|
|
|
|
TEXT = "Der Kreml ist in Moskau.\n\nDas ist bekannt.\n"
|
|
SOURCE = {
|
|
"titel": "Eine Rede", "kanal": "Kanal", "datum": "20260328",
|
|
"url": "https://www.youtube.com/watch?v=abc123", "id": "abc123",
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def work(tmp_path, monkeypatch):
|
|
"""abschriften/rede/ with everything a run leaves behind; cwd is tmp_path."""
|
|
monkeypatch.chdir(tmp_path)
|
|
folder = tmp_path / "abschriften" / "rede"
|
|
parts = folder / "rede.korrigiert.parts"
|
|
parts.mkdir(parents=True)
|
|
(parts / "part001-abc.txt").write_text("x", encoding="utf-8")
|
|
(folder / "rede.txt").write_text("der kremmel ist in moskau\n", encoding="utf-8")
|
|
(folder / "rede.korrigiert.txt").write_text(TEXT, encoding="utf-8")
|
|
(folder / "rede.aenderungen.html").write_text("<p>", encoding="utf-8")
|
|
(folder / "rede.quelle.json").write_text(json.dumps(SOURCE), encoding="utf-8")
|
|
return folder
|
|
|
|
|
|
def run_main(monkeypatch, *args, answer=None):
|
|
monkeypatch.setattr(sys, "argv", ["abschliessen.py", *map(str, args)])
|
|
if answer is not None:
|
|
monkeypatch.setattr("builtins.input", lambda question: answer)
|
|
ab.main()
|
|
|
|
|
|
def test_finish_writes_header_and_deletes(work, tmp_path, monkeypatch, capsys):
|
|
run_main(monkeypatch, work, "--ja")
|
|
|
|
finished = (tmp_path / "fertig" / "rede.txt").read_text(encoding="utf-8")
|
|
assert finished == (
|
|
"Titel: Eine Rede\nKanal: Kanal\nDatum: 2026-03-28\n"
|
|
"Quelle: https://www.youtube.com/watch?v=abc123\n"
|
|
f"Abgeschlossen: {date.today().isoformat()}\n\n" + TEXT
|
|
)
|
|
assert not work.exists()
|
|
out = capsys.readouterr().out
|
|
assert "rede.korrigiert.parts/" in out and f"Gelöscht: {work}" in out
|
|
|
|
|
|
def test_answer_no_keeps_folder_and_rerun_deletes(work, tmp_path, monkeypatch, capsys):
|
|
run_main(monkeypatch, work, answer="n")
|
|
assert work.is_dir()
|
|
assert (tmp_path / "fertig" / "rede.txt").is_file()
|
|
assert "Nicht gelöscht." in capsys.readouterr().out
|
|
|
|
# Later: the result is already in fertig/, only the deletion is left
|
|
run_main(monkeypatch, work, answer="j")
|
|
assert not work.exists()
|
|
assert "Bereits fertig" in capsys.readouterr().out
|
|
|
|
|
|
def test_open_review_marks_stop(work, tmp_path, monkeypatch, capsys):
|
|
(work / "rede.korrigiert.txt").write_text(
|
|
"Der Kreml [prüfen: Kremmel] ist in Moskau.\n", encoding="utf-8"
|
|
)
|
|
with pytest.raises(SystemExit, match="offene Prüfmarken"):
|
|
run_main(monkeypatch, work, "--ja")
|
|
assert "Zeile 1: Der Kreml [prüfen: Kremmel]" in capsys.readouterr().out
|
|
assert not (tmp_path / "fertig").exists() and work.is_dir()
|
|
|
|
run_main(monkeypatch, work, "--ja", "--trotzdem")
|
|
assert (tmp_path / "fertig" / "rede.txt").is_file()
|
|
|
|
|
|
def test_conflict_stops(work, monkeypatch):
|
|
(work / "rede.neu.korrigiert.txt").write_text(TEXT, encoding="utf-8")
|
|
with pytest.raises(SystemExit, match="Ungeklärter Konflikt: rede.neu.korrigiert.txt"):
|
|
run_main(monkeypatch, work, "--ja")
|
|
assert work.is_dir()
|
|
|
|
|
|
def test_no_result_stops(work, monkeypatch):
|
|
(work / "rede.korrigiert.txt").unlink()
|
|
with pytest.raises(SystemExit, match="Keine korrigierte Abschrift"):
|
|
run_main(monkeypatch, work, "--ja")
|
|
|
|
|
|
def test_existing_different_target_is_never_overwritten(work, tmp_path, monkeypatch):
|
|
(tmp_path / "fertig").mkdir()
|
|
(tmp_path / "fertig" / "rede.txt").write_text("Anderer Text\n", encoding="utf-8")
|
|
with pytest.raises(SystemExit, match="mit anderem Text"):
|
|
run_main(monkeypatch, work, "--ja")
|
|
assert (tmp_path / "fertig" / "rede.txt").read_text(encoding="utf-8") == "Anderer Text\n"
|
|
assert work.is_dir()
|
|
|
|
|
|
def test_without_source_header_names_the_file(work, tmp_path, monkeypatch, capsys):
|
|
(work / "rede.quelle.json").unlink()
|
|
run_main(monkeypatch, work, "--ja")
|
|
finished = (tmp_path / "fertig" / "rede.txt").read_text(encoding="utf-8")
|
|
assert finished.startswith("Datei: rede.korrigiert.txt\nAbgeschlossen: ")
|
|
assert "keine Quellenangabe" in capsys.readouterr().out
|
|
|
|
|
|
def test_every_excerpt_is_finished(work, tmp_path, monkeypatch):
|
|
(work / "rede_ab_00-05-00.korrigiert.txt").write_text("[00:05:00 - 00:06:00]\n\nB.\n")
|
|
run_main(monkeypatch, work, "--ja")
|
|
assert (tmp_path / "fertig" / "rede.txt").is_file()
|
|
assert (tmp_path / "fertig" / "rede_ab_00-05-00.txt").read_text().endswith(
|
|
"[00:05:00 - 00:06:00]\n\nB.\n"
|
|
)
|
|
|
|
|
|
def test_foreign_file_prevents_deletion(work, tmp_path, monkeypatch, capsys):
|
|
(work / "notizen.docx").write_bytes(b"x")
|
|
run_main(monkeypatch, work, "--ja")
|
|
assert work.is_dir()
|
|
assert (tmp_path / "fertig" / "rede.txt").is_file()
|
|
assert "Fremde Datei: notizen.docx" in capsys.readouterr().out
|
|
|
|
|
|
@pytest.mark.parametrize("protected", ["testdaten", "glossare", "tests", "fertig"])
|
|
def test_protected_folders_are_never_deleted(tmp_path, monkeypatch, capsys, protected):
|
|
monkeypatch.chdir(tmp_path)
|
|
folder = tmp_path / protected / "rede"
|
|
folder.mkdir(parents=True)
|
|
(folder / "rede.korrigiert.txt").write_text(TEXT, encoding="utf-8")
|
|
run_main(monkeypatch, folder, "--ja", "--ziel", tmp_path / "ziel")
|
|
assert folder.is_dir()
|
|
assert f"„{protected}“, das nie gelöscht wird" in capsys.readouterr().out
|
|
|
|
|
|
def test_current_directory_is_never_deleted(tmp_path, monkeypatch, capsys):
|
|
monkeypatch.chdir(tmp_path)
|
|
(tmp_path / "rede.korrigiert.txt").write_text(TEXT, encoding="utf-8")
|
|
run_main(monkeypatch, ".", "--ja")
|
|
assert (tmp_path / "rede.korrigiert.txt").is_file()
|
|
assert "Aufrufverzeichnis" in capsys.readouterr().out
|
|
|
|
|
|
def test_video_glossary_entries_not_shared_are_listed(work, tmp_path, monkeypatch, capsys):
|
|
(work / "rede.glossar.txt").write_text(
|
|
"Kremmel => Kreml\nNetano => Netanjahu\nEgon Bahr\nMoskau\n", encoding="utf-8"
|
|
)
|
|
(tmp_path / "glossare").mkdir()
|
|
(tmp_path / "glossare" / "gemeinsam.glossar.txt").write_text(
|
|
"Kremmel => Kreml\nMoskau\n", encoding="utf-8"
|
|
)
|
|
run_main(monkeypatch, work, "--ja")
|
|
out = capsys.readouterr().out
|
|
listed = out.split("gemeinsames übernehmen:")[1].split("\n\n")[0]
|
|
assert "Netano => Netanjahu" in listed and "Egon Bahr" in listed
|
|
assert "Kremmel" not in listed and "Moskau" not in listed
|
|
|
|
|
|
def test_missing_folder(tmp_path, monkeypatch, capsys):
|
|
with pytest.raises(SystemExit):
|
|
run_main(monkeypatch, tmp_path / "fehlt")
|
|
assert "Ordner nicht gefunden" in capsys.readouterr().err
|