Files
Timmy-time-dashboard/tests/dashboard/test_chat_api.py

178 lines
5.8 KiB
Python
Raw Normal View History

"""Tests for the JSON chat API (/api/chat, /api/upload, /api/chat/history)."""
import io
from unittest.mock import patch
# ── POST /api/chat ────────────────────────────────────────────────────────────
def test_api_chat_success(client):
with patch("dashboard.routes.chat_api.agent_chat", return_value="Hello."):
response = client.post(
"/api/chat",
json={"messages": [{"role": "user", "content": "hello"}]},
)
assert response.status_code == 200
data = response.json()
assert data["reply"] == "Hello."
assert "timestamp" in data
def test_api_chat_multimodal_content(client):
"""Multimodal content arrays should extract text parts."""
with patch("dashboard.routes.chat_api.agent_chat", return_value="I see an image."):
response = client.post(
"/api/chat",
json={
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "What is this?"},
{"type": "image_url", "image_url": {"url": "/uploads/test.jpg"}},
],
}
]
},
)
assert response.status_code == 200
assert response.json()["reply"] == "I see an image."
def test_api_chat_empty_messages(client):
response = client.post("/api/chat", json={"messages": []})
assert response.status_code == 400
assert "error" in response.json()
def test_api_chat_missing_messages(client):
response = client.post("/api/chat", json={"foo": "bar"})
assert response.status_code == 400
assert "messages" in response.json()["error"]
def test_api_chat_no_user_message(client):
response = client.post(
"/api/chat",
json={"messages": [{"role": "assistant", "content": "hi"}]},
)
assert response.status_code == 400
assert "No user message" in response.json()["error"]
def test_api_chat_ollama_offline(client):
with patch(
"dashboard.routes.chat_api.agent_chat",
side_effect=ConnectionError("Ollama unreachable"),
):
response = client.post(
"/api/chat",
json={"messages": [{"role": "user", "content": "hello"}]},
)
assert response.status_code == 503
data = response.json()
assert "offline" in data["error"].lower() or "unreachable" in data["error"].lower()
def test_api_chat_logs_to_message_log(client):
from dashboard.store import message_log
with patch("dashboard.routes.chat_api.agent_chat", return_value="Reply."):
client.post(
"/api/chat",
json={"messages": [{"role": "user", "content": "test msg"}]},
)
entries = message_log.all()
assert len(entries) == 2
assert entries[0].role == "user"
assert entries[0].content == "test msg"
assert entries[1].role == "agent"
assert entries[1].content == "Reply."
def test_api_chat_invalid_json(client):
response = client.post(
"/api/chat",
content=b"not json",
headers={"content-type": "application/json"},
)
assert response.status_code == 400
# ── POST /api/upload ──────────────────────────────────────────────────────────
def test_api_upload_file(client, tmp_path):
with patch("dashboard.routes.chat_api._UPLOAD_DIR", str(tmp_path)):
response = client.post(
"/api/upload",
files={"file": ("test.txt", io.BytesIO(b"hello world"), "text/plain")},
)
assert response.status_code == 200
data = response.json()
assert data["fileName"] == "test.txt"
assert data["mimeType"] == "text/plain"
assert "/uploads/" in data["url"]
def test_api_upload_image(client, tmp_path):
# 1x1 red PNG
png = (
b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01"
b"\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00"
)
with patch("dashboard.routes.chat_api._UPLOAD_DIR", str(tmp_path)):
response = client.post(
"/api/upload",
files={"file": ("photo.png", io.BytesIO(png), "image/png")},
)
assert response.status_code == 200
data = response.json()
assert data["fileName"] == "photo.png"
assert data["mimeType"] == "image/png"
# ── GET /api/chat/history ────────────────────────────────────────────────────
def test_api_chat_history_empty(client):
response = client.get("/api/chat/history")
assert response.status_code == 200
assert response.json()["messages"] == []
def test_api_chat_history_after_chat(client):
with patch("dashboard.routes.chat_api.agent_chat", return_value="Hi!"):
client.post(
"/api/chat",
json={"messages": [{"role": "user", "content": "hello"}]},
)
response = client.get("/api/chat/history")
assert response.status_code == 200
msgs = response.json()["messages"]
assert len(msgs) == 2
assert msgs[0]["role"] == "user"
assert msgs[1]["role"] == "agent"
# ── DELETE /api/chat/history ──────────────────────────────────────────────────
def test_api_clear_history(client):
from dashboard.store import message_log
message_log.append(role="user", content="old", timestamp="00:00:00")
response = client.delete("/api/chat/history")
assert response.status_code == 200
assert response.json()["success"] is True
assert len(message_log) == 0