108 lines
4.0 KiB
Python
108 lines
4.0 KiB
Python
from __future__ import annotations
|
|
|
|
import inspect
|
|
from pathlib import Path
|
|
|
|
from dashboard.page_views import settlement_drafts as view
|
|
from jarca_ledger_mcp import service
|
|
from jarca_ledger_mcp.adapters.mcp import server, tool_contracts
|
|
|
|
|
|
HISTORY_TOOLS = (
|
|
"list_monthly_settlement_history",
|
|
"get_monthly_settlement_history_record",
|
|
)
|
|
|
|
|
|
class _FakeStreamlit:
|
|
def __init__(self) -> None:
|
|
self.session_state: dict[str, object] = {}
|
|
self.selectbox_calls: list[tuple[str, list[str], dict]] = []
|
|
self.captions: list[str] = []
|
|
self.json_values: list[object] = []
|
|
self.dataframes: list[object] = []
|
|
self.info_values: list[str] = []
|
|
self.error_values: list[str] = []
|
|
|
|
def selectbox(self, label, options, **kwargs):
|
|
values = list(options)
|
|
self.selectbox_calls.append((label, values, kwargs))
|
|
return values[-1]
|
|
|
|
def caption(self, value):
|
|
self.captions.append(str(value))
|
|
|
|
def json(self, value):
|
|
self.json_values.append(value)
|
|
|
|
def dataframe(self, value, **kwargs):
|
|
self.dataframes.append(value)
|
|
|
|
def info(self, value):
|
|
self.info_values.append(str(value))
|
|
|
|
def error(self, value):
|
|
self.error_values.append(str(value))
|
|
|
|
|
|
|
|
def test_history_tools_are_registered_with_public_no_db_path_schemas():
|
|
tools = server.mcp._tool_manager._tools
|
|
|
|
for name in HISTORY_TOOLS:
|
|
assert name in tool_contracts.TOOL_CONTRACTS
|
|
assert name in tool_contracts.__all__
|
|
assert name in tools
|
|
schema = tools[name].parameters if hasattr(tools[name], "parameters") else tools[name].inputSchema
|
|
properties = schema.get("properties", {})
|
|
assert "db_path" not in properties
|
|
assert set(properties) == set(inspect.signature(getattr(service, name)).parameters) - {"db_path"}
|
|
|
|
|
|
|
|
def test_history_control_opens_selected_run_and_render_fetches_exact_record(monkeypatch):
|
|
fake = _FakeStreamlit()
|
|
monkeypatch.setattr(view, "st", fake)
|
|
calls: list[tuple] = []
|
|
|
|
def list_history(month="", *, db_path=None):
|
|
calls.append(("list", month, db_path))
|
|
return {
|
|
"success": True,
|
|
"history": [
|
|
{"run_id": "run-old", "settlement_month": month, "version": 2, "closed_at": "2026-10-01", "close_status": "complete_exact"},
|
|
{"run_id": "run-new", "settlement_month": month, "version": 3, "closed_at": "2026-10-02", "close_status": "conditional", "correction_target": "run-old", "reason": "fixed"},
|
|
],
|
|
}
|
|
|
|
def get_record(run_id, *, db_path=None):
|
|
calls.append(("get", run_id, db_path))
|
|
return {"success": True, "history": {"run_id": run_id, "net_cashflow": 55, "net_worth": 995}}
|
|
|
|
monkeypatch.setattr(view.gateway, "list_monthly_settlement_history", list_history)
|
|
monkeypatch.setattr(view.gateway, "get_monthly_settlement_history_record", get_record)
|
|
|
|
view._open_settlement_history("draft-1", "run-old")
|
|
assert fake.session_state["settlement_history_open_draft"] == "draft-1"
|
|
assert fake.session_state["settlement_history_run_draft-1"] == "run-old"
|
|
|
|
view._render_settlement_history("fixture.sqlite3", "2026-09", "draft-1")
|
|
|
|
assert calls == [("list", "2026-09", "fixture.sqlite3"), ("get", "run-new", "fixture.sqlite3")]
|
|
assert fake.selectbox_calls[0][0] == "불변 마감 run 선택"
|
|
assert fake.selectbox_calls[0][1] == ["run-old", "run-new"]
|
|
assert fake.json_values == [{"run_id": "run-new", "net_cashflow": 55, "net_worth": 995}]
|
|
|
|
|
|
def test_public_history_contract_and_immutable_run_model_are_documented():
|
|
root = Path(__file__).parents[1]
|
|
interface = (root / "docs/interface-contract.md").read_text(encoding="utf-8")
|
|
data_model = (root / "docs/data-model.md").read_text(encoding="utf-8")
|
|
|
|
for operation in HISTORY_TOOLS:
|
|
assert operation in interface
|
|
assert "MCP signatures omit internal `db_path`" in interface
|
|
assert "마감내역보기" in interface
|
|
assert "append-only immutable settlement history" in data_model
|
|
assert "correction_of_run_id" in data_model
|