Files
CIAgent/apps/api/tests/unit/test_discover_endpoint.py
T
saksham 1a4c80958f 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).
2026-08-05 10:48:20 -04:00

96 lines
3.5 KiB
Python

"""POST /companies/discover: persists nothing, returns a proposed profile,
rate-limited tightly since it costs a real search + LLM call."""
from __future__ import annotations
import json
import uuid
from unittest.mock import patch
import httpx
import respx
from app.core.rate_limit import limiter
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 _mock_empty_github_sec():
respx.get("https://api.github.com/search/users").mock(
return_value=httpx.Response(200, text=json.dumps({"items": []}))
)
respx.get("https://www.sec.gov/cgi-bin/browse-edgar").mock(
return_value=httpx.Response(
200, text='<?xml version="1.0"?><feed xmlns="http://www.w3.org/2005/Atom"></feed>'
)
)
def test_discover_returns_a_profile_without_persisting_a_company(client):
headers = _register_and_login(client)
with patch("socket.getaddrinfo", return_value=[(2, 1, 6, "", ("93.184.216.34", 0))]):
with respx.mock:
_mock_empty_github_sec()
respx.get("https://acmewidgets.com/robots.txt").mock(return_value=httpx.Response(404))
respx.get("https://acmewidgets.com").mock(
return_value=httpx.Response(200, html="<html><body>Acme Widgets</body></html>")
)
resp = client.post(
"/api/v1/companies/discover",
json={"name": "Acme Widgets"},
headers=headers,
)
assert resp.status_code == 200
body = resp.json()
assert body["name"] == "Acme Widgets"
assert body["official_website"] == "https://acmewidgets.com"
assert "potential_sources" in body
assert "sources_consulted" in body
companies = client.get("/api/v1/companies", headers=headers).json()
assert companies == []
def test_discover_requires_auth(client):
resp = client.post("/api/v1/companies/discover", json={"name": "Acme"})
assert resp.status_code in (401, 403)
def test_discover_enforces_rate_limit(client):
headers = _register_and_login(client)
limiter.enabled = True
try:
with patch("socket.getaddrinfo", return_value=[(2, 1, 6, "", ("93.184.216.34", 0))]):
with respx.mock:
_mock_empty_github_sec()
respx.route(host="acme0.com").mock(return_value=httpx.Response(404))
respx.route(host="acme1.com").mock(return_value=httpx.Response(404))
respx.route(host="acme2.com").mock(return_value=httpx.Response(404))
respx.route(host="acme3.com").mock(return_value=httpx.Response(404))
respx.route(host="acme4.com").mock(return_value=httpx.Response(404))
respx.route(host="acme5.com").mock(return_value=httpx.Response(404))
statuses = [
client.post(
"/api/v1/companies/discover",
json={"name": f"Acme{i}"},
headers=headers,
).status_code
for i in range(6)
]
assert 429 in statuses, f"Expected a 429 among {statuses} after 6 rapid discover calls"
finally:
limiter.enabled = False