Spaces:
Runtime error
Runtime error
Download backend/tests/test_api_fetching.py from compendious/precis: direct link, hf CLI and curl.
- Browser
- Download file 5.86 kB
-
https://huggingface.co/spaces/compendious/precis/resolve/main/backend/tests/test_api_fetching.py
- Command line
-
hf download hf://spaces/compendious/precis/backend/tests/test_api_fetching.py
-
curl -L -o test_api_fetching.py https://huggingface.co/spaces/compendious/precis/resolve/main/backend/tests/test_api_fetching.py
5.86 kB
| import json | |
| import pytest | |
| from unittest.mock import AsyncMock, MagicMock, patch | |
| from fastapi.testclient import TestClient | |
| # Mock env before importing app | |
| import os | |
| import sys | |
| from pathlib import Path | |
| # Ensure `backend` is on path when running `pytest` from repo root | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[1])) | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "backend")) | |
| os.environ.setdefault("OLLAMA_BASE_URL", "http://127.0.0.1:11434") | |
| os.environ.setdefault("DEFAULT_MODEL", "phi4-mini:latest") | |
| os.environ.setdefault("PRECIS_API_KEY", "test-key") | |
| os.environ.setdefault("AVAILABLE_MODELS", "phi4-mini:latest,qwen:4b") | |
| from app import app | |
| client = TestClient(app) | |
| API_KEY = "test-key" | |
| HEADERS = {"X-API-Key": API_KEY} | |
| def test_health(): | |
| r = client.get("/health") | |
| assert r.status_code == 200 | |
| assert r.json() == {"status": "healthy", "service": "precis"} | |
| def test_status_ollama_reachable(mock_client): | |
| mock_resp = MagicMock() | |
| mock_resp.status_code = 200 | |
| mock_client.return_value.__aenter__.return_value.get = AsyncMock(return_value=mock_resp) | |
| r = client.get("/status") | |
| assert r.status_code == 200 | |
| assert "ollama_reachable" in r.json() | |
| def test_models_returns_installed_when_present(mock_client): | |
| # /api/tags returns 2 models, /api/ps returns 1 running | |
| tags_resp = MagicMock() | |
| tags_resp.status_code = 200 | |
| tags_resp.content = b'{"models":[{"name":"phi4-mini:latest"},{"name":"qwen:4b"}]}' | |
| tags_resp.json.return_value = {"models": [{"name": "phi4-mini:latest"}, {"name": "qwen:4b"}]} | |
| tags_resp.raise_for_status = MagicMock() | |
| ps_resp = MagicMock() | |
| ps_resp.status_code = 200 | |
| ps_resp.content = b'{"models":[{"name":"phi4-mini:latest"}]}' | |
| ps_resp.json.return_value = {"models": [{"name": "phi4-mini:latest"}]} | |
| mock_instance = MagicMock() | |
| mock_instance.get = AsyncMock(side_effect=[tags_resp, ps_resp]) | |
| mock_client.return_value.__aenter__.return_value = mock_instance | |
| r = client.get("/models") | |
| assert r.status_code == 200 | |
| data = r.json() | |
| assert set(data["available"]) == {"phi4-mini:latest", "qwen:4b"} | |
| assert data["running"] == ["phi4-mini:latest"] | |
| assert data["default"] in data["available"] | |
| def test_models_returns_empty_when_ollama_has_no_models(mock_client): | |
| # Ollama reachable but 0 models — should NOT fallback to AVAILABLE_MODELS | |
| tags_resp = MagicMock() | |
| tags_resp.status_code = 200 | |
| tags_resp.content = b'{"models":[]}' | |
| tags_resp.json.return_value = {"models": []} | |
| tags_resp.raise_for_status = MagicMock() | |
| ps_resp = MagicMock() | |
| ps_resp.status_code = 200 | |
| ps_resp.content = b'{"models":[]}' | |
| ps_resp.json.return_value = {"models": []} | |
| mock_instance = MagicMock() | |
| mock_instance.get = AsyncMock(side_effect=[tags_resp, ps_resp]) | |
| mock_client.return_value.__aenter__.return_value = mock_instance | |
| r = client.get("/models") | |
| assert r.status_code == 200 | |
| data = r.json() | |
| # Fixed bug: should be empty, not fallback | |
| assert data["available"] == [] | |
| assert data["default"] is None | |
| assert data["running"] == [] | |
| def test_models_fallback_when_ollama_unreachable(mock_client): | |
| mock_client.return_value.__aenter__.return_value.get = AsyncMock(side_effect=Exception("connection refused")) | |
| r = client.get("/models") | |
| assert r.status_code == 200 | |
| data = r.json() | |
| # Fallback to env when Ollama down | |
| assert "phi4-mini:latest" in data["available"] | |
| assert data["default"] == "phi4-mini:latest" | |
| def test_youtube_id_strips_timestamp(): | |
| from helpers.transcript import _extract_video_id, _strip_timestamp | |
| # t=, start, time_continue stripped before ID extraction | |
| assert _extract_video_id("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=42s") == "dQw4w9WgXcQ" | |
| assert _extract_video_id("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=1m30s&start=30") == "dQw4w9WgXcQ" | |
| assert _extract_video_id("https://youtu.be/dQw4w9WgXcQ?t=120") == "dQw4w9WgXcQ" | |
| assert _extract_video_id("https://www.youtube.com/shorts/dQw4w9WgXcQ?t=10") == "dQw4w9WgXcQ" | |
| # _strip_timestamp removes params | |
| assert "t=" not in _strip_timestamp("https://www.youtube.com/watch?v=abc12345678&t=120s") | |
| assert "start=" not in _strip_timestamp("https://www.youtube.com/watch?v=abc12345678&start=30") | |
| def test_transcript_fetch_uses_stripped_id(mock_api): | |
| from helpers.transcript import transcript | |
| import asyncio | |
| mock_instance = MagicMock() | |
| mock_instance.fetch.return_value = [MagicMock(text="hello"), MagicMock(text="world")] | |
| mock_api.return_value = mock_instance | |
| # Should strip t= and fetch with clean ID | |
| title, text = asyncio.run(transcript("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=42s")) | |
| # fetch called with clean ID, not including t= | |
| assert mock_instance.fetch.called | |
| args, kwargs = mock_instance.fetch.call_args | |
| assert args[0] == "dQw4w9WgXcQ" | |
| def test_summarize_transcript_requires_api_key(mock_summary): | |
| mock_summary.return_value = MagicMock() | |
| # No key -> 401, with key -> mocked success (not 401) | |
| r = client.post("/summarize/transcript", json={"text": "hello"}) | |
| assert r.status_code == 401 | |
| r = client.post("/summarize/transcript", json={"text": "hello"}, headers=HEADERS) | |
| assert r.status_code != 401 | |
| mock_summary.assert_called_once() | |
| def test_summarize_file_rejects_non_txt(): | |
| import io | |
| files = {"file": ("test.pdf", io.BytesIO(b"hello"), "application/pdf")} | |
| r = client.post("/summarize/file", files=files, headers=HEADERS) | |
| assert r.status_code == 400 | |
| assert "Only .txt" in r.text | |