| """Self-check for app.py upload and api_result asynchronous endpoints (CR-10).""" |
| import importlib |
| import io |
| import os |
| import sys |
| import tempfile |
|
|
| HERE = os.path.dirname(os.path.abspath(__file__)) |
| sys.path.insert(0, os.path.dirname(HERE)) |
|
|
| def test_async_api_flow(): |
| fd, db_path = tempfile.mkstemp(suffix=".db") |
| os.close(fd) |
| os.environ["LDV_DB_PATH"] = db_path |
| os.environ["LDV_SECRET_KEY"] = "test-secret-key-123" |
| os.environ.pop("LDV_ENCRYPTION_KEY", None) |
|
|
| import database |
| importlib.reload(database) |
| database.init_db() |
|
|
| import auth |
| importlib.reload(auth) |
|
|
| |
| oid = database.create_org("TestOrg") |
| user_token = "user-api-token-123" |
| database.create_user(oid, "user@testorg.com", auth.hash_password("password"), "user", user_token) |
|
|
| other_oid = database.create_org("OtherOrg") |
| other_token = "other-api-token-123" |
| database.create_user(other_oid, "other@otherorg.com", auth.hash_password("password"), "user", other_token) |
|
|
| |
| submitted_jobs = [] |
| import worker |
| worker.submit_job = lambda public_id, text, lang, explain, policy_name=None: submitted_jobs.append((public_id, text, lang, explain, policy_name)) |
|
|
| |
| import app |
| importlib.reload(app) |
| client = app.app.test_client() |
|
|
| try: |
| |
| data = { |
| "file": (io.BytesIO(b"This is a dummy contract document."), "contract.txt") |
| } |
| headers = { |
| "Authorization": f"Bearer {user_token}" |
| } |
| resp = client.post("/api/v1/upload", data=data, headers=headers, content_type="multipart/form-data") |
| assert resp.status_code == 202, resp.status_code |
| res_json = resp.json |
| assert "id" in res_json |
| assert res_json["status"] == "queued" |
|
|
| |
| analysis_id = res_json["id"] |
| assert len(submitted_jobs) == 1 |
| assert submitted_jobs[0][0] == analysis_id |
| assert "dummy contract document" in submitted_jobs[0][1] |
|
|
| |
| |
| resp = client.get(f"/api/v1/result/{analysis_id}", headers=headers) |
| assert resp.status_code == 200, resp.status_code |
| assert resp.json["status"] == "queued" |
| assert resp.json["result"] is None |
|
|
| |
| database.update_analysis(analysis_id, status="processing") |
| resp = client.get(f"/api/v1/result/{analysis_id}", headers=headers) |
| assert resp.status_code == 200, resp.status_code |
| assert resp.json["status"] == "processing" |
| assert resp.json["result"] is None |
|
|
| |
| mock_result = {"layer1": {}, "layer2": {}, "layer3": {"score": 5, "label": "LOW"}} |
| database.update_analysis(analysis_id, status="completed", risk_score=5, risk_label="LOW", result=mock_result) |
| resp = client.get(f"/api/v1/result/{analysis_id}", headers=headers) |
| assert resp.status_code == 200, resp.status_code |
| assert resp.json["status"] == "completed" |
| assert resp.json["result"] == mock_result |
|
|
| |
| assert "extracted_text" not in resp.json |
| assert "raw_text" not in resp.json |
|
|
| |
| resp_debug = client.get(f"/api/v1/result/{analysis_id}?debug=1", headers=headers) |
| assert resp_debug.status_code == 200 |
| assert resp_debug.json.get("raw_text") == "This is a dummy contract document." |
|
|
| |
| |
| other_headers = { |
| "Authorization": f"Bearer {other_token}" |
| } |
| resp = client.get(f"/api/v1/result/{analysis_id}", headers=other_headers) |
| assert resp.status_code == 403, resp.status_code |
| finally: |
| os.remove(db_path) |
|
|
| if __name__ == "__main__": |
| test_async_api_flow() |
| print("test_async_api OK") |
|
|