- 8 DB models (services, incidents, monitors, subscribers, etc.) - Full CRUD API for services, incidents, monitors - Public status page with live data - Incident detail page with timeline - API key authentication - Uptime monitoring scheduler - 13 tests passing - TECHNICAL_DESIGN.md with full spec
154 lines
No EOL
4.3 KiB
Python
154 lines
No EOL
4.3 KiB
Python
"""Test Incidents API endpoints."""
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_incident(client, api_key):
|
|
"""Should create a new incident after creating a service."""
|
|
# Create a service first
|
|
svc = await client.post(
|
|
"/api/v1/services/",
|
|
json={"name": "Auth Service", "slug": "auth-service"},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
assert svc.status_code == 201
|
|
service_id = svc.json()["id"]
|
|
|
|
# Create an incident
|
|
response = await client.post(
|
|
"/api/v1/incidents/",
|
|
json={
|
|
"service_id": service_id,
|
|
"title": "Login failures",
|
|
"status": "investigating",
|
|
"severity": "major",
|
|
},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
assert response.status_code == 201
|
|
data = response.json()
|
|
assert data["title"] == "Login failures"
|
|
assert data["status"] == "investigating"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_incidents(client, api_key):
|
|
"""Should list incidents."""
|
|
response = await client.get("/api/v1/incidents/")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert isinstance(data, list)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_incident_with_updates(client, api_key):
|
|
"""Should get an incident and add an update."""
|
|
# Create a service
|
|
svc = await client.post(
|
|
"/api/v1/services/",
|
|
json={"name": "Storage", "slug": "storage"},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
service_id = svc.json()["id"]
|
|
|
|
# Create an incident
|
|
inc = await client.post(
|
|
"/api/v1/incidents/",
|
|
json={
|
|
"service_id": service_id,
|
|
"title": "Data loss",
|
|
"status": "investigating",
|
|
"severity": "outage",
|
|
},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
incident_id = inc.json()["id"]
|
|
|
|
# Add an update
|
|
upd = await client.post(
|
|
f"/api/v1/incidents/{incident_id}/updates",
|
|
json={
|
|
"status": "identified",
|
|
"body": "We found the root cause.",
|
|
},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
assert upd.status_code == 201
|
|
assert upd.json()["status"] == "identified"
|
|
|
|
# Get the incident - should include updates
|
|
get_resp = await client.get(f"/api/v1/incidents/{incident_id}")
|
|
assert get_resp.status_code == 200
|
|
data = get_resp.json()
|
|
assert data["status"] == "identified"
|
|
assert len(data["updates"]) == 1
|
|
assert data["updates"][0]["body"] == "We found the root cause."
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_incident(client, api_key):
|
|
"""Should update incident status via PATCH."""
|
|
# Create service + incident
|
|
svc = await client.post(
|
|
"/api/v1/services/",
|
|
json={"name": "Cache", "slug": "cache"},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
service_id = svc.json()["id"]
|
|
|
|
inc = await client.post(
|
|
"/api/v1/incidents/",
|
|
json={
|
|
"service_id": service_id,
|
|
"title": "Slow responses",
|
|
"status": "investigating",
|
|
"severity": "minor",
|
|
},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
incident_id = inc.json()["id"]
|
|
|
|
# Patch the incident
|
|
patch_resp = await client.patch(
|
|
f"/api/v1/incidents/{incident_id}",
|
|
json={"status": "resolved"},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
assert patch_resp.status_code == 200
|
|
data = patch_resp.json()
|
|
assert data["status"] == "resolved"
|
|
assert data["resolved_at"] is not None
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_incident(client, api_key):
|
|
"""Should delete an incident."""
|
|
svc = await client.post(
|
|
"/api/v1/services/",
|
|
json={"name": "Email", "slug": "email-svc"},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
service_id = svc.json()["id"]
|
|
|
|
inc = await client.post(
|
|
"/api/v1/incidents/",
|
|
json={
|
|
"service_id": service_id,
|
|
"title": "Emails delayed",
|
|
"status": "monitoring",
|
|
"severity": "minor",
|
|
},
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
incident_id = inc.json()["id"]
|
|
|
|
del_resp = await client.delete(
|
|
f"/api/v1/incidents/{incident_id}",
|
|
headers={"X-API-Key": api_key},
|
|
)
|
|
assert del_resp.status_code == 204
|
|
|
|
# Verify it's gone
|
|
get_resp = await client.get(f"/api/v1/incidents/{incident_id}")
|
|
assert get_resp.status_code == 404 |