Skip to content

Commit 62fe738

Browse files
test: cover the real /ingest pipeline end-to-end (slow)
1 parent 0fc7a3b commit 62fe738

1 file changed

Lines changed: 44 additions & 0 deletions

File tree

tests/unit/test_ingest_route.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
"""POST /ingest (ADR 0029): flag gate, validation, and the happy-path append."""
22

3+
from pathlib import Path
34
from unittest import mock
45

6+
import fitz
57
import pytest
68
from fastapi.testclient import TestClient
79

810
from src.api.deps import get_settings
911
from src.api.main import create_app
1012
from src.config.settings import Settings
13+
from src.rag.bm25 import Bm25Index
14+
from src.rag.vectorstore import QdrantVectorStore
15+
from tests.fakes import FakeEmbedder
1116

1217

1318
def _app(enable_upload: bool) -> TestClient:
@@ -79,3 +84,42 @@ async def fake_ingest(**kwargs: object) -> mock.Mock:
7984
assert resp.status_code == 422
8085
assert "internal detail" not in resp.text # no exception/path leakage to the client
8186
assert "Could not parse" in resp.text
87+
88+
89+
@pytest.mark.slow
90+
async def test_ingest_route_real_pipeline(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
91+
"""The real /ingest pipeline, unmocked: Docling parse + embed + Qdrant upsert
92+
+ the live chunks_by_id append, then retrievable. Uses in-memory Qdrant + a
93+
fake embedder (the repo's e2e pattern), so it needs no services — only the
94+
real Docling parse, hence `slow`."""
95+
embedder = FakeEmbedder(dim=8)
96+
vectorstore = QdrantVectorStore(url=":memory:", collection_name="ingest_slow", dim=8)
97+
await vectorstore.ensure_collection()
98+
bm25 = Bm25Index()
99+
chunks: dict[str, object] = {}
100+
monkeypatch.setattr(
101+
"src.api.routes.ingest.get_corpus_handles", lambda: (embedder, vectorstore, bm25)
102+
)
103+
monkeypatch.setattr("src.api.routes.ingest.get_chunks", lambda: chunks)
104+
105+
doc = fitz.open()
106+
doc.new_page().insert_text(
107+
(72, 72),
108+
"The zorblax7731 calibration constant equals 88.5 in this synthetic test document.",
109+
fontsize=11,
110+
)
111+
pdf = tmp_path / "zorblax.pdf"
112+
doc.save(pdf)
113+
doc.close()
114+
115+
resp = _app(enable_upload=True).post(
116+
"/ingest", files={"file": ("zorblax.pdf", pdf.read_bytes(), "application/pdf")}
117+
)
118+
119+
assert resp.status_code == 200, resp.text
120+
body = resp.json()
121+
assert body["chunks_added"] >= 1
122+
assert body["paper_id"] == "zorblax"
123+
assert len(chunks) == body["chunks_added"] # route appended to the live index
124+
hits = bm25.search("zorblax7731", top_k=5) # the uploaded doc is now retrievable
125+
assert hits and any(h.chunk_id in chunks for h in hits)

0 commit comments

Comments
 (0)