This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/tests/functional/test_dashboard.py
Claude c91e02e7c5 test: add functional test suite with real fixtures, no mocking
Three-tier functional test infrastructure:
- CLI tests via Typer CliRunner (timmy, timmy-serve, self-tdd)
- Dashboard integration tests with real TestClient, real SQLite, real
  coordinator (no patch/mock — Ollama offline = graceful degradation)
- Docker compose container-level tests (gated by FUNCTIONAL_DOCKER=1)
- End-to-end L402 payment flow with real mock-lightning backend

42 new tests (8 Docker tests skipped without FUNCTIONAL_DOCKER=1).
All 849 tests pass.

https://claude.ai/code/session_01WU4h3cQQiouMwmgYmAgkMM
2026-02-25 00:46:22 +00:00

200 lines
8.0 KiB
Python

"""Functional tests for the dashboard — real HTTP requests, no mocking.
The dashboard runs with Ollama offline (graceful degradation).
These tests verify what a real user sees when they open the browser.
"""
import pytest
class TestDashboardLoads:
"""Verify the dashboard serves real HTML pages."""
def test_index_page(self, app_client):
response = app_client.get("/")
assert response.status_code == 200
assert "text/html" in response.headers["content-type"]
# The real rendered page should have the base HTML structure
assert "<html" in response.text
assert "Timmy" in response.text
def test_health_endpoint(self, app_client):
response = app_client.get("/health")
assert response.status_code == 200
data = response.json()
assert "status" in data or "ollama" in data
def test_agents_json(self, app_client):
response = app_client.get("/agents")
assert response.status_code == 200
data = response.json()
assert isinstance(data, (dict, list))
def test_swarm_live_page(self, app_client):
response = app_client.get("/swarm/live")
assert response.status_code == 200
assert "text/html" in response.headers["content-type"]
assert "WebSocket" in response.text or "swarm" in response.text.lower()
def test_mobile_endpoint(self, app_client):
response = app_client.get("/mobile/status")
assert response.status_code == 200
class TestChatFlowOffline:
"""Test the chat flow when Ollama is not running.
This is a real user scenario — they start the dashboard before Ollama.
The app should degrade gracefully, not crash.
"""
def test_chat_with_ollama_offline(self, app_client):
"""POST to chat endpoint — should return HTML with an error message,
not a 500 server error."""
response = app_client.post(
"/agents/timmy/chat",
data={"message": "hello timmy"},
)
# The route catches exceptions and returns them in the template
assert response.status_code == 200
assert "text/html" in response.headers["content-type"]
# Should contain either the error message or the response
assert "hello timmy" in response.text or "offline" in response.text.lower() or "error" in response.text.lower()
def test_chat_requires_message_field(self, app_client):
"""POST without the message field should fail."""
response = app_client.post("/agents/timmy/chat", data={})
assert response.status_code == 422
def test_history_starts_empty(self, app_client):
response = app_client.get("/agents/timmy/history")
assert response.status_code == 200
def test_chat_then_history(self, app_client):
"""After chatting, history should contain the message."""
app_client.post("/agents/timmy/chat", data={"message": "test message"})
response = app_client.get("/agents/timmy/history")
assert response.status_code == 200
assert "test message" in response.text
def test_clear_history(self, app_client):
app_client.post("/agents/timmy/chat", data={"message": "ephemeral"})
response = app_client.delete("/agents/timmy/history")
assert response.status_code == 200
class TestSwarmLifecycle:
"""Full swarm lifecycle: spawn → post task → bid → assign → complete.
No mocking. Real coordinator, real SQLite, real in-process agents.
"""
def test_spawn_agent_and_list(self, app_client):
spawn = app_client.post("/swarm/spawn", data={"name": "Echo"})
assert spawn.status_code == 200
spawn_data = spawn.json()
agent_id = spawn_data.get("id") or spawn_data.get("agent_id")
assert agent_id
agents = app_client.get("/swarm/agents")
assert agents.status_code == 200
agent_names = [a["name"] for a in agents.json()["agents"]]
assert "Echo" in agent_names
def test_post_task_opens_auction(self, app_client):
resp = app_client.post("/swarm/tasks", data={"description": "Summarize README"})
assert resp.status_code == 200
data = resp.json()
assert data["description"] == "Summarize README"
assert data["status"] == "bidding"
def test_task_persists_in_list(self, app_client):
app_client.post("/swarm/tasks", data={"description": "Task Alpha"})
app_client.post("/swarm/tasks", data={"description": "Task Beta"})
resp = app_client.get("/swarm/tasks")
descriptions = [t["description"] for t in resp.json()["tasks"]]
assert "Task Alpha" in descriptions
assert "Task Beta" in descriptions
def test_complete_task(self, app_client):
post = app_client.post("/swarm/tasks", data={"description": "Quick job"})
task_id = post.json()["task_id"]
resp = app_client.post(
f"/swarm/tasks/{task_id}/complete",
data={"result": "Done."},
)
assert resp.status_code == 200
assert resp.json()["status"] == "completed"
# Verify the result persisted
task = app_client.get(f"/swarm/tasks/{task_id}")
assert task.json()["result"] == "Done."
def test_fail_task_feeds_learner(self, app_client):
post = app_client.post("/swarm/tasks", data={"description": "Doomed job"})
task_id = post.json()["task_id"]
resp = app_client.post(
f"/swarm/tasks/{task_id}/fail",
data={"reason": "OOM"},
)
assert resp.status_code == 200
assert resp.json()["status"] == "failed"
def test_stop_agent(self, app_client):
spawn = app_client.post("/swarm/spawn", data={"name": "Disposable"})
agent_id = spawn.json().get("id") or spawn.json().get("agent_id")
resp = app_client.delete(f"/swarm/agents/{agent_id}")
assert resp.status_code == 200
assert resp.json()["stopped"] is True
def test_insights_endpoint(self, app_client):
resp = app_client.get("/swarm/insights")
assert resp.status_code == 200
assert "agents" in resp.json()
def test_websocket_connects(self, app_client):
"""Real WebSocket connection to /swarm/live."""
with app_client.websocket_connect("/swarm/live") as ws:
ws.send_text("ping")
# Connection holds — the endpoint just logs, doesn't echo back.
# The point is it doesn't crash.
class TestSwarmUIPartials:
"""HTMX partial endpoints — verify they return real rendered HTML."""
def test_agents_sidebar_html(self, app_client):
app_client.post("/swarm/spawn", data={"name": "Echo"})
resp = app_client.get("/swarm/agents/sidebar")
assert resp.status_code == 200
assert "text/html" in resp.headers["content-type"]
assert "echo" in resp.text.lower()
def test_agent_panel_html(self, app_client):
spawn = app_client.post("/swarm/spawn", data={"name": "Echo"})
agent_id = spawn.json().get("id") or spawn.json().get("agent_id")
resp = app_client.get(f"/swarm/agents/{agent_id}/panel")
assert resp.status_code == 200
assert "text/html" in resp.headers["content-type"]
assert "echo" in resp.text.lower()
def test_message_agent_creates_task(self, app_client):
spawn = app_client.post("/swarm/spawn", data={"name": "Worker"})
agent_id = spawn.json().get("id") or spawn.json().get("agent_id")
resp = app_client.post(
f"/swarm/agents/{agent_id}/message",
data={"message": "Summarise the codebase"},
)
assert resp.status_code == 200
assert "text/html" in resp.headers["content-type"]
def test_direct_assign_to_agent(self, app_client):
spawn = app_client.post("/swarm/spawn", data={"name": "Worker"})
agent_id = spawn.json().get("id") or spawn.json().get("agent_id")
resp = app_client.post(
"/swarm/tasks/direct",
data={"description": "Direct job", "agent_id": agent_id},
)
assert resp.status_code == 200
assert "text/html" in resp.headers["content-type"]