"""Tests for flashcard-diff-ids.py: :ID: extraction + SRS-state diff CLI. Plain python3 script (no third-party deps), so card_id_map imports directly; the disappeared/appeared reporting is exercised through the CLI. """ from __future__ import annotations import importlib.util import subprocess import sys from pathlib import Path import pytest SCRIPT = Path(__file__).resolve().parents[1] / "flashcard-diff-ids.py" @pytest.fixture(scope="module") def diff_ids(): spec = importlib.util.spec_from_file_location("flashcard_diff_ids", SCRIPT) assert spec and spec.loader module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module DECK_A = """* Section ** What is DeepSat? :drill: :PROPERTIES: :ID: id-1 :END: Body. ** Who founded it? :drill: :PROPERTIES: :ID: id-2 :END: Body. """ # id-2 dropped, id-3 added relative to DECK_A DECK_B = """* Section ** What is DeepSat? :drill: :PROPERTIES: :ID: id-1 :END: Body. ** When was it founded? :drill: :PROPERTIES: :ID: id-3 :END: Body. """ def test_card_id_map_extracts_id_to_heading(diff_ids, tmp_path): f = tmp_path / "a.org" f.write_text(DECK_A) m = diff_ids.card_id_map(f) assert set(m) == {"id-1", "id-2"} assert m["id-1"] == "What is DeepSat?" def _run(before, after): return subprocess.run( [sys.executable, str(SCRIPT), str(before), str(after)], capture_output=True, text=True, ) def test_cli_identical_decks_exit_zero(tmp_path): a = tmp_path / "a.org" a.write_text(DECK_A) b = tmp_path / "b.org" b.write_text(DECK_A) r = _run(a, b) assert r.returncode == 0 assert "preserved" in r.stdout.lower() def test_cli_dropped_id_warns_and_exits_one(tmp_path): a = tmp_path / "a.org" a.write_text(DECK_A) b = tmp_path / "b.org" b.write_text(DECK_B) r = _run(a, b) assert r.returncode == 1 assert "disappeared" in r.stdout.lower() assert "id-2" in r.stdout DECK_ONE = """* Section ** What is DeepSat? :drill: :PROPERTIES: :ID: id-1 :END: Body. """ def test_cli_appeared_only_notes_new_ids_and_exits_one(tmp_path): # before has id-1; after adds id-2 and drops nothing. before = tmp_path / "before.org" before.write_text(DECK_ONE) after = tmp_path / "after.org" after.write_text(DECK_A) r = _run(before, after) assert r.returncode == 1 assert "appeared" in r.stdout.lower() assert "id-2" in r.stdout