schedule-manager / backend /tests /test_api.py
Jessedbrown's picture
build class schedule manager
e310cf5
Raw History Blame Contribute Delete
7.7 kB
"""Tests for API endpoints."""
from datetime import date, time
import pytest
class TestHealthEndpoints:
"""Test health check endpoints."""
def test_root_endpoint(self, client):
"""Root endpoint should return OK status."""
response = client.get("/")
assert response.status_code == 200
assert response.json()["status"] == "ok"
def test_health_endpoint(self, client):
"""Health endpoint should return healthy status."""
response = client.get("/health")
assert response.status_code == 200
assert response.json()["status"] == "healthy"
class TestLookupEndpoints:
"""Test lookup API endpoints."""
def test_get_rooms(self, client, seed_data):
"""Should return all rooms."""
response = client.get("/rooms")
assert response.status_code == 200
rooms = response.json()
assert len(rooms) == 3
assert all("name" in r and "capacity" in r for r in rooms)
def test_get_instructors(self, client, seed_data):
"""Should return all instructors."""
response = client.get("/instructors")
assert response.status_code == 200
instructors = response.json()
assert len(instructors) == 2
def test_get_students(self, client, seed_data):
"""Should return all students."""
response = client.get("/students")
assert response.status_code == 200
students = response.json()
assert len(students) == 10
class TestClassCRUD:
"""Test class CRUD operations."""
def test_create_class(self, client, seed_data):
"""Should create a new class."""
response = client.post("/classes", json={
"course_name": "Test Course",
"chapter_topic": "Test Topic",
"date": "2024-01-15",
"start_time": "10:00:00",
"end_time": "11:30:00",
"room_id": 1,
"instructor_id": 1,
"student_ids": [1, 2, 3],
})
assert response.status_code == 201
data = response.json()
assert data["course_name"] == "Test Course"
assert len(data["students"]) == 3
def test_get_classes_by_date(self, client, seed_data):
"""Should return classes for a specific date."""
# First create a class
client.post("/classes", json={
"course_name": "Test Course",
"chapter_topic": "Test Topic",
"date": "2024-01-15",
"start_time": "10:00:00",
"end_time": "11:30:00",
"room_id": 1,
"instructor_id": 1,
"student_ids": [],
})
response = client.get("/classes?date=2024-01-15")
assert response.status_code == 200
classes = response.json()
assert len(classes) == 1
def test_update_class(self, client, seed_data):
"""Should update an existing class."""
# Create
create_response = client.post("/classes", json={
"course_name": "Original Name",
"chapter_topic": "Original Topic",
"date": "2024-01-15",
"start_time": "10:00:00",
"end_time": "11:30:00",
"room_id": 1,
"instructor_id": 1,
"student_ids": [],
})
class_id = create_response.json()["id"]
# Update
update_response = client.put(f"/classes/{class_id}", json={
"course_name": "Updated Name",
"chapter_topic": "Updated Topic",
"date": "2024-01-15",
"start_time": "10:00:00",
"end_time": "11:30:00",
"room_id": 1,
"instructor_id": 1,
"student_ids": [1],
})
assert update_response.status_code == 200
assert update_response.json()["course_name"] == "Updated Name"
assert len(update_response.json()["students"]) == 1
def test_delete_class(self, client, seed_data):
"""Should delete a class."""
# Create
create_response = client.post("/classes", json={
"course_name": "To Delete",
"chapter_topic": "Topic",
"date": "2024-01-15",
"start_time": "10:00:00",
"end_time": "11:30:00",
"room_id": 1,
"instructor_id": 1,
"student_ids": [],
})
class_id = create_response.json()["id"]
# Delete
delete_response = client.delete(f"/classes/{class_id}")
assert delete_response.status_code == 204
# Verify deleted
get_response = client.get(f"/classes/{class_id}")
assert get_response.status_code == 404
class TestConflictAPI:
"""Test conflict detection via API."""
def test_room_conflict_returns_409(self, client, seed_data):
"""Creating a class with room conflict should return 409."""
# Create first class
client.post("/classes", json={
"course_name": "First Class",
"chapter_topic": "Topic",
"date": "2024-01-15",
"start_time": "10:00:00",
"end_time": "11:30:00",
"room_id": 1,
"instructor_id": 1,
"student_ids": [],
})
# Try to create conflicting class
response = client.post("/classes", json={
"course_name": "Conflicting Class",
"chapter_topic": "Topic",
"date": "2024-01-15",
"start_time": "11:00:00", # Overlaps
"end_time": "12:30:00",
"room_id": 1, # Same room
"instructor_id": 2, # Different instructor
"student_ids": [],
})
assert response.status_code == 409
detail = response.json()["detail"]
assert detail["error"] == "conflict"
assert any(c["type"] == "room" for c in detail["conflicts"])
def test_adjacent_times_no_conflict(self, client, seed_data):
"""Adjacent times should not conflict."""
# Create first class
client.post("/classes", json={
"course_name": "First Class",
"chapter_topic": "Topic",
"date": "2024-01-15",
"start_time": "10:00:00",
"end_time": "11:00:00",
"room_id": 1,
"instructor_id": 1,
"student_ids": [],
})
# Create adjacent class (should succeed)
response = client.post("/classes", json={
"course_name": "Adjacent Class",
"chapter_topic": "Topic",
"date": "2024-01-15",
"start_time": "11:00:00", # Starts exactly when first ends
"end_time": "12:00:00",
"room_id": 1, # Same room
"instructor_id": 1, # Same instructor
"student_ids": [],
})
assert response.status_code == 201
def test_capacity_conflict_returns_409(self, client, seed_data):
"""Creating a class with too many students should return 409."""
response = client.post("/classes", json={
"course_name": "Overcrowded Class",
"chapter_topic": "Topic",
"date": "2024-01-15",
"start_time": "10:00:00",
"end_time": "11:30:00",
"room_id": 3, # Small Room with capacity=5
"instructor_id": 1,
"student_ids": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], # 10 students
})
assert response.status_code == 409
detail = response.json()["detail"]
assert any(c["type"] == "capacity" for c in detail["conflicts"])