"""Помощники golden-снимков: нормализация volatile-полей, путь снимка, формат записи (design D-10).""" import json from pathlib import Path from golden_helpers import ( SNAPSHOT_DIR, STATEMENT_SNAPSHOT_DIR, golden_path, normalize_result, snapshot_text, unified_diff, ) def _result() -> dict: return { "schema_version": "1.2", "job_id": "00000000-0000-0000-0000-000000000000", "file_id": "00000000-0000-0000-0000-000000000000", "service": {"name": "tabular-parser", "version": "0.1.0"}, "status": "done", "metrics": {"duration_ms": 12, "rows": 7, "warnings": ["б", "а"]}, "documents": [{"z": 1, "a": 2}], } def test_normalize_removes_exactly_the_volatile_fields() -> None: normalized = normalize_result(_result()) assert "job_id" not in normalized assert "file_id" not in normalized assert normalized["service"] == {"name": "tabular-parser"} assert normalized["metrics"] == {"rows": 7, "warnings": ["б", "а"]} assert normalized["documents"] == [{"z": 1, "a": 2}] def test_normalize_keeps_key_and_warning_order_and_does_not_mutate_input() -> None: source = _result() normalized = normalize_result(source) assert list(normalized) == ["schema_version", "service", "status", "metrics", "documents"] assert list(normalized["documents"][0]) == ["z", "a"] assert normalized["metrics"]["warnings"] == ["б", "а"] assert source == _result() def test_normalize_tolerates_missing_volatile_fields() -> None: assert normalize_result({"status": "error"}) == {"status": "error"} def test_golden_path_mirrors_osv_tree_without_extension(tmp_path: Path) -> None: root = tmp_path file = root / "osv" / "rb" / "2025-Q1" / "ОСВ сч 60.xlsx" assert golden_path(root, file) == root / "golden" / SNAPSHOT_DIR / "rb" / "2025-Q1" / "ОСВ сч 60.json" synthetic = root / "osv" / "synthetic" / "s01.xlsx" assert golden_path(root, synthetic) == root / "golden" / SNAPSHOT_DIR / "synthetic" / "s01.json" def test_golden_path_keeps_dots_inside_the_name(tmp_path: Path) -> None: file = tmp_path / "osv" / "a" / "сч 62 за 3 квартал 2024 г..xls" assert golden_path(tmp_path, file).name == "сч 62 за 3 квартал 2024 г..json" def test_snapshot_text_is_utf8_json_with_indent_and_trailing_newline() -> None: text = snapshot_text({"имя": "ОСВ", "n": ["1"]}) assert text.endswith("}\n") assert "ОСВ" in text assert json.loads(text) == {"имя": "ОСВ", "n": ["1"]} assert text.startswith('{\n "имя"') def test_unified_diff_names_files_and_shows_changed_lines() -> None: diff = unified_diff("a\nb\n", "a\nc\n", name="снимок.json") assert "--- снимок.json (в fixtures)" in diff assert "+++ снимок.json (разбор сейчас)" in diff assert "-b" in diff assert "+c" in diff assert unified_diff("a\n", "a\n", name="x") == "" def test_dkb_snapshot_path_mirrors_osv_dkb_under_its_own_subdirectory(tmp_path: Path) -> None: file = tmp_path / "osv-dkb" / "nm" / "2025-Q3" / "НМ ОСВ 63.xlsx" assert golden_path(tmp_path, file) == ( tmp_path / "golden" / SNAPSHOT_DIR / "osv-dkb" / "nm" / "2025-Q3" / "НМ ОСВ 63.json" ) assert ( golden_path(tmp_path, tmp_path / "osv" / "rb" / "a.xlsx") == tmp_path / "golden" / SNAPSHOT_DIR / "rb" / "a.json" ) def test_statement_snapshot_path_mirrors_statements_tree_under_its_own_directory(tmp_path: Path) -> None: file = tmp_path / "statements-xlsx" / "npz" / "2025-Q3" / "Отчётность (НПЗ).xlsx" synthetic = tmp_path / "statements-xlsx" / "synthetic" / "st01.xlsx" expected = tmp_path / "golden" / STATEMENT_SNAPSHOT_DIR / "npz" / "2025-Q3" / "Отчётность (НПЗ).json" assert golden_path(tmp_path, file) == expected assert golden_path(tmp_path, synthetic) == tmp_path / "golden" / STATEMENT_SNAPSHOT_DIR / "synthetic" / "st01.json"