86 lines
3.2 KiB
Python
86 lines
3.2 KiB
Python
"""Tests for the driver's orchestration logic (external tools are mocked)."""
|
|
import json
|
|
|
|
from woodshop import driver
|
|
from woodshop.cli import normalize_anchor
|
|
|
|
|
|
def test_anchor_aliases():
|
|
assert normalize_anchor("end") == "end_b"
|
|
assert normalize_anchor("the end") == "end_b" # falls through to default end_b
|
|
assert normalize_anchor("start") == "end_a"
|
|
assert normalize_anchor("NEAR") == "end_a"
|
|
assert normalize_anchor("") == "end_b"
|
|
|
|
|
|
def test_dispatch_resolves_dollar_symbols(monkeypatch):
|
|
"""$1/$2 in a multi-op turn resolve to the ids of boards placed this turn."""
|
|
seen = []
|
|
|
|
def fake_run(cmd, stdin=""):
|
|
if cmd[0] != "pa-execute-tool":
|
|
return ""
|
|
name, args = cmd[2], json.loads(cmd[4])
|
|
seen.append((name, args))
|
|
if name == "wood-place":
|
|
n = sum(1 for c in seen if c[0] == "wood-place")
|
|
return json.dumps({"success": True, "output": f"Placed p{n}: a board.", "error": ""})
|
|
return json.dumps({"success": True, "output": f"did {name}", "error": ""})
|
|
|
|
monkeypatch.setattr(driver, "_run", fake_run)
|
|
calls = [
|
|
{"tool": "wood-place", "args": {"stock": "2x4", "length": "2 ft"}},
|
|
{"tool": "wood-place", "args": {"stock": "2x4", "length": "2 ft"}},
|
|
{"tool": "wood-join", "args": {"part_b": "$2", "to": "$1", "angle": "90"}},
|
|
]
|
|
driver.dispatch(calls, verbose=False)
|
|
join_args = next(a for n, a in seen if n == "wood-join")
|
|
assert join_args["part_b"] == "p2"
|
|
assert join_args["to"] == "p1"
|
|
|
|
|
|
def test_say_pseudo_tool_does_not_dispatch(monkeypatch):
|
|
calls_made = []
|
|
monkeypatch.setattr(driver, "_run", lambda cmd, stdin="": calls_made.append(cmd) or "")
|
|
msgs = driver.dispatch([{"tool": "say", "args": {"text": "which end?"}}], verbose=False)
|
|
assert msgs == ["which end?"]
|
|
assert calls_made == [] # nothing executed
|
|
|
|
|
|
def test_interpret_tolerates_fenced_json(monkeypatch):
|
|
monkeypatch.setattr(
|
|
driver, "_run",
|
|
lambda cmd, stdin="": '```json\n[{"tool": "wood-undo", "args": {}}]\n```'
|
|
if cmd[:2] != ["pa-load-tools", "--tools"] else "[]",
|
|
)
|
|
calls = driver.interpret("undo that", schemas="[]")
|
|
assert calls == [{"tool": "wood-undo", "args": {}}]
|
|
|
|
|
|
def test_summarize_rolls_up_many_ops():
|
|
calls = ([{"tool": "wood-place", "args": {}}] * 8
|
|
+ [{"tool": "wood-join", "args": {}}] * 2
|
|
+ [{"tool": "wood-stand", "args": {}}] * 4)
|
|
summary = driver.summarize(calls, [""] * len(calls))
|
|
assert "placed 8" in summary
|
|
assert "joined 2" in summary
|
|
assert "stood up 4" in summary
|
|
assert len(summary) < 80 # short enough to speak
|
|
|
|
|
|
def test_summarize_speaks_queries_verbatim():
|
|
calls = [{"tool": "wood-cutlist", "args": {}}]
|
|
messages = ["CUT LIST\n 2 x 2x4 ..."]
|
|
assert driver.summarize(calls, messages).startswith("CUT LIST")
|
|
|
|
|
|
def test_summarize_speaks_clarification():
|
|
calls = [{"tool": "say", "args": {"text": "which end?"}}]
|
|
assert driver.summarize(calls, ["which end?"]) == "which end?"
|
|
|
|
|
|
def test_interpret_handles_garbage(monkeypatch):
|
|
monkeypatch.setattr(driver, "_run", lambda cmd, stdin="": "I'm not sure what you mean")
|
|
calls = driver.interpret("blah", schemas="[]")
|
|
assert calls[0]["tool"] == "say"
|