"""`sync_snapshots` и `scripts/golden_update.py`: запись, сравнение, diff, лишние снимки (на временном каталоге).""" import sys from pathlib import Path import pytest from golden_helpers import golden_path, render, snapshot_text, sync_snapshots from src.parser import get_parser from tests.synthetic.generate import generate_all FILES = 2 # s01 и s02 API_ROOT = Path(__file__).resolve().parents[2] @pytest.fixture(scope="module") def fixtures_root(tmp_path_factory: pytest.TempPathFactory) -> Path: root = tmp_path_factory.mktemp("fixtures") generate_all(root / "osv" / "synthetic") return root @pytest.fixture def root(fixtures_root: Path, tmp_path: Path) -> Path: """Копия дерева `osv/` на каждый тест: снимки не пересекаются между тестами.""" copy = tmp_path / "fx" (copy / "osv" / "synthetic").mkdir(parents=True) for source in sorted((fixtures_root / "osv" / "synthetic").glob("s0[12]*")): (copy / "osv" / "synthetic" / source.name).write_bytes(source.read_bytes()) return copy def files_of(root: Path) -> list[Path]: return sorted((root / "osv" / "synthetic").glob("s*")) def test_first_run_creates_snapshots_equal_to_render(root: Path) -> None: parser = get_parser() report = sync_snapshots(root, files_of(root), parser, write=True) assert len(report.created) == FILES assert report.changed == [] and report.orphans == [] and report.unchanged == 0 for file in files_of(root): assert golden_path(root, file).read_text(encoding="utf-8") == snapshot_text(render(parser, file)) assert (root / "golden" / "expected_osv_parse" / "synthetic" / "s01_variant2_header.json").is_file() def test_second_run_reports_nothing_and_check_does_not_write(root: Path) -> None: parser = get_parser() sync_snapshots(root, files_of(root), parser, write=True) again = sync_snapshots(root, files_of(root), parser, write=False) assert again.unchanged == FILES assert not again.differs assert again.diffs == [] def test_changed_snapshot_gives_diff_and_check_leaves_it_untouched(root: Path) -> None: parser = get_parser() sync_snapshots(root, files_of(root), parser, write=True) target = golden_path(root, files_of(root)[0]) original = target.read_text(encoding="utf-8") target.write_text(original.replace('"done"', '"needs_check"', 1), encoding="utf-8") checked = sync_snapshots(root, files_of(root), parser, write=False) assert checked.changed == [target.relative_to(root)] assert '- "status": "needs_check"' in checked.diffs[0] assert '+ "status": "done"' in checked.diffs[0] assert target.read_text(encoding="utf-8") != original written = sync_snapshots(root, files_of(root), parser, write=True) assert written.changed == [target.relative_to(root)] assert target.read_text(encoding="utf-8") == original def test_orphan_snapshot_is_reported_and_removed_on_write(root: Path) -> None: parser = get_parser() sync_snapshots(root, files_of(root), parser, write=True) orphan = root / "golden" / "expected_osv_parse" / "synthetic" / "s99_gone.json" orphan.write_text("{}\n", encoding="utf-8") checked = sync_snapshots(root, files_of(root), parser, write=False) assert checked.orphans == [orphan.relative_to(root)] assert orphan.exists() sync_snapshots(root, files_of(root), parser, write=True) assert not orphan.exists() def test_script_check_exit_codes( root: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] ) -> None: monkeypatch.setenv("ARM_KA_FIXTURES", str(root)) monkeypatch.syspath_prepend(str(API_ROOT / "scripts")) sys.modules.pop("golden_update", None) import golden_update # noqa: PLC0415 - модуль-скрипт assert golden_update.main(["--check"]) == 1 assert golden_update.main([]) == 0 assert golden_update.main(["--check"]) == 0 monkeypatch.setenv("ARM_KA_FIXTURES", str(root / "нет")) capsys.readouterr() assert golden_update.main([]) == golden_update.EXIT_NO_FIXTURES assert "каталог фикстур не найден" in capsys.readouterr().err