""" End-to-end tests for the OpenAPI-first Veterinary Clinic example app. These tests validate that all CRUD operations behave correctly against the in-memory mock data store using Pydantic models. """ from fastapi.testclient import TestClient from main import app from openapi_first.loader import load_openapi from openapi_first.client import OpenAPIClient test_client = TestClient(app) spec = load_openapi("openapi.yaml") client = OpenAPIClient( spec=spec, base_url="http://testserver", client=test_client, ) # Bootstrap CSRF token via a safe GET request _ = client.list_parents(query={"limit": 1}) _CSRF_TOKEN = client.client.cookies.get("csrftoken") def _csrf_headers() -> dict: return {"X-CSRFToken": _CSRF_TOKEN} if _CSRF_TOKEN else {} def test_list_parents(): """List parents returns paginated response.""" response = client.list_parents(query={"limit": 10, "offset": 0}) assert response.status_code == 200 data = response.json() assert "total" in data assert "items" in data def test_create_parent(): """Creating a parent returns 201 with the created entity.""" payload = {"name": "Alice", "email": "alice@example.com"} response = client.create_parent(body=payload, headers=_csrf_headers()) assert response.status_code == 201 parent = response.json() assert parent["name"] == "Alice" assert "id" in parent def test_get_parent(): """Get parent by ID returns the entity.""" parent = client.create_parent(body={"name": "Bob", "email": "bob@example.com"}, headers=_csrf_headers()).json() response = client.get_parent(path_params={"id": parent["id"]}) assert response.status_code == 200 assert response.json()["name"] == "Bob" def test_update_parent(): """Update parent replaces its values.""" parent = client.create_parent(body={"name": "Carol", "email": "carol@example.com"}, headers=_csrf_headers()).json() payload = {"name": "Carol Smith", "email": "carol.smith@example.com"} response = client.update_parent(path_params={"id": parent["id"]}, body=payload, headers=_csrf_headers()) assert response.status_code == 200 assert response.json()["name"] == "Carol Smith" def test_delete_parent(): """Delete parent returns 204 and removes the entity.""" parent = client.create_parent(body={"name": "Dave", "email": "dave@example.com"}, headers=_csrf_headers()).json() response = client.delete_parent(path_params={"id": parent["id"]}, headers=_csrf_headers()) assert response.status_code == 204 def test_list_vets(): """List vets returns paginated response.""" response = client.list_vets(query={"limit": 10, "offset": 0}) assert response.status_code == 200 data = response.json() assert "total" in data assert "items" in data def test_create_vet(): """Creating a vet returns 201.""" payload = {"name": "Dr. Smith", "specialty": "Surgery", "email": "smith@clinic.com"} response = client.create_vet(body=payload, headers=_csrf_headers()) assert response.status_code == 201 assert response.json()["name"] == "Dr. Smith" def test_list_treatments(): """List treatments returns an array.""" response = client.list_treatments() assert response.status_code == 200 assert isinstance(response.json(), list) def test_create_treatment(): """Creating a treatment returns 201.""" payload = {"label": "Vaccination", "description": "Annual vaccination"} response = client.create_treatment(body=payload, headers=_csrf_headers()) assert response.status_code == 201 assert response.json()["label"] == "Vaccination" def test_create_pet(): """Creating a pet links FK references.""" parent = client.create_parent(body={"name": "Owner", "email": "owner@example.com"}, headers=_csrf_headers()).json() payload = {"name": "Fido", "species": "dog", "parent_ids": [parent["id"]]} response = client.create_pet(body=payload, headers=_csrf_headers()) assert response.status_code == 201 assert response.json()["name"] == "Fido" def test_upload_pet_photo(): """Upload pet photo returns 200.""" pet = client.create_pet(body={"name": "PhotoPet", "species": "cat", "parent_ids": []}, headers=_csrf_headers()).json() response = client.client.post( f"http://testserver/pets/{pet['id']}", files={"file": ("test.jpg", b"fake-image-data", "image/jpeg")}, headers=_csrf_headers(), ) assert response.status_code == 200 def test_list_appointments(): """List appointments returns paginated response with filter params.""" response = client.list_appointments(query={"limit": 10, "offset": 0}) assert response.status_code == 200 data = response.json() assert "total" in data assert "items" in data def test_full_appointment_lifecycle(): """Create a parent, vet, treatment, pet, then an appointment.""" parent = client.create_parent(body={"name": "Eve", "email": "eve@example.com"}, headers=_csrf_headers()).json() vet = client.create_vet(body={"name": "Dr. Jones", "specialty": "Dentistry", "email": "jones@clinic.com"}, headers=_csrf_headers()).json() treatment = client.create_treatment(body={"label": "Cleaning", "description": "Teeth cleaning"}, headers=_csrf_headers()).json() pet = client.create_pet(body={"name": "Max", "species": "dog", "parent_ids": [parent["id"]]}, headers=_csrf_headers()).json() payload = { "date": "2025-06-01T10:00:00", "pet_id": pet["id"], "vet_id": vet["id"], "treatment_id": treatment["id"], } response = client.create_appointment(body=payload, headers=_csrf_headers()) assert response.status_code == 201 appointment = response.json() assert appointment["pet_id"] == pet["id"] # Fetch it back get_resp = client.get_appointment(path_params={"id": appointment["id"]}) assert get_resp.status_code == 200 # Delete it del_resp = client.delete_appointment(path_params={"id": appointment["id"]}, headers=_csrf_headers()) assert del_resp.status_code == 204