import pytest from app.normalize import mark_pause_delimiters, normalize_common from app.segmentation import prepare_segments from app.ssml import PAUSE_DELIM as P, build_ssml, strip_sentinels DELIMS = "([{«“<)]}»>\"'`*_~" # 5.1/5.2: разделительные символы удаляются, в паузообразующих позициях # остаётся sentinel (НЕ запятая). Проверяем инварианты, а не литеральные запятые. @pytest.mark.parametrize("text, expected_pauses", [ ("скажи, что именно интересует (мир, техника, курсы валют), и я поищу.", 1), ('он сказал "сейчас проверю" и ушёл', 2), ('он сказал: "привет"', 0), ("мы сходим (надо)", 1), ('вот текст (важно)"', 1), ("он сказал **важно** слово", 2), ("слово *курсив* конец", 2), ("это _важно_ для дела", 2), ("список ~зачёркнут~ конец", 2), ("код `inline` конец", 2), ("тема «мир» конец", 2), ("сравнение x < 5 > 3 конец", 2), ("это {фигурные} и [квадратные] скобки", 4), ("слово 'вот это' конец", 2), ]) def test_delimiters_removed_pause_is_sentinel(text, expected_pauses): result = mark_pause_delimiters(text) for ch in DELIMS: assert ch not in result, f"символ {ch!r} не удалён из {result!r}" assert result.count(P) == expected_pauses @pytest.mark.parametrize("text, expected", [ ("мы сходим (надо)", f"мы сходим {P} надо"), ('вот текст (важно)"', f"вот текст {P} важно"), ("он сказал **важно** слово", f"он сказал {P} важно {P} слово"), ('он сказал: "привет"', "он сказал: привет"), ("погода в твоём городе?), и я поищу.", "погода в твоём городе?, и я поищу."), ]) def test_delimiter_pause_positions(text, expected): assert mark_pause_delimiters(text) == expected @pytest.mark.parametrize("text", [ "д'Катт и O'Neill пришли", ]) def test_apostrophes_inside_words_untouched(text): assert mark_pause_delimiters(text) == text @pytest.mark.parametrize("text", [ "текст (важно).", "текст (важно), конец", "текст [важно]!", "(важно)", ]) def test_no_delimiter_chars_left(text): result = mark_pause_delimiters(text) for ch in DELIMS: assert ch not in result @pytest.mark.parametrize("text", [ "текст (важно).", "текст (важно), конец", "текст (важно)! и ещё (так) конец", ]) def test_no_dangling_artifacts(text): # Sentinel не добавляет запятых; после удаления артефактов не остаётся. result = mark_pause_delimiters(text) assert ",," not in result assert not result.lstrip().startswith(",") assert ",." not in result def test_line_boundaries(): text = "(в начале строки) текст\nтекст (в конце строки)\n(снова) конец" result = mark_pause_delimiters(text) for ch in "()": assert ch not in result assert P in result clean = strip_sentinels(result) assert "снова" in clean and "конец" in clean and "текст" in clean def test_multiline_delimiters_processed_in_every_line(): text = "первая (строка) тут\nвторая «строка» тут" result = mark_pause_delimiters(text) assert "(" not in result and "«" not in result and "»" not in result clean = strip_sentinels(result) assert "строка" in clean and "тут" in clean assert P in result def test_english_text_same_rule(): segments = prepare_segments("The (parenthetical) works") ssml = build_ssml(segments) assert "