| """Tests for the public Hugging Face chat Space app.""" |
|
|
| from __future__ import annotations |
|
|
| import importlib |
| import sys |
| from pathlib import Path |
|
|
| from fastapi.testclient import TestClient |
|
|
| REPO_ROOT = Path(__file__).resolve().parents[2] |
| if str(REPO_ROOT) not in sys.path: |
| sys.path.insert(0, str(REPO_ROOT)) |
|
|
| chat_space_app = importlib.import_module("huggingface_chat_space.app") |
|
|
|
|
| def test_chat_space_index_contains_persona_and_model_controls() -> None: |
| client = TestClient(chat_space_app.app) |
|
|
| response = client.get("/") |
|
|
| assert response.status_code == 200 |
| assert 'id="model"' in response.text |
| assert 'id="custom-model"' in response.text |
| assert 'id="persona-list"' in response.text |
| assert 'id="session-list"' in response.text |
| assert "Māris AI" in response.text |
| assert "Jauna saruna" in response.text |
| assert "Tiešsaistē" in response.text |
| assert "Māris AI chat logo" in response.text |
| assert "Dzēst sesiju" in response.text |
|
|
|
|
| def test_chat_space_index_avoids_resending_pending_user_turn() -> None: |
| client = TestClient(chat_space_app.app) |
|
|
| response = client.get("/") |
|
|
| assert response.status_code == 200 |
| assert "function historyPayloadForRequest" in response.text |
| assert "function resolveRequestedModel" in response.text |
| assert "historyPayloadForRequest(sessionForRequest || activeSession, message)" in response.text |
| assert "model: resolveRequestedModel(sessionForRequest || activeSession)" in response.text |
|
|
|
|
| def test_chat_endpoint_returns_generated_payload(monkeypatch) -> None: |
| client = TestClient(chat_space_app.app) |
|
|
| class DummyResponse: |
| def model_dump(self) -> dict[str, object]: |
| return { |
| "response": "Sakārtoju atbildi.", |
| "model": "MarisUK/Codex", |
| "persona_id": "strategist", |
| "persona_title": "Systems Strategist", |
| "persona_summary": "Stratēģiska persona.", |
| "detected_emotion": "curious", |
| "emotion_confidence": 0.82, |
| "response_style": "clear_grounded", |
| } |
|
|
| async def fake_generate_reply(request): |
| assert request.persona_id == "strategist" |
| return DummyResponse() |
|
|
| monkeypatch.setattr(chat_space_app, "generate_space_chat_reply", fake_generate_reply) |
|
|
| response = client.post( |
| "/api/chat", |
| json={ |
| "message": "Palīdzi ar roadmap", |
| "history": [], |
| "model": "MarisUK/Codex", |
| "persona_id": "strategist", |
| }, |
| ) |
|
|
| assert response.status_code == 200 |
| assert response.json()["persona_title"] == "Systems Strategist" |
| assert response.json()["response"] == "Sakārtoju atbildi." |
|
|
|
|
| def test_chat_space_exposes_api_health_and_cors() -> None: |
| client = TestClient(chat_space_app.app) |
|
|
| health_response = client.get("/api/health") |
| assert health_response.status_code == 200 |
| assert health_response.json()["service"] == "maris-chat-space" |
|
|
| cors_response = client.options( |
| "/api/chat", |
| headers={ |
| "Origin": "https://example.com", |
| "Access-Control-Request-Method": "POST", |
| }, |
| ) |
| assert cors_response.status_code == 200 |
| assert cors_response.headers["access-control-allow-origin"] == "*" |
|
|
|
|
| def test_chat_endpoint_hides_internal_stop_iteration_errors(monkeypatch) -> None: |
| client = TestClient(chat_space_app.app) |
|
|
| async def fake_generate_reply(request): |
| del request |
| raise RuntimeError("coroutine raised StopIteration") |
|
|
| monkeypatch.setattr(chat_space_app, "generate_space_chat_reply", fake_generate_reply) |
|
|
| response = client.post( |
| "/api/chat", |
| json={ |
| "message": "Palīdzi ar roadmap", |
| "history": [], |
| "model": "MarisUK/Codex", |
| "persona_id": "strategist", |
| }, |
| ) |
|
|
| assert response.status_code == 503 |
| assert response.json()["detail"] == ( |
| "Māris AI Space īslaicīgi nevar atbildēt. Lūdzu, mēģini vēlreiz pēc brīža." |
| ) |
|
|