Zum Inhalt

tests/test_transcript_history.py

"""Tests for transcript_history — snapshot, undo_last, cleanup."""

import json
import shutil
import time
from pathlib import Path

import pytest


@pytest.fixture
def sample_run(tmp_path, fixtures_dir):
    stem = "ep01"
    run_dir = tmp_path / stem
    run_dir.mkdir()
    src = fixtures_dir / "sample-transcript.whisperx.json"
    dst = run_dir / f"{stem}.whisperx.json"
    shutil.copy(src, dst)
    return {"dir": run_dir, "stem": stem, "json_path": dst}


def test_snapshot_creates_file(sample_run):
    from transcript_history import snapshot

    snap_path = snapshot(
        str(sample_run["json_path"]), action="edit_text", metric="1 segment edited"
    )
    assert Path(snap_path).exists()
    # File should be a sibling under snapshots/
    assert "snapshots" in str(snap_path)


def test_snapshot_content_matches_pre_mutation(sample_run):
    from transcript_history import snapshot

    pre_content = sample_run["json_path"].read_text(encoding="utf-8")
    snap_path = snapshot(str(sample_run["json_path"]), action="edit_text", metric="x")
    # Snapshot file must contain the PRE-mutation state (caller hasn't mutated yet)
    assert Path(snap_path).read_text(encoding="utf-8") == pre_content


def test_snapshot_appends_history_entry(sample_run):
    from transcript_history import snapshot

    snapshot(str(sample_run["json_path"]), action="edit_text", metric="1 segment edited")
    data = json.loads(sample_run["json_path"].read_text(encoding="utf-8"))
    history = data.get("_history", [])
    assert len(history) == 1
    assert history[0]["action"] == "edit_text"
    assert history[0]["metric"] == "1 segment edited"
    assert "ts" in history[0]
    assert "snapshot" in history[0]


def test_snapshot_history_path_is_relative(sample_run):
    from transcript_history import snapshot

    snapshot(str(sample_run["json_path"]), action="merge", metric="0+1")
    data = json.loads(sample_run["json_path"].read_text(encoding="utf-8"))
    # Stored path should be relative to output dir: "snapshots/<ts>.json"
    rel = data["_history"][-1]["snapshot"]
    assert rel.startswith("snapshots/")
    assert rel.endswith(".json")


def test_cleanup_snapshots_keeps_cap(sample_run, monkeypatch):
    from transcript_history import cleanup_snapshots, snapshot

    # Force a small cap for the test
    monkeypatch.setattr("transcript_history.SNAPSHOT_CAP", 3)
    for i in range(5):
        snapshot(str(sample_run["json_path"]), action="x", metric=f"{i}")
        time.sleep(0.01)  # ensure ts ordering
    cleanup_snapshots(str(sample_run["json_path"]))
    data = json.loads(sample_run["json_path"].read_text(encoding="utf-8"))
    # Only 3 history entries should remain
    assert len(data["_history"]) == 3
    # Corresponding snapshot files: also 3
    snap_dir = sample_run["dir"] / "snapshots"
    assert len(list(snap_dir.glob("*.json"))) == 3


def test_undo_last_restores_pre_mutation_state(sample_run):
    from transcript_history import snapshot, undo_last

    snapshot(str(sample_run["json_path"]), action="edit_text", metric="1 changed")
    # Simulate a mutation: alter segment 0's text
    data = json.loads(sample_run["json_path"].read_text(encoding="utf-8"))
    data["segments"][0]["text"] = "CHANGED."
    sample_run["json_path"].write_text(json.dumps(data, indent=2), encoding="utf-8")

    entry = undo_last(str(sample_run["json_path"]))
    assert entry is not None
    assert entry["action"] == "edit_text"
    # Content should match pre-snapshot state
    restored = json.loads(sample_run["json_path"].read_text(encoding="utf-8"))
    assert restored["segments"][0]["text"] != "CHANGED."


def test_undo_last_deletes_snapshot_file(sample_run):
    from transcript_history import snapshot, undo_last

    snap_path = snapshot(str(sample_run["json_path"]), action="x", metric="y")
    assert Path(snap_path).exists()
    undo_last(str(sample_run["json_path"]))
    assert not Path(snap_path).exists()


def test_undo_last_returns_none_when_empty(sample_run):
    from transcript_history import undo_last

    entry = undo_last(str(sample_run["json_path"]))
    assert entry is None


def test_list_history_returns_entries_newest_last(sample_run):
    from transcript_history import list_history, snapshot

    snapshot(str(sample_run["json_path"]), action="a", metric="1")
    time.sleep(0.01)
    snapshot(str(sample_run["json_path"]), action="b", metric="2")
    entries = list_history(str(sample_run["json_path"]))
    assert len(entries) == 2
    assert entries[0]["action"] == "a"
    assert entries[1]["action"] == "b"