159 lines
4.4 KiB
Python
159 lines
4.4 KiB
Python
import json
|
|
from unittest.mock import patch
|
|
|
|
from scripts.console_chat import format_result, main, run_turn
|
|
|
|
|
|
class FakeMessage:
|
|
def __init__(self, content: str):
|
|
self.content = content
|
|
|
|
|
|
class FakeAgent:
|
|
def __init__(self, model_section=None):
|
|
self.model_section = model_section
|
|
self.calls = []
|
|
|
|
def run(self, query, **kwargs):
|
|
self.calls.append((query, kwargs))
|
|
return {
|
|
"messages": [FakeMessage("mock answer")],
|
|
"context": {
|
|
"table_name": "apbo_eta_ful",
|
|
"query_mode": "detail",
|
|
"final_sql": "SELECT service_order_id FROM dwd_ai.apbo_eta_ful",
|
|
"sql_plan": {"selected_table": "apbo_eta_ful", "query_mode": "detail"},
|
|
},
|
|
"final_step": "response_generated",
|
|
}
|
|
|
|
|
|
def test_format_result_includes_optional_blocks():
|
|
result = {
|
|
"messages": [FakeMessage("hello")],
|
|
"context": {
|
|
"final_sql": "SELECT 1",
|
|
"sql_plan": {"mode": "detail"},
|
|
"foo": "bar",
|
|
},
|
|
}
|
|
|
|
text = format_result(result, show_sql=True, show_context=True, show_plan=True)
|
|
assert "Answer:" in text
|
|
assert "SQL:" in text
|
|
assert "SQL Plan:" in text
|
|
assert "Context:" in text
|
|
|
|
|
|
def test_format_result_renders_table_from_wrapped_sr_api_result():
|
|
wrapped = json.dumps(
|
|
{
|
|
"status_code": 200,
|
|
"text": json.dumps(
|
|
{
|
|
"data": [
|
|
{"service_order_id": "4020438779", "ship_to_country": "VN"},
|
|
{"service_order_id": "4020438780", "ship_to_country": "PH"},
|
|
]
|
|
},
|
|
ensure_ascii=False,
|
|
),
|
|
},
|
|
ensure_ascii=False,
|
|
)
|
|
result = {
|
|
"messages": [FakeMessage('{"status_code": 200, "text": "..."}')],
|
|
"context": {
|
|
"sr_api_result": wrapped,
|
|
"final_sql": "SELECT service_order_id, ship_to_country FROM dwd_ai.apbo_eta_ful",
|
|
},
|
|
}
|
|
|
|
text = format_result(result)
|
|
assert "Query Result: 2 row(s)" in text
|
|
assert "status=200" in text
|
|
assert "service_order_id" in text
|
|
assert "ship_to_country" in text
|
|
assert "4020438779" in text
|
|
assert "VN" in text
|
|
|
|
|
|
def test_format_result_renders_columns_and_rows_payload():
|
|
result = {
|
|
"messages": [FakeMessage("ok")],
|
|
"context": {
|
|
"sr_api_result": {
|
|
"status_code": 200,
|
|
"text": {
|
|
"columns": ["region", "qty"],
|
|
"rows": [["ANZ", 12], ["CAP", 8]],
|
|
},
|
|
}
|
|
},
|
|
}
|
|
|
|
text = format_result(result)
|
|
assert "Query Result: 2 row(s)" in text
|
|
assert "status=200" in text
|
|
assert "region" in text
|
|
assert "qty" in text
|
|
assert "ANZ" in text
|
|
assert "12" in text
|
|
|
|
|
|
def test_format_result_falls_back_for_non_tabular_error():
|
|
result = {
|
|
"messages": [FakeMessage("请求失败: timeout")],
|
|
"context": {"sr_api_result": "请求失败: timeout"},
|
|
}
|
|
|
|
text = format_result(result)
|
|
assert "Answer:" in text
|
|
assert "请求失败: timeout" in text
|
|
assert "Query Result:" not in text
|
|
|
|
|
|
def test_main_one_shot_success(capsys):
|
|
with patch("scripts.console_chat.Config.validate_config", return_value=None), \
|
|
patch("scripts.console_chat.ConversationAgent", FakeAgent):
|
|
exit_code = main([
|
|
"--query",
|
|
"查询 SO 4020438779 的 eta 信息",
|
|
"--skip-sr-api",
|
|
"--show-sql",
|
|
])
|
|
|
|
captured = capsys.readouterr()
|
|
assert exit_code == 0
|
|
assert "mock answer" in captured.out
|
|
assert "SELECT service_order_id FROM dwd_ai.apbo_eta_ful" in captured.out
|
|
|
|
|
|
def test_run_turn_enables_debug_node_trace(capsys):
|
|
agent = FakeAgent()
|
|
|
|
run_turn(
|
|
agent,
|
|
"查询 SO 4020438779 的 eta 信息",
|
|
user="tester",
|
|
conversation_id="cid-1",
|
|
skip_sr_api=True,
|
|
show_sql=False,
|
|
show_context=False,
|
|
show_plan=False,
|
|
)
|
|
|
|
_, kwargs = agent.calls[-1]
|
|
assert kwargs["debug_node_trace"] is True
|
|
|
|
|
|
def test_main_config_error(capsys):
|
|
with patch("scripts.console_chat.Config.validate_config", side_effect=ValueError("bad config")):
|
|
exit_code = main(["--query", "hello"])
|
|
|
|
captured = capsys.readouterr()
|
|
assert exit_code == 1
|
|
assert "Configuration error" in captured.err
|
|
|
|
|