test: add unit tests for all 10 routers (92 total)
New test files: - test_conversations.py — list/create/get/update/delete/delete-all, admin enforcement - test_presets.py — list/create/update/delete, default preset protection - test_profile.py — get/update/default, length validation - test_models_router.py — list/ps/show/stats/search-status, connect errors - test_completions.py — API key auth, FIM passthrough, streaming/blocking, errors - test_search_route.py — explicit search flow, no results, stream errors - test_memories.py — edit/search/stats endpoints, validation, admin enforcement Update AGENTS.md with full test file coverage table and README.md
This commit is contained in:
153
tests/test_conversations.py
Normal file
153
tests/test_conversations.py
Normal file
@@ -0,0 +1,153 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import app
|
||||
import db
|
||||
from security import SESSIONS, PIN_ATTEMPTS, RATE_EVENTS
|
||||
|
||||
|
||||
def make_client(tmp_path: Path) -> TestClient:
|
||||
os.environ["JARVISCHAT_ADMIN_PIN"] = "1234"
|
||||
db.DB_PATH = tmp_path / "jarvischat-conversations.db"
|
||||
SESSIONS.clear()
|
||||
PIN_ATTEMPTS.clear()
|
||||
RATE_EVENTS.clear()
|
||||
db.init_db()
|
||||
return TestClient(app.app, raise_server_exceptions=False)
|
||||
|
||||
|
||||
def _admin_headers(client: TestClient) -> dict:
|
||||
login = client.post("/api/auth/login", json={"pin": "1234"}, headers={"Origin": "http://testserver"})
|
||||
sid = login.json()["session_id"]
|
||||
return {"X-Session-ID": sid, "Origin": "http://testserver"}
|
||||
|
||||
|
||||
def _guest_headers(client: TestClient) -> dict:
|
||||
sid = client.post("/api/auth/guest", headers={"Origin": "http://testserver"}).json()["session_id"]
|
||||
return {"X-Session-ID": sid, "Origin": "http://testserver"}
|
||||
|
||||
|
||||
def test_list_conversations_empty(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
resp = client.get("/api/conversations", headers=_guest_headers(client))
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() == []
|
||||
|
||||
|
||||
def test_create_and_list_conversation(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
headers = _admin_headers(client)
|
||||
|
||||
create = client.post("/api/conversations", json={"title": "Test Chat", "model": "llama3.1:latest"}, headers=headers)
|
||||
assert create.status_code == 200
|
||||
data = create.json()
|
||||
assert data["title"] == "Test Chat"
|
||||
assert data["model"] == "llama3.1:latest"
|
||||
|
||||
list_resp = client.get("/api/conversations", headers=headers)
|
||||
assert list_resp.status_code == 200
|
||||
convs = list_resp.json()
|
||||
assert len(convs) == 1
|
||||
assert convs[0]["title"] == "Test Chat"
|
||||
|
||||
|
||||
def test_get_conversation_returns_messages(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
headers = _admin_headers(client)
|
||||
create = client.post("/api/conversations", json={"title": "My Chat"}, headers=headers)
|
||||
conv_id = create.json()["id"]
|
||||
|
||||
resp = client.get(f"/api/conversations/{conv_id}", headers=headers)
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["conversation"]["id"] == conv_id
|
||||
assert data["messages"] == []
|
||||
|
||||
|
||||
def test_get_conversation_not_found(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
resp = client.get("/api/conversations/nope", headers=_guest_headers(client))
|
||||
assert resp.status_code == 404
|
||||
|
||||
|
||||
def test_update_conversation_title(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
headers = _admin_headers(client)
|
||||
create = client.post("/api/conversations", json={"title": "Old"}, headers=headers)
|
||||
conv_id = create.json()["id"]
|
||||
|
||||
update = client.put(f"/api/conversations/{conv_id}", json={"title": "New Title"}, headers=headers)
|
||||
assert update.status_code == 200
|
||||
|
||||
get = client.get(f"/api/conversations/{conv_id}", headers=headers)
|
||||
assert get.json()["conversation"]["title"] == "New Title"
|
||||
|
||||
|
||||
def test_update_conversation_model(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
headers = _admin_headers(client)
|
||||
create = client.post("/api/conversations", json={"title": "Test"}, headers=headers)
|
||||
conv_id = create.json()["id"]
|
||||
|
||||
update = client.put(f"/api/conversations/{conv_id}", json={"model": "qwen2:latest"}, headers=headers)
|
||||
assert update.status_code == 200
|
||||
|
||||
get = client.get(f"/api/conversations/{conv_id}", headers=headers)
|
||||
assert get.json()["conversation"]["model"] == "qwen2:latest"
|
||||
|
||||
|
||||
def test_delete_conversation(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
headers = _admin_headers(client)
|
||||
create = client.post("/api/conversations", json={"title": "Delete Me"}, headers=headers)
|
||||
conv_id = create.json()["id"]
|
||||
|
||||
delete = client.delete(f"/api/conversations/{conv_id}", headers=headers)
|
||||
assert delete.status_code == 200
|
||||
|
||||
get = client.get(f"/api/conversations/{conv_id}", headers=_guest_headers(client))
|
||||
assert get.status_code == 404
|
||||
|
||||
|
||||
def test_delete_all_conversations(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
headers = _admin_headers(client)
|
||||
client.post("/api/conversations", json={"title": "One"}, headers=headers)
|
||||
client.post("/api/conversations", json={"title": "Two"}, headers=headers)
|
||||
|
||||
delete_all = client.delete("/api/conversations", headers=headers)
|
||||
assert delete_all.status_code == 200
|
||||
|
||||
list_resp = client.get("/api/conversations", headers=_guest_headers(client))
|
||||
assert list_resp.json() == []
|
||||
|
||||
|
||||
def test_guest_cannot_create_conversation(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
resp = client.post("/api/conversations", json={"title": "test"}, headers=_guest_headers(client))
|
||||
assert resp.status_code == 403
|
||||
|
||||
|
||||
def test_guest_cannot_update_conversation(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
headers = _admin_headers(client)
|
||||
create = client.post("/api/conversations", json={"title": "Test"}, headers=headers)
|
||||
conv_id = create.json()["id"]
|
||||
|
||||
guest_headers = _guest_headers(client)
|
||||
resp = client.put(f"/api/conversations/{conv_id}", json={"title": "hack"}, headers=guest_headers)
|
||||
assert resp.status_code == 403
|
||||
|
||||
|
||||
def test_guest_cannot_delete_conversation(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
resp = client.delete("/api/conversations/some-id", headers=_guest_headers(client))
|
||||
assert resp.status_code == 403
|
||||
|
||||
|
||||
def test_guest_cannot_delete_all(tmp_path: Path):
|
||||
with make_client(tmp_path) as client:
|
||||
resp = client.delete("/api/conversations", headers=_guest_headers(client))
|
||||
assert resp.status_code == 403
|
||||
Reference in New Issue
Block a user