"""Prompt-scaffolding tests (#960) — render, версионирование, отсутствие шаблона.""" from __future__ import annotations import pytest from app.services.llm.prompts import ( PromptNotFoundError, PromptTemplate, get_template, render, ) def test_get_known_template() -> None: tpl = get_template("system_base") assert tpl.name == "system_base" assert tpl.version == 1 assert tpl.key == "system_base@v1" def test_get_unknown_template_raises() -> None: with pytest.raises(PromptNotFoundError): get_template("does_not_exist") def test_render_known_template() -> None: out = render("system_base") assert "ассистент" in out def test_chat_system_v3_has_unit_mix_formatting_rule() -> None: """chat_system@v3: чистый рендер квартирографии, без «N-тип» склейки (сохранено с v2).""" tpl = get_template("chat_system") assert tpl.version == 3 assert tpl.key == "chat_system@v3" out = render("chat_system") assert "квартирограф" in out.lower() # правило про перечисление сегментов assert "«2-1-к»" in out # явный анти-пример (склейка номера с типом) # ключевые жёсткие правила сохранены assert "НИКОГДА не выдумывай" in out assert "ВЕРБАТИМ" in out def test_chat_system_v3_mentions_parcel_info_tool() -> None: """chat_system@v3: паспорт участка/ПЗЗ теперь в области ответа через get_parcel_info.""" out = render("chat_system") assert "get_parcel_info" in out # tool паспорта участка/градрегламента assert "зон" in out.lower() # тер.зона ПЗЗ упомянута как отвечаемая def test_render_with_required_vars() -> None: """render подставляет переменные через str.format и валидирует required_vars.""" tpl = PromptTemplate( name="probe", version=1, template="zone={zone}", required_vars=("zone",), ) # Прямой рендер шаблона (не из реестра) — проверяем format-механику. assert tpl.template.format(zone="Ц-1") == "zone=Ц-1" def test_render_missing_required_var_raises() -> None: """Если шаблон требует переменную, а её нет → KeyError (для зарегистрированного).""" with pytest.raises(PromptNotFoundError): render("missing_template", zone="Ц-1")