Files
delphi-database/tests/test_customers_edge_cases.py
2025-08-13 18:53:35 -05:00

169 lines
5.4 KiB
Python

import os
import uuid
import pytest
from fastapi.testclient import TestClient
# Ensure required env vars for app import/config
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 # noqa: E402
@pytest.fixture(scope="module")
def client():
# Override auth to bypass JWT for these tests
class _User:
def __init__(self):
self.id = "test"
self.username = "tester"
self.is_admin = True
self.is_active = True
app.dependency_overrides[get_current_user] = lambda: _User()
try:
yield TestClient(app)
finally:
app.dependency_overrides.pop(get_current_user, None)
def _assert_validation_error(resp, field_name: str):
assert resp.status_code == 422
body = resp.json()
assert body.get("success") is False
assert body.get("error", {}).get("code") == "validation_error"
# Ensure correlation id is present and echoed in header
cid = body.get("correlation_id")
assert isinstance(cid, str) and cid
assert resp.headers.get("X-Correlation-ID") == cid
# Ensure the field appears in details
details = body.get("error", {}).get("details", [])
assert any(field_name in ":".join(map(str, err.get("loc", []))) for err in details)
def _assert_http_error(resp, status_code: int, message_substr: str):
assert resp.status_code == status_code
body = resp.json()
assert body.get("success") is False
assert body.get("error", {}).get("code") == "http_error"
assert message_substr in body.get("error", {}).get("message", "")
cid = body.get("correlation_id")
assert isinstance(cid, str) and cid
assert resp.headers.get("X-Correlation-ID") == cid
def test_create_customer_invalid_email_returns_422(client: TestClient):
customer_id = f"SCHEMA-{uuid.uuid4().hex[:8]}"
payload = {
"id": customer_id,
"last": "InvalidEmail",
"email": "not-an-email",
}
resp = client.post("/api/customers/", json=payload)
_assert_validation_error(resp, "email")
def test_update_customer_invalid_email_returns_422(client: TestClient):
customer_id = f"SCHEMA-UPD-{uuid.uuid4().hex[:8]}"
# Create valid customer first
create_payload = {
"id": customer_id,
"last": "Valid",
"email": "ok@example.com",
}
resp = client.post("/api/customers/", json=create_payload)
assert resp.status_code == 200
# Attempt invalid email on update
resp = client.put(f"/api/customers/{customer_id}", json={"email": "bad"})
_assert_validation_error(resp, "email")
# Cleanup
resp = client.delete(f"/api/customers/{customer_id}")
assert resp.status_code == 200
def test_create_customer_duplicate_id_returns_400(client: TestClient):
customer_id = f"DUP-{uuid.uuid4().hex[:8]}"
payload = {
"id": customer_id,
"last": "Doe",
"email": "john.doe@example.com",
}
# First create OK
resp = client.post("/api/customers/", json=payload)
assert resp.status_code == 200
# Duplicate should be 400 with envelope
resp = client.post("/api/customers/", json=payload)
_assert_http_error(resp, 400, "Customer ID already exists")
# Cleanup
resp = client.delete(f"/api/customers/{customer_id}")
assert resp.status_code == 200
def test_get_update_delete_nonexistent_customer_404(client: TestClient):
missing_id = f"NOPE-{uuid.uuid4().hex[:8]}"
resp = client.get(f"/api/customers/{missing_id}")
_assert_http_error(resp, 404, "Customer not found")
resp = client.put(f"/api/customers/{missing_id}", json={"last": "X"})
_assert_http_error(resp, 404, "Customer not found")
resp = client.delete(f"/api/customers/{missing_id}")
_assert_http_error(resp, 404, "Customer not found")
def test_phones_endpoints_404_for_missing_customer_and_phone(client: TestClient):
missing_id = f"NOPE-{uuid.uuid4().hex[:8]}"
# Missing customer: get and add phone
resp = client.get(f"/api/customers/{missing_id}/phones")
_assert_http_error(resp, 404, "Customer not found")
resp = client.post(
f"/api/customers/{missing_id}/phones",
json={"location": "Office", "phone": "(555) 000-0000"},
)
_assert_http_error(resp, 404, "Customer not found")
# Create a real customer to test non-existent phone id
real_id = f"PHONE-{uuid.uuid4().hex[:8]}"
resp = client.post(
"/api/customers/",
json={"id": real_id, "last": "Phones", "email": "phones@example.com"},
)
assert resp.status_code == 200
# Update non-existent phone for this customer
resp = client.put(
f"/api/customers/{real_id}/phones/999999",
json={"location": "Home", "phone": "(555) 111-2222"},
)
_assert_http_error(resp, 404, "Phone number not found")
# Delete non-existent phone for this customer
resp = client.delete(f"/api/customers/{real_id}/phones/999999")
_assert_http_error(resp, 404, "Phone number not found")
# Cleanup
resp = client.delete(f"/api/customers/{real_id}")
assert resp.status_code == 200
def test_list_customers_query_param_validation_422(client: TestClient):
# limit must be >=1 and <=200
resp = client.get("/api/customers/?limit=0")
_assert_validation_error(resp, "limit")
# skip must be >=0
resp = client.get("/api/customers/?skip=-1")
_assert_validation_error(resp, "skip")