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,98 @@
|
||||
"""Snapshots API: read-only history listing, newest-first, ownership-scoped.
|
||||
Snapshots have no creation endpoint (they're written internally by
|
||||
collection_service.py during a monitoring run), so tests insert one directly
|
||||
via db_session against the same DB the `client` fixture's TestClient uses."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
from app.models.snapshot import Snapshot
|
||||
|
||||
|
||||
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"Co {uuid.uuid4().hex[:6]}", "frequency_type": "weekly"},
|
||||
headers=headers,
|
||||
).json()
|
||||
|
||||
|
||||
def _create_source(client, headers, company_id):
|
||||
return client.post(
|
||||
f"/api/v1/companies/{company_id}/sources",
|
||||
json={"source_type": "custom_url", "name": "Pricing", "base_url": "https://example.com"},
|
||||
headers=headers,
|
||||
).json()
|
||||
|
||||
|
||||
def test_snapshots_empty_before_any_collection(client):
|
||||
headers = _register_and_login(client)
|
||||
company = _create_company(client, headers)
|
||||
|
||||
resp = client.get(f"/api/v1/companies/{company['id']}/snapshots", headers=headers)
|
||||
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_snapshots_list_newest_first(client, db_session):
|
||||
headers = _register_and_login(client)
|
||||
company = _create_company(client, headers)
|
||||
source = _create_source(client, headers, company["id"])
|
||||
|
||||
older = Snapshot(
|
||||
company_id=uuid.UUID(company["id"]),
|
||||
source_id=uuid.UUID(source["id"]),
|
||||
snapshot_type="website",
|
||||
hash="hash-older",
|
||||
structured_summary={"title": "Old"},
|
||||
text_summary="Old page text",
|
||||
)
|
||||
db_session.add(older)
|
||||
await db_session.commit()
|
||||
|
||||
newer = Snapshot(
|
||||
company_id=uuid.UUID(company["id"]),
|
||||
source_id=uuid.UUID(source["id"]),
|
||||
snapshot_type="website",
|
||||
hash="hash-newer",
|
||||
structured_summary={"title": "New"},
|
||||
text_summary="New page text",
|
||||
)
|
||||
db_session.add(newer)
|
||||
await db_session.commit()
|
||||
|
||||
resp = client.get(f"/api/v1/companies/{company['id']}/snapshots", headers=headers)
|
||||
|
||||
assert resp.status_code == 200
|
||||
body = resp.json()
|
||||
assert len(body) == 2
|
||||
assert body[0]["hash"] == "hash-newer"
|
||||
assert body[1]["hash"] == "hash-older"
|
||||
assert body[0]["text_summary"] == "New page text"
|
||||
|
||||
|
||||
def test_snapshots_scoped_to_owner(client):
|
||||
owner_headers = _register_and_login(client)
|
||||
other_headers = _register_and_login(client)
|
||||
company = _create_company(client, owner_headers)
|
||||
|
||||
resp = client.get(f"/api/v1/companies/{company['id']}/snapshots", headers=other_headers)
|
||||
|
||||
assert resp.status_code == 404
|
||||
Reference in New Issue
Block a user