112 lines
3.6 KiB
Python
112 lines
3.6 KiB
Python
"""Phase 6 maintenance API tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
from collections.abc import Generator
|
|
from contextlib import asynccontextmanager
|
|
from datetime import datetime
|
|
|
|
from fastapi.testclient import TestClient
|
|
from ont_platform.api import db_deps
|
|
from ont_platform.storage.candidate_repository import CandidateRepository
|
|
from ont_platform.storage.models import Base, SourceDocument
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import Session, sessionmaker
|
|
from sqlalchemy.pool import StaticPool
|
|
|
|
main_module = importlib.import_module("ont_platform.api.main")
|
|
|
|
|
|
@asynccontextmanager
|
|
async def _noop_lifespan(app):
|
|
yield
|
|
|
|
|
|
def _phase6_client(monkeypatch) -> TestClient:
|
|
monkeypatch.setenv("PHASE", "6")
|
|
engine = create_engine(
|
|
"sqlite://",
|
|
connect_args={"check_same_thread": False},
|
|
poolclass=StaticPool,
|
|
)
|
|
Base.metadata.create_all(engine)
|
|
session_factory = sessionmaker(bind=engine)
|
|
|
|
def override_get_db() -> Generator[Session, None, None]:
|
|
db = session_factory()
|
|
if db.get(SourceDocument, "doc_api_phase6") is None:
|
|
_seed(db)
|
|
db.commit()
|
|
try:
|
|
yield db
|
|
finally:
|
|
db.close()
|
|
|
|
app = main_module.create_app()
|
|
app.router.lifespan_context = _noop_lifespan
|
|
app.dependency_overrides[db_deps.get_db] = override_get_db
|
|
return TestClient(app, raise_server_exceptions=True, backend="asyncio")
|
|
|
|
|
|
def _seed(db: Session) -> None:
|
|
db.add(
|
|
SourceDocument(
|
|
id="doc_api_phase6",
|
|
project_id="proj_api_phase6",
|
|
source_url="https://example.test/api-phase6",
|
|
document_type="html",
|
|
title="API Phase 6 Source",
|
|
text="Acme appears in a source.",
|
|
content_hash="hash_api_phase6",
|
|
fingerprint="fp_api_phase6",
|
|
retrieved_at=datetime.utcnow(),
|
|
extracted_by="trafilatura",
|
|
)
|
|
)
|
|
CandidateRepository(db).save_lightweight_result(
|
|
project_id="proj_api_phase6",
|
|
document_id="doc_api_phase6",
|
|
result={
|
|
"entities": [
|
|
{
|
|
"id": "E_api_phase6",
|
|
"label": "Acme",
|
|
"type": "org",
|
|
"confidence": 0.4,
|
|
"evidence_ids": [],
|
|
}
|
|
],
|
|
"relations": [],
|
|
"evidence_spans": [],
|
|
},
|
|
)
|
|
|
|
|
|
def test_phase6_api_runs_loop_and_reviews_proposal(monkeypatch) -> None:
|
|
with _phase6_client(monkeypatch) as client:
|
|
run_response = client.post(
|
|
"/api/v1/maintenance/runs",
|
|
json={
|
|
"project_id": "proj_api_phase6",
|
|
"requested_by": "ops",
|
|
"actor_role": "admin",
|
|
},
|
|
)
|
|
proposal_response = client.get(
|
|
"/api/v1/maintenance/proposals",
|
|
params={"project_id": "proj_api_phase6", "status": "pending_review"},
|
|
)
|
|
proposal_id = proposal_response.json()["proposals"][0]["id"]
|
|
review_response = client.post(
|
|
f"/api/v1/maintenance/proposals/{proposal_id}/review",
|
|
json={"reviewed_by": "admin", "actor_role": "admin", "approve": True},
|
|
)
|
|
|
|
assert run_response.status_code == 200, run_response.text
|
|
assert run_response.json()["run"]["summary"]["direct_mutations"] == 0
|
|
assert proposal_response.status_code == 200
|
|
assert proposal_response.json()["proposals"]
|
|
assert review_response.status_code == 200, review_response.text
|
|
assert review_response.json()["proposal"]["status"] == "approved"
|