128 lines
5.0 KiB
Python
128 lines
5.0 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from opc.plugins.cli_board.state.models import BoardSnapshot, BoardTaskView, PendingCheckpointView
|
|
from opc.plugins.cli_board.state.store import BoardStateStore
|
|
|
|
|
|
def _task(task_id: str, title: str, column_id: str, *, status: str | None = None) -> BoardTaskView:
|
|
return BoardTaskView(
|
|
task_id=task_id,
|
|
title=title,
|
|
description=f"{title} description",
|
|
status=status or ("pending" if column_id == "todo" else "running"),
|
|
column_id=column_id,
|
|
priority="medium",
|
|
created_at=1.0,
|
|
updated_at=1.0,
|
|
)
|
|
|
|
|
|
class BoardStateStoreTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.store = BoardStateStore()
|
|
self.store.replace_snapshot(
|
|
BoardSnapshot(
|
|
project_id="demo",
|
|
tasks=[
|
|
_task("todo-1", "Todo 1", "todo"),
|
|
_task("todo-2", "Todo 2", "todo"),
|
|
_task("run-1", "Run 1", "in-progress"),
|
|
_task("done-1", "Done 1", "done", status="done"),
|
|
],
|
|
)
|
|
)
|
|
|
|
def test_initial_selection_uses_first_visible_task(self) -> None:
|
|
selected = self.store.selected_task()
|
|
self.assertIsNotNone(selected)
|
|
self.assertEqual(selected.task_id, "todo-1")
|
|
|
|
def test_move_selection_crosses_columns_and_rows(self) -> None:
|
|
self.store.move_selection(row_delta=1)
|
|
self.assertEqual(self.store.selected_task().task_id, "todo-2")
|
|
|
|
self.store.move_selection(column_delta=1)
|
|
self.assertEqual(self.store.selected_task().task_id, "run-1")
|
|
|
|
self.store.move_selection(column_delta=1)
|
|
self.assertEqual(self.store.selected_task().task_id, "done-1")
|
|
|
|
def test_toggle_done_hides_done_column_tasks(self) -> None:
|
|
showing = self.store.toggle_show_done()
|
|
self.assertFalse(showing)
|
|
counts = self.store.board_counts()
|
|
self.assertEqual(counts["done"], 0)
|
|
|
|
def test_search_filter_updates_selection(self) -> None:
|
|
self.store.set_search_query("run")
|
|
selected = self.store.selected_task()
|
|
self.assertIsNotNone(selected)
|
|
self.assertEqual(selected.task_id, "run-1")
|
|
|
|
def test_runtime_updates_and_progress_are_tracked(self) -> None:
|
|
self.store.apply_runtime_update(
|
|
"run-1",
|
|
status="tool_active",
|
|
current_tool="shell_exec",
|
|
iteration=2,
|
|
tool_elapsed_ms=420,
|
|
last_tool_summary="pytest -q completed",
|
|
context_tokens=1200,
|
|
context_window=4000,
|
|
context_remaining_pct=70,
|
|
turn_cost_usd=0.0123,
|
|
session_cost_usd=0.0456,
|
|
pending_permission_count=1,
|
|
drain_mode="smooth",
|
|
)
|
|
self.store.append_progress("run-1", "[Tool: shell_exec] pytest -q")
|
|
|
|
runtime = self.store.runtime_for("run-1")
|
|
self.assertIsNotNone(runtime)
|
|
self.assertEqual(runtime.status, "tool_active")
|
|
self.assertEqual(runtime.current_tool, "shell_exec")
|
|
self.assertEqual(runtime.iteration, 2)
|
|
self.assertEqual(runtime.tool_elapsed_ms, 420)
|
|
self.assertEqual(runtime.last_tool_summary, "pytest -q completed")
|
|
self.assertEqual(runtime.context_remaining_pct, 70)
|
|
self.assertEqual(runtime.turn_cost_usd, 0.0123)
|
|
self.assertEqual(runtime.pending_permission_count, 1)
|
|
self.assertEqual(runtime.drain_mode, "smooth")
|
|
self.assertEqual(len(runtime.progress_entries), 1)
|
|
|
|
def test_metrics_and_alerts_include_snapshot_and_runtime_state(self) -> None:
|
|
self.store.snapshot.hidden_task_count = 2
|
|
self.store.snapshot.pending_checkpoint_count = 1
|
|
self.store.snapshot.tasks[2].pending_checkpoint = PendingCheckpointView(
|
|
checkpoint_id="cp-1",
|
|
checkpoint_type="task_user_input",
|
|
status="pending",
|
|
session_id="session-run-1",
|
|
task_id="run-1",
|
|
summary="Need approval",
|
|
prompt="Approve this step",
|
|
)
|
|
self.store.apply_runtime_update("run-1", status="tool_active", current_tool="shell_exec")
|
|
|
|
metrics = self.store.metrics()
|
|
alerts = self.store.alerts()
|
|
|
|
self.assertEqual(metrics.total_tasks, 6)
|
|
self.assertEqual(metrics.pending_checkpoint_count, 1)
|
|
self.assertEqual(metrics.running_count, 1)
|
|
self.assertGreaterEqual(metrics.alert_count, 1)
|
|
self.assertTrue(any(alert.task_id == "run-1" for alert in alerts))
|
|
|
|
def test_session_navigation_and_view_state_controls(self) -> None:
|
|
self.store.select_task("run-1")
|
|
self.store.set_pane_focus("session-rail")
|
|
self.store.move_session_selection(1)
|
|
self.assertEqual(self.store.selected_task().task_id, "todo-1")
|
|
|
|
self.store.set_view_mode("list")
|
|
self.assertEqual(self.store.view_mode, "list")
|
|
self.assertEqual(self.store.toggle_density(), "comfortable")
|
|
self.assertEqual(self.store.cycle_context_tab(1), "session")
|