128 lines
4.4 KiB
Python
128 lines
4.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, get_admin_user # noqa: E402
|
|
from tests.helpers import assert_validation_error, assert_http_error # noqa: E402
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def client():
|
|
class _Admin:
|
|
def __init__(self):
|
|
self.id = 1
|
|
self.username = "admin"
|
|
self.is_admin = True
|
|
self.is_active = True
|
|
self.first_name = "Admin"
|
|
self.last_name = "User"
|
|
|
|
# For public create, current_user is optional; override admin endpoints
|
|
app.dependency_overrides[get_admin_user] = lambda: _Admin()
|
|
app.dependency_overrides[get_current_user] = lambda: _Admin()
|
|
|
|
try:
|
|
yield TestClient(app)
|
|
finally:
|
|
app.dependency_overrides.pop(get_admin_user, None)
|
|
app.dependency_overrides.pop(get_current_user, None)
|
|
|
|
|
|
def test_create_ticket_validation_errors(client: TestClient):
|
|
# Missing required fields
|
|
resp = client.post("/api/support/tickets", json={})
|
|
assert_validation_error(resp, "subject")
|
|
|
|
# Too short subject/description and invalid email
|
|
payload = {
|
|
"subject": "Hey",
|
|
"description": "short",
|
|
"contact_name": "",
|
|
"contact_email": "not-an-email",
|
|
}
|
|
resp = client.post("/api/support/tickets", json=payload)
|
|
assert_validation_error(resp, "subject")
|
|
assert_validation_error(resp, "description")
|
|
assert_validation_error(resp, "contact_name")
|
|
assert_validation_error(resp, "contact_email")
|
|
|
|
|
|
def _valid_ticket_payload() -> dict:
|
|
token = uuid.uuid4().hex[:6]
|
|
return {
|
|
"subject": f"Support issue {token}",
|
|
"description": "A reproducible problem description long enough",
|
|
"category": "bug_report",
|
|
"priority": "medium",
|
|
"contact_name": "John Tester",
|
|
"contact_email": f"john.{token}@example.com",
|
|
"current_page": "/dashboard",
|
|
"browser_info": "pytest-agent",
|
|
}
|
|
|
|
|
|
def test_ticket_lifecycle_and_404s_with_audit(client: TestClient):
|
|
# Create ticket (public)
|
|
payload = _valid_ticket_payload()
|
|
resp = client.post("/api/support/tickets", json=payload)
|
|
assert resp.status_code == 200
|
|
body = resp.json()
|
|
ticket_id = body["ticket_id"]
|
|
assert body["status"] == "created"
|
|
|
|
# Get ticket as admin
|
|
resp = client.get(f"/api/support/tickets/{ticket_id}")
|
|
assert resp.status_code == 200
|
|
detail = resp.json()
|
|
assert detail["status"] == "open"
|
|
assert isinstance(detail.get("responses"), list)
|
|
|
|
# 404 on missing ticket get/update/respond
|
|
resp = client.get("/api/support/tickets/999999")
|
|
assert_http_error(resp, 404, "Ticket not found")
|
|
resp = client.put("/api/support/tickets/999999", json={"status": "in_progress"})
|
|
assert_http_error(resp, 404, "Ticket not found")
|
|
resp = client.post("/api/support/tickets/999999/responses", json={"message": "x"})
|
|
assert_http_error(resp, 404, "Ticket not found")
|
|
|
|
# State transitions: open -> in_progress -> resolved
|
|
resp = client.put(f"/api/support/tickets/{ticket_id}", json={"status": "in_progress"})
|
|
assert resp.status_code == 200
|
|
resp = client.get(f"/api/support/tickets/{ticket_id}")
|
|
assert resp.status_code == 200
|
|
assert resp.json()["status"] == "in_progress"
|
|
|
|
# Add public response
|
|
resp = client.post(
|
|
f"/api/support/tickets/{ticket_id}/responses",
|
|
json={"message": "We are working on it", "is_internal": False},
|
|
)
|
|
assert resp.status_code == 200
|
|
|
|
# Resolve ticket
|
|
resp = client.put(f"/api/support/tickets/{ticket_id}", json={"status": "resolved"})
|
|
assert resp.status_code == 200
|
|
resp = client.get(f"/api/support/tickets/{ticket_id}")
|
|
data = resp.json()
|
|
assert data["status"] == "resolved"
|
|
assert data["resolved_at"] is not None
|
|
|
|
# Basic list with pagination params should 200
|
|
resp = client.get("/api/support/tickets", params={"skip": 0, "limit": 10})
|
|
assert resp.status_code == 200
|
|
assert isinstance(resp.json(), list)
|
|
|
|
# Search should filter results
|
|
resp = client.get("/api/support/tickets", params={"search": "Support issue"})
|
|
assert resp.status_code == 200
|
|
assert isinstance(resp.json(), list)
|
|
|
|
|