from pathlib import Path from click.testing import CliRunner from markitect_tool.cache import ( build_cache, cache_path_for, detect_changes, fingerprint_file, load_cache, save_cache, scan_markdown_files, ) from markitect_tool.cli import main def test_fingerprint_file_records_hash_and_parse_summary(tmp_path: Path): source = tmp_path / "doc.md" source.write_text("# Title\n\nBody.\n", encoding="utf-8") entry = fingerprint_file(source, root=tmp_path) assert entry.path == "doc.md" assert entry.content_hash.startswith("sha256:") assert entry.headings == 1 assert entry.sections == 1 assert entry.blocks == 2 def test_build_cache_and_detect_changes(tmp_path: Path): one = tmp_path / "one.md" two = tmp_path / "two.md" one.write_text("# One\n", encoding="utf-8") two.write_text("# Two\n", encoding="utf-8") manifest = build_cache([tmp_path], root=tmp_path) assert sorted(manifest.entries) == ["one.md", "two.md"] status = detect_changes(manifest, [tmp_path], root=tmp_path) assert not status.dirty assert status.unchanged == ["one.md", "two.md"] one.write_text("# One\n\nChanged.\n", encoding="utf-8") two.unlink() three = tmp_path / "three.md" three.write_text("# Three\n", encoding="utf-8") status = detect_changes(manifest, [tmp_path], root=tmp_path) assert status.dirty assert status.changed == ["one.md"] assert status.deleted == ["two.md"] assert status.new == ["three.md"] def test_save_and_load_cache_manifest(tmp_path: Path): source = tmp_path / "doc.md" source.write_text("# Doc\n", encoding="utf-8") manifest_path = cache_path_for(tmp_path) manifest = build_cache([source], root=tmp_path) save_cache(manifest, manifest_path) loaded = load_cache(manifest_path) assert loaded.entries["doc.md"].content_hash == manifest.entries["doc.md"].content_hash def test_scan_markdown_files_skips_non_markdown(tmp_path: Path): (tmp_path / "doc.md").write_text("# Doc\n", encoding="utf-8") (tmp_path / "notes.txt").write_text("Nope\n", encoding="utf-8") nested = tmp_path / "nested" nested.mkdir() (nested / "other.markdown").write_text("# Other\n", encoding="utf-8") assert [path.name for path in scan_markdown_files([tmp_path])] == ["doc.md", "other.markdown"] assert [path.name for path in scan_markdown_files([tmp_path], recursive=False)] == ["doc.md"] def test_mkt_cache_build_and_status(tmp_path: Path): source = tmp_path / "doc.md" source.write_text("# Doc\n", encoding="utf-8") runner = CliRunner() build = runner.invoke(main, ["cache", "build", str(tmp_path), "--root", str(tmp_path)]) assert build.exit_code == 0 assert "written: True" in build.output clean = runner.invoke(main, ["cache", "status", str(tmp_path), "--root", str(tmp_path)]) assert clean.exit_code == 0 assert "clean" in clean.output source.write_text("# Doc\n\nChanged.\n", encoding="utf-8") dirty = runner.invoke(main, ["cache", "status", str(tmp_path), "--root", str(tmp_path)]) assert dirty.exit_code == 1 assert "dirty" in dirty.output assert "changed: 1" in dirty.output def test_mkt_cache_fingerprint_outputs_json(tmp_path: Path): source = tmp_path / "doc.md" source.write_text("# Doc\n", encoding="utf-8") result = CliRunner().invoke( main, ["cache", "fingerprint", str(source), "--root", str(tmp_path)], ) assert result.exit_code == 0 assert '"path": "doc.md"' in result.output assert '"content_hash": "sha256:' in result.output