Files
jarca-ledger-mcp/tests/test_settlement_draft_panel_feedback.py
T

59 lines
3.0 KiB
Python

"""Operator feedback distinguishes read failures and partially committed saves."""
import pytest
from streamlit.testing.v1 import AppTest
from jarca_ledger_mcp import service as s
from jarca_ledger_mcp.adapters.streamlit import settlement_gateway
from jarca_ledger_mcp.db import init_db
def panel(monkeypatch, path):
monkeypatch.setenv('JARCA_LEDGER_DB_PATH', str(path))
app = AppTest.from_string('from dashboard.page_views.settlement_drafts import render_settlement_drafts\nrender_settlement_drafts()\n').run(timeout=20)
assert not app.exception
return app
def control(elements, label):
return next(element for element in elements if element.label == label)
def test_panel_shows_safe_error_when_draft_listing_fails(tmp_path, monkeypatch):
path = tmp_path / 'missing.sqlite3'
monkeypatch.setattr(settlement_gateway, 'list_settlement_drafts', lambda *args, **kwargs: {
'success': False, 'error_code': 'storage_error', 'message': 'SYNTHETIC_PRIVATE_DIAGNOSTIC',
})
app = panel(monkeypatch, path)
assert app.error and 'storage_error' in ' '.join(element.value for element in app.error)
assert not any('초안이 없습니다' in element.value for element in app.info)
visible = ' '.join(element.value for elements in (app.error, app.info, app.caption) for element in elements)
assert 'SYNTHETIC_PRIVATE_DIAGNOSTIC' not in visible
assert not path.exists()
def test_panel_reports_partial_save_when_item_update_fails(tmp_path, monkeypatch):
path = str(tmp_path / 'partial.sqlite3')
init_db(path)
account = s.create_ledger_account('Synthetic cash', db_path=path)['account']['id']
assert s.register_account_valuation(account, '2026-09-30', 10, verification_status='verified',
idempotency_key='synthetic-value', db_path=path)['success']
app = panel(monkeypatch, path)
control(app.button, '초안 생성 / 정정 초안').click().run(timeout=20)
control(app.button, '검토 / 새로고침 대상').click().run(timeout=20)
draft = s.list_settlement_drafts('2026-09', db_path=path)['drafts'][0]
review_key = f"review_result_{draft['id']}"
assert app.session_state[review_key]['success']
control(app.text_input, '초안 메모 저장').set_value('Synthetic persisted memo')
control(app.text_input, '대상 ID').set_value('synthetic-nonexistent-target')
control(app.button, '저장 / 지정 / 포함·제외').click().run(timeout=20)
assert not app.exception
current = s.get_settlement_draft(draft['id'], db_path=path)
assert current['draft']['memo'] == 'Synthetic persisted memo'
assert current['draft']['version'] == draft['version'] + 1
assert len(current['items']) == 1 and current['items'][0]['source_id'] == account
assert app.error
assert any('메모는 저장되었지만 항목 변경은 실패했습니다' in element.value for element in app.warning)
with pytest.raises(KeyError):
app.session_state[review_key]
assert not any(element.label in {'검토 결과 승인', '최종 마감'} for element in app.button)