Files
jarca-ledger-mcp/tests/test_monthly_settlement_public_history.py

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