import os import uuid from datetime import date import pytest from fastapi.testclient import TestClient os.environ.setdefault("SECRET_KEY", "x" * 32) os.environ.setdefault("DATABASE_URL", "sqlite:////tmp/delphi_test.sqlite") from app.main import app # noqa: E402 from app.auth.security import get_current_user, get_admin_user # noqa: E402 class _User: def __init__(self, admin: bool = False): self.id = 1 self.username = "tester" self.is_admin = admin self.is_active = True @pytest.fixture() def client(): app.dependency_overrides[get_current_user] = lambda: _User(True) app.dependency_overrides[get_admin_user] = lambda: _User(True) try: yield TestClient(app) finally: app.dependency_overrides.pop(get_current_user, None) app.dependency_overrides.pop(get_admin_user, None) def _create_customer(client: TestClient) -> str: cid = f"PGN-{uuid.uuid4().hex[:8]}" resp = client.post("/api/customers/", json={"id": cid, "last": "Paginate", "email": f"{cid}@ex.com"}) assert resp.status_code == 200 return cid def test_files_include_total_shape(client: TestClient): owner_id = _create_customer(client) for _ in range(2): fno = f"P-{uuid.uuid4().hex[:6]}" payload = { "file_no": fno, "id": owner_id, "regarding": "Pagination Test", "empl_num": "E01", "file_type": "CIVIL", "opened": date.today().isoformat(), "status": "ACTIVE", "rate_per_hour": 100.0, } resp = client.post("/api/files/", json=payload) assert resp.status_code == 200 resp = client.get("/api/files/", params={"include_total": True, "limit": 1}) assert resp.status_code == 200 body = resp.json() assert set(body.keys()) == {"items", "total"} assert isinstance(body["items"], list) assert body["total"] >= len(body["items"]) >= 1 def test_templates_include_total_shape(client: TestClient): tid = f"PGT-{uuid.uuid4().hex[:6]}" resp = client.post( "/api/documents/templates/", json={"form_id": tid, "form_name": "TName", "category": "GENERAL", "content": "C"}, ) assert resp.status_code == 200 resp = client.get("/api/documents/templates/", params={"include_total": True, "limit": 1}) assert resp.status_code == 200 body = resp.json() assert set(body.keys()) == {"items", "total"} assert isinstance(body["items"], list) def test_users_include_total_shape(client: TestClient): # Admin endpoint: just validate shape resp = client.get("/api/admin/users", params={"include_total": True, "limit": 1}) assert resp.status_code == 200 body = resp.json() assert set(body.keys()) == {"items", "total"} assert isinstance(body["items"], list) def test_support_tickets_include_total_shape(client: TestClient): # Ensure at least one ticket exists payload = { "subject": "Pagination test subject", "description": "A sufficiently long description for validation.", "category": "bug_report", "priority": "medium", "contact_name": "Tester", "contact_email": "tester@example.com", } resp = client.post("/api/support/tickets", json=payload) assert resp.status_code == 200 # Validate include_total shape resp = client.get("/api/support/tickets", params={"include_total": True, "limit": 1}) assert resp.status_code == 200 body = resp.json() assert set(body.keys()) == {"items", "total"} assert isinstance(body["items"], list) assert body["total"] >= len(body["items"]) >= 0 def test_my_support_tickets_include_total_shape(client: TestClient): # Even if empty, should return the same shape resp = client.get("/api/support/my-tickets", params={"include_total": True, "limit": 1}) assert resp.status_code == 200 body = resp.json() assert set(body.keys()) == {"items", "total"} assert isinstance(body["items"], list) assert body["total"] >= 0 def test_qdros_by_file_include_total_shape(client: TestClient): # Create minimal file and a qdro import uuid owner_id = _create_customer(client) fno = f"P-{uuid.uuid4().hex[:6]}" resp = client.post( "/api/files/", json={ "file_no": fno, "id": owner_id, "regarding": "QDRO Pagination Test", "empl_num": "E01", "file_type": "CIVIL", "opened": date.today().isoformat(), "status": "ACTIVE", "rate_per_hour": 100.0, }, ) assert resp.status_code == 200 resp = client.post( "/api/documents/qdros/", json={"file_no": fno, "form_name": "FormX", "status": "DRAFT"}, ) assert resp.status_code == 200 # Validate include_total on file-specific qdros resp = client.get(f"/api/documents/qdros/{fno}", params={"include_total": True, "limit": 1}) assert resp.status_code == 200 body = resp.json() assert set(body.keys()) == {"items", "total"} assert isinstance(body["items"], list) def test_ledger_by_file_include_total_shape(client: TestClient): # Create minimal file and a ledger entry via financial quick helper import uuid owner_id = _create_customer(client) fno = f"P-{uuid.uuid4().hex[:6]}" resp = client.post( "/api/files/", json={ "file_no": fno, "id": owner_id, "regarding": "Ledger Pagination Test", "empl_num": "E01", "file_type": "CIVIL", "opened": date.today().isoformat(), "status": "ACTIVE", "rate_per_hour": 100.0, }, ) assert resp.status_code == 200 # Quick time entry resp = client.post( "/api/financial/time-entry/quick", params={"file_no": fno, "hours": 1.5, "description": "Work"}, ) assert resp.status_code == 200 # Validate include_total on file ledger resp = client.get(f"/api/financial/ledger/{fno}", params={"include_total": True, "limit": 1}) assert resp.status_code == 200 body = resp.json() assert set(body.keys()) == {"items", "total"} assert isinstance(body["items"], list) def test_customer_phones_include_total_shape(client: TestClient): # Create customer and a couple of phones owner_id = _create_customer(client) for ph in ["555-1000", "555-1001"]: resp = client.post(f"/api/customers/{owner_id}/phones", json={"phone": ph, "location": "Home"}) assert resp.status_code == 200 resp = client.get(f"/api/customers/{owner_id}/phones", params={"include_total": True, "limit": 1}) assert resp.status_code == 200 body = resp.json() assert set(body.keys()) == {"items", "total"} assert isinstance(body["items"], list)