coming together
This commit is contained in:
168
tests/test_customers_edge_cases.py
Normal file
168
tests/test_customers_edge_cases.py
Normal file
@@ -0,0 +1,168 @@
|
||||
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")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user