File size: 2,405 Bytes
39ff835
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
"""Tests for the FastAPI layer (in-process, via TestClient).

We point INDEX_PATH at a non-existent file *before* importing the app so the
engine is built from the committed sample (fast, deterministic) and BERT is
disabled (no dense.pkl next to that path).
"""
import os
import sys
from pathlib import Path

import pytest

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))  # make the top-level `api` package importable
os.environ["INDEX_PATH"] = str(ROOT / "tests" / "_no_such_index.pkl")

from fastapi.testclient import TestClient  # noqa: E402
from api.main import app  # noqa: E402


@pytest.fixture(scope="module")
def client():
    with TestClient(app) as c:  # context manager runs startup/shutdown (lifespan)
        yield c


def test_health(client):
    r = client.get("/api/health")
    assert r.status_code == 200
    body = r.json()
    assert body["status"] == "ok"
    assert body["documents"] > 100
    assert body["bert_available"] is False
    assert "bm25" in body["methods"]


def test_categories(client):
    r = client.get("/api/categories")
    assert r.status_code == 200
    assert isinstance(r.json()["categories"], list)


def test_search_basic(client):
    r = client.get("/api/search", params={"q": "health", "method": "bm25", "top_k": 5})
    assert r.status_code == 200
    body = r.json()
    assert body["method"] == "bm25"
    assert len(body["results"]) <= 5
    assert body["total_hits"] >= len(body["results"])


def test_search_default_method_falls_back_to_bm25_without_bert(client):
    # No method given + BERT unavailable in this test deployment -> BM25, not an error.
    r = client.get("/api/search", params={"q": "health"})
    assert r.status_code == 200
    assert r.json()["method"] == "bm25"


def test_search_unknown_method_is_400(client):
    r = client.get("/api/search", params={"q": "health", "method": "nope"})
    assert r.status_code == 400


def test_search_bert_unavailable_is_400(client):
    r = client.get("/api/search", params={"q": "health", "method": "bert"})
    assert r.status_code == 400


def test_search_rejects_empty_query(client):
    r = client.get("/api/search", params={"q": ""})
    assert r.status_code == 422  # violates min_length=1


def test_search_rejects_overlong_query(client):
    r = client.get("/api/search", params={"q": "x" * 1000})
    assert r.status_code == 422  # violates max_length=512