File size: 2,108 Bytes
b4f2238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
"""Tests for unified placeholder fallback slash rules."""

from __future__ import annotations

from apps.documents.services.generation.prompts import PromptSpec
from apps.documents.services.placeholders.fallback import (
    PLACEHOLDER_FALLBACK_VALUE,
    build_docx_render_context,
    resolve_render_variable,
)
from apps.litigation_ai.services.placeholder_render_service import PlaceholderRenderService


class _DocStub:
    def get_undeclared_template_variables(self, context: dict[str, object] | None = None) -> set[str]:
        if context and "known" in context:
            return {"missing_key"}
        return set()


def test_build_docx_render_context_fills_undeclared_with_slash() -> None:
    context = build_docx_render_context(doc=_DocStub(), context={"known": "ok"})

    assert context["known"] == "ok"
    assert context["missing_key"] == PLACEHOLDER_FALLBACK_VALUE


def test_resolve_render_variable_returns_slash_for_none_and_missing() -> None:
    hit, value = resolve_render_variable({"a": None}, "a")
    assert hit is False
    assert value == PLACEHOLDER_FALLBACK_VALUE

    hit_missing, value_missing = resolve_render_variable({}, "missing")
    assert hit_missing is False
    assert value_missing == PLACEHOLDER_FALLBACK_VALUE


def test_placeholder_render_service_renders_slash_for_missing_and_none() -> None:
    rendered, stats = PlaceholderRenderService().render(
        "姓名:{name};地址:{address}",
        {"name": None},
        syntax="single",
        keep_unmatched=True,
    )

    assert rendered == f"姓名:{PLACEHOLDER_FALLBACK_VALUE};地址:{PLACEHOLDER_FALLBACK_VALUE}"
    assert stats.placeholders_found == ["name", "address"]
    assert stats.placeholders_hit == []
    assert stats.placeholders_missed == ["name", "address"]


def test_prompt_spec_render_user_message_uses_slash_for_none_and_missing() -> None:
    prompt = PromptSpec(system_prompt="s", user_template="A:{a};B:{b}", format_instructions="")

    rendered = prompt.render_user_message({"a": None})

    assert rendered == f"A:{PLACEHOLDER_FALLBACK_VALUE};B:{PLACEHOLDER_FALLBACK_VALUE}"