"""Очистка OCR-текста (§11.1 п. 1, 6; D-4 `text.py`): перенос функций старого ядра, поведение — как в источнике.""" import pytest from src.normalizer.ocr.text import ( clean_value, collapse_whitespace, digits_only, fix_lookalikes, is_code_header, is_value_header, normalize_header, ) LOOKALIKES = { "О": "0", "о": "0", "O": "0", "o": "0", "З": "3", "з": "3", "l": "1", "I": "1", "|": "1", "і": "1", "б": "6", "S": "5", "s": "5", "Ч": "4", } class TestFixLookalikes: @pytest.mark.parametrize( ("raw", "expected"), [ ("2ОО5", "2005"), # два прохода: О после 2, затем О после 0 ("3l.12.2О24", "31.12.2024"), ("Общество", "Общество"), # буквы без соседней цифры не трогаются ("2|0|2|4|", "2 0 2 4 "), # первая строка — только цифры и |: это разделитель клеток ("3l", "31"), # | не разделитель, если есть буквы ("", ""), ], ) def test_replaces_only_next_to_digits(self, raw: str, expected: str) -> None: assert fix_lookalikes(raw, LOOKALIKES) == expected def test_separator_rule_looks_at_first_line_only(self) -> None: assert fix_lookalikes("2|0|2|4|\nмусор", LOOKALIKES) == "2 0 2 4 \nмусор" def test_empty_table_keeps_text(self) -> None: assert fix_lookalikes("2ОО5", {}) == "2ОО5" def test_nbsp_replacement(self) -> None: # неразрывный пробел (U+00A0) → обычный пробел (U+0020) assert fix_lookalikes("31\xa012\xa02024", LOOKALIKES) == "31 12 2024" assert fix_lookalikes("31\xa012\xa02024", {}) == "31 12 2024" @pytest.mark.parametrize( ("raw", "expected"), [ ("13 070", "13 070"), ("(7744536}", "7744536"), ("изо :", "изо"), ("На 30 июня\n2025 г", "На 30 июня 2025 г"), ("", ""), ], ) def test_clean_value(raw: str, expected: str) -> None: assert clean_value(raw) == expected def test_digits_only() -> None: assert digits_only("3|1 21 2| о! О' 0 0; 3: 51") == "3121200351" assert digits_only("+") == "" def test_collapse_whitespace() -> None: assert collapse_whitespace(" На 31 декабря\n2024 г.\t") == "На 31 декабря 2024 г." class TestHeaders: def test_normalize_header(self) -> None: assert normalize_header("Наименование\nпоказателя:") == "наименование показателя" assert normalize_header(None) == "" def test_code_header(self) -> None: assert is_code_header(normalize_header("Код")) assert is_code_header(normalize_header("Код строки")) assert not is_code_header(normalize_header("Наименование")) @pytest.mark.parametrize( ("text", "expected"), [ ("на 30 июня 2025 г", True), ("за январь июнь 2025 г", True), ("2024", True), ("пояснения", False), ("", False), ], ) def test_value_header(self, text: str, expected: bool) -> None: assert is_value_header(text) is expected