Initial commit: CI Agent competitive-intelligence monitoring app
FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
"""Reports API: ownership isolation, manual generation, and the raw
|
||||
markdown/json export endpoints."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
|
||||
def _register_and_login(client) -> dict[str, str]:
|
||||
email = f"user-{uuid.uuid4().hex[:12]}@example.com"
|
||||
client.post(
|
||||
"/api/v1/auth/register",
|
||||
json={"email": email, "password": "correct-horse-1", "display_name": "Test User"},
|
||||
)
|
||||
tokens = client.post(
|
||||
"/api/v1/auth/login", json={"email": email, "password": "correct-horse-1"}
|
||||
).json()
|
||||
return {"Authorization": f"Bearer {tokens['access_token']}"}
|
||||
|
||||
|
||||
def _create_company(client, headers):
|
||||
return client.post(
|
||||
"/api/v1/companies",
|
||||
json={"name": f"Report Co {uuid.uuid4().hex[:6]}", "frequency_type": "weekly"},
|
||||
headers=headers,
|
||||
).json()
|
||||
|
||||
|
||||
def test_generate_report_creates_and_returns_report(client):
|
||||
headers = _register_and_login(client)
|
||||
company = _create_company(client, headers)
|
||||
|
||||
resp = client.post(f"/api/v1/companies/{company['id']}/reports/generate", headers=headers)
|
||||
assert resp.status_code == 201
|
||||
body = resp.json()
|
||||
assert body["report_type"] == "manual"
|
||||
assert body["model_provider"] == "mock"
|
||||
assert company["name"] in body["executive_summary"]
|
||||
|
||||
|
||||
def test_list_reports_and_get_detail(client):
|
||||
headers = _register_and_login(client)
|
||||
company = _create_company(client, headers)
|
||||
created = client.post(
|
||||
f"/api/v1/companies/{company['id']}/reports/generate", headers=headers
|
||||
).json()
|
||||
|
||||
listing = client.get(f"/api/v1/companies/{company['id']}/reports", headers=headers).json()
|
||||
assert any(r["id"] == created["id"] for r in listing)
|
||||
|
||||
detail = client.get(f"/api/v1/reports/{created['id']}", headers=headers)
|
||||
assert detail.status_code == 200
|
||||
assert detail.json()["structured_report"]["executive_summary"]
|
||||
|
||||
|
||||
def test_report_markdown_and_json_export(client):
|
||||
headers = _register_and_login(client)
|
||||
company = _create_company(client, headers)
|
||||
created = client.post(
|
||||
f"/api/v1/companies/{company['id']}/reports/generate", headers=headers
|
||||
).json()
|
||||
|
||||
md_resp = client.get(f"/api/v1/reports/{created['id']}/markdown", headers=headers)
|
||||
assert md_resp.status_code == 200
|
||||
assert md_resp.headers["content-type"].startswith("text/markdown")
|
||||
assert "# Competitive Intelligence Report" in md_resp.text
|
||||
|
||||
json_resp = client.get(f"/api/v1/reports/{created['id']}/json", headers=headers)
|
||||
assert json_resp.status_code == 200
|
||||
assert "executive_summary" in json_resp.json()
|
||||
|
||||
|
||||
def test_reports_scoped_to_owner(client):
|
||||
owner_headers = _register_and_login(client)
|
||||
other_headers = _register_and_login(client)
|
||||
company = _create_company(client, owner_headers)
|
||||
created = client.post(
|
||||
f"/api/v1/companies/{company['id']}/reports/generate", headers=owner_headers
|
||||
).json()
|
||||
|
||||
assert (
|
||||
client.get(f"/api/v1/companies/{company['id']}/reports", headers=other_headers).status_code
|
||||
== 404
|
||||
)
|
||||
assert client.get(f"/api/v1/reports/{created['id']}", headers=other_headers).status_code == 404
|
||||
assert (
|
||||
client.post(
|
||||
f"/api/v1/companies/{company['id']}/reports/generate", headers=other_headers
|
||||
).status_code
|
||||
== 404
|
||||
)
|
||||
Reference in New Issue
Block a user