Files
PTSRaiAgent/tests/test_dashboard_console_pages.py
T
ElebobaandClaude Opus 5.5 260422138a feat(dashboard): demo console with web chat, demo clock, scenario playback and split screen
- pages/2_Демо-консоль.py: persona selector, virtual clock bar (+1 h, to 08:00/20:00,
  next day, reset with confirm), fallback patient web chat (buttons from Reply.buttons,
  kind styling, outbox drained after every action and on a 2 s fragment poll), scenario panel
- pages/3_Сплит-экран.py: patient chat or PATIENT_WEB_URL iframe on the left, compact doctor
  panel (patients, live alerts, red banner on a new acute alert) on the right
- console/playback.py: data/synthetic/<persona>.jsonl runner (advance_to/press/text/
  expect_color/start), date chaining between days, pause on failure with retry/skip/manual
- console/api.py: own HTTP client over the frozen API contract, ApiError only

Refs #17

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 12:46:14 +03:00

65 lines
2.7 KiB
Python

"""Demo console pages (#17) render without crashing even when the API is down (robustness of the live demo)."""
from pathlib import Path
import pytest
from streamlit.testing.v1 import AppTest
PAGES = Path(__file__).resolve().parents[1] / "dashboard" / "pages"
@pytest.fixture
def api_down(monkeypatch):
monkeypatch.setenv("API_BASE_URL", "http://127.0.0.1:9") # nothing listens on the discard port
monkeypatch.setenv("DEMO_PERSONA_TOKEN", "tok-andrey")
monkeypatch.delenv("PATIENT_WEB_URL", raising=False)
def _page(name: str) -> AppTest:
return AppTest.from_file(str(PAGES / name), default_timeout=30)
def test_console_page_survives_api_down_and_button_clicks(api_down, tmp_path):
scenario = tmp_path / "s.jsonl"
scenario.write_text('{"day": 1, "note": "утро", "actions": [{"advance_to": "08:00"}]}\n', encoding="utf-8")
at = _page("2_Демо-консоль.py")
at.session_state["console_scenario_path:tok-andrey"] = str(scenario)
at.run()
assert not at.exception
assert any("Часы недоступны" in w.value for w in at.warning)
labels = [b.label for b in at.button]
assert {"+1 час", "Следующий день", "🚀 Начать", "▶ Проиграть день 1"} <= set(labels)
at.button(key="console-clock-d1").click().run() # «Следующий день» with the API down
assert not at.exception
at.button(key="console-chat-start").click().run()
assert not at.exception
next(b for b in at.button if b.label == "▶ Проиграть день 1").click().run()
assert not at.exception
state = at.session_state["console_playback:tok-andrey"]
assert state.failed is not None and state.done == [] # playback paused, page alive
at.run()
assert not at.exception
assert any("Повторить шаг" in b.label for b in at.button), [b.label for b in at.button]
def test_console_page_without_scenario_file(api_down):
at = _page("2_Демо-консоль.py")
at.session_state["console_scenario_path:tok-andrey"] = "data/synthetic/__missing__.jsonl"
at.run()
assert not at.exception
assert any("Сценарий не загружен" in i.value for i in at.info)
def test_split_screen_survives_api_down_and_uses_iframe_when_configured(api_down, monkeypatch):
at = _page("3_Сплит-экран.py")
at.run()
assert not at.exception
assert any("Алерты недоступны" in w.value for w in at.warning)
monkeypatch.setenv("PATIENT_WEB_URL", "http://localhost:5173")
at = _page("3_Сплит-экран.py")
at.run()
assert not at.exception
assert any("http://localhost:5173" in c.value for c in at.caption)