Skip to content

Commit b403168

Browse files
committed
test(mcp_server): cover single-pass prompt substitution
Direct unit coverage for _substitute (previously only exercised through the subprocess round-trip on the happy path). Pins the literal-value contract: an argument value containing {other} is not re-expanded, repeated and unknown placeholders behave, and empty args leave the template untouched.
1 parent 4aea663 commit b403168

1 file changed

Lines changed: 45 additions & 0 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""Unit coverage for mcp_server._substitute (prompts/get placeholder fill).
2+
3+
These exercise the pure substitution helper directly — no hub or subprocess —
4+
so they pin the single-pass contract: an argument value is literal text, never
5+
re-scanned for further placeholders.
6+
"""
7+
8+
from zhub.mcp_server import _substitute
9+
10+
11+
def test_basic_substitution():
12+
assert _substitute("Hi {name}", {"name": "Sam"}) == "Hi Sam"
13+
14+
15+
def test_non_string_value_coerced():
16+
assert _substitute("amount: {n}", {"n": 42}) == "amount: 42"
17+
18+
19+
def test_unknown_placeholder_left_intact():
20+
assert _substitute("Hi {name} {missing}", {"name": "Sam"}) == "Hi Sam {missing}"
21+
22+
23+
def test_empty_args_returns_template_unchanged():
24+
assert _substitute("No {vars} here", {}) == "No {vars} here"
25+
26+
27+
def test_repeated_placeholder_all_filled():
28+
assert _substitute("{x}-{x}", {"x": "A"}) == "A-A"
29+
30+
31+
def test_value_containing_other_placeholder_is_literal():
32+
# The argument order puts {text} before {style}; the naive replace-in-a-loop
33+
# substituted {text} first, then re-scanned its inserted value and expanded
34+
# the literal "{style}" inside it into the style argument. The value must
35+
# stay verbatim.
36+
out = _substitute(
37+
"Text: {text}. Style: {style}",
38+
{"text": "make it {style}", "style": "formal"},
39+
)
40+
assert out == "Text: make it {style}. Style: formal"
41+
42+
43+
def test_value_is_never_treated_as_template():
44+
# {a}'s value is itself "{b}"; it must not be expanded into b's value.
45+
assert _substitute("{a}", {"a": "{b}", "b": "Z"}) == "{b}"

0 commit comments

Comments
 (0)