schedule-manager / backend /tests /test_conflicts.py
Jessedbrown's picture
build class schedule manager
e310cf5
Raw History Blame Contribute Delete
10.8 kB
"""Tests for conflict detection logic."""
from datetime import date, time
import pytest
from app.models import Class, ClassEnrollment
from app.services.conflicts import (
detect_conflicts,
detect_room_conflicts,
detect_instructor_conflicts,
detect_student_conflicts,
detect_capacity_conflict,
)
class TestTimeOverlapLogic:
"""Test the time overlap detection logic."""
def test_overlapping_times_conflict(self, db, seed_data):
"""Class A: 10:00-11:30, Class B: 11:00-12:30 β†’ CONFLICT"""
rooms = seed_data["rooms"]
instructors = seed_data["instructors"]
# Create existing class
existing = Class(
course_name="Existing Class",
chapter_topic="Topic",
date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
room_id=rooms[0].id,
instructor_id=instructors[0].id,
)
db.add(existing)
db.commit()
# Check for room conflict with overlapping time
conflicts = detect_room_conflicts(
db=db,
room_id=rooms[0].id,
class_date=date(2024, 1, 15),
start_time=time(11, 0),
end_time=time(12, 30),
)
assert len(conflicts) == 1
assert conflicts[0].type == "room"
def test_adjacent_times_no_conflict(self, db, seed_data):
"""Class A: 10:00-11:00, Class B: 11:00-12:00 β†’ NO CONFLICT"""
rooms = seed_data["rooms"]
instructors = seed_data["instructors"]
# Create existing class
existing = Class(
course_name="Existing Class",
chapter_topic="Topic",
date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 0),
room_id=rooms[0].id,
instructor_id=instructors[0].id,
)
db.add(existing)
db.commit()
# Check for room conflict with adjacent time (should not conflict)
conflicts = detect_room_conflicts(
db=db,
room_id=rooms[0].id,
class_date=date(2024, 1, 15),
start_time=time(11, 0),
end_time=time(12, 0),
)
assert len(conflicts) == 0
def test_identical_times_conflict(self, db, seed_data):
"""Class A: 10:00-11:30, Class B: 10:00-11:30 β†’ CONFLICT"""
rooms = seed_data["rooms"]
instructors = seed_data["instructors"]
# Create existing class
existing = Class(
course_name="Existing Class",
chapter_topic="Topic",
date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
room_id=rooms[0].id,
instructor_id=instructors[0].id,
)
db.add(existing)
db.commit()
# Check for room conflict with identical time
conflicts = detect_room_conflicts(
db=db,
room_id=rooms[0].id,
class_date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
)
assert len(conflicts) == 1
class TestRoomConflicts:
"""Test room conflict detection."""
def test_different_room_no_conflict(self, db, seed_data):
"""Same time, different room β†’ NO CONFLICT"""
rooms = seed_data["rooms"]
instructors = seed_data["instructors"]
existing = Class(
course_name="Existing Class",
chapter_topic="Topic",
date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
room_id=rooms[0].id,
instructor_id=instructors[0].id,
)
db.add(existing)
db.commit()
conflicts = detect_room_conflicts(
db=db,
room_id=rooms[1].id, # Different room
class_date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
)
assert len(conflicts) == 0
def test_different_date_no_conflict(self, db, seed_data):
"""Same room, same time, different date β†’ NO CONFLICT"""
rooms = seed_data["rooms"]
instructors = seed_data["instructors"]
existing = Class(
course_name="Existing Class",
chapter_topic="Topic",
date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
room_id=rooms[0].id,
instructor_id=instructors[0].id,
)
db.add(existing)
db.commit()
conflicts = detect_room_conflicts(
db=db,
room_id=rooms[0].id,
class_date=date(2024, 1, 16), # Different date
start_time=time(10, 0),
end_time=time(11, 30),
)
assert len(conflicts) == 0
class TestInstructorConflicts:
"""Test instructor conflict detection."""
def test_instructor_conflict(self, db, seed_data):
"""Same instructor, overlapping time β†’ CONFLICT"""
rooms = seed_data["rooms"]
instructors = seed_data["instructors"]
existing = Class(
course_name="Existing Class",
chapter_topic="Topic",
date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
room_id=rooms[0].id,
instructor_id=instructors[0].id,
)
db.add(existing)
db.commit()
conflicts = detect_instructor_conflicts(
db=db,
instructor_id=instructors[0].id,
class_date=date(2024, 1, 15),
start_time=time(11, 0),
end_time=time(12, 30),
)
assert len(conflicts) == 1
assert conflicts[0].type == "instructor"
def test_different_instructor_no_conflict(self, db, seed_data):
"""Different instructor, same time β†’ NO CONFLICT"""
rooms = seed_data["rooms"]
instructors = seed_data["instructors"]
existing = Class(
course_name="Existing Class",
chapter_topic="Topic",
date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
room_id=rooms[0].id,
instructor_id=instructors[0].id,
)
db.add(existing)
db.commit()
conflicts = detect_instructor_conflicts(
db=db,
instructor_id=instructors[1].id, # Different instructor
class_date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
)
assert len(conflicts) == 0
class TestStudentConflicts:
"""Test student conflict detection."""
def test_student_conflict(self, db, seed_data):
"""Student enrolled in overlapping class β†’ CONFLICT"""
rooms = seed_data["rooms"]
instructors = seed_data["instructors"]
students = seed_data["students"]
existing = Class(
course_name="Existing Class",
chapter_topic="Topic",
date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
room_id=rooms[0].id,
instructor_id=instructors[0].id,
)
db.add(existing)
db.flush()
# Enroll student
enrollment = ClassEnrollment(class_id=existing.id, student_id=students[0].id)
db.add(enrollment)
db.commit()
conflicts = detect_student_conflicts(
db=db,
student_ids=[students[0].id],
class_date=date(2024, 1, 15),
start_time=time(11, 0),
end_time=time(12, 30),
)
assert len(conflicts) == 1
assert conflicts[0].type == "student"
def test_empty_students_no_conflict(self, db, seed_data):
"""Empty student list β†’ NO CONFLICT"""
conflicts = detect_student_conflicts(
db=db,
student_ids=[],
class_date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
)
assert len(conflicts) == 0
class TestCapacityConflicts:
"""Test room capacity conflict detection."""
def test_over_capacity_conflict(self, db, seed_data):
"""More students than room capacity β†’ CONFLICT"""
rooms = seed_data["rooms"]
small_room = rooms[2] # capacity=5
conflicts = detect_capacity_conflict(
db=db,
room_id=small_room.id,
student_count=10,
)
assert len(conflicts) == 1
assert conflicts[0].type == "capacity"
def test_within_capacity_no_conflict(self, db, seed_data):
"""Students within room capacity β†’ NO CONFLICT"""
rooms = seed_data["rooms"]
conflicts = detect_capacity_conflict(
db=db,
room_id=rooms[0].id, # capacity=30
student_count=25,
)
assert len(conflicts) == 0
class TestMultipleConflicts:
"""Test that multiple conflicts are detected simultaneously."""
def test_multiple_conflicts_detected(self, db, seed_data):
"""Should detect room, instructor, and student conflicts together."""
rooms = seed_data["rooms"]
instructors = seed_data["instructors"]
students = seed_data["students"]
existing = Class(
course_name="Existing Class",
chapter_topic="Topic",
date=date(2024, 1, 15),
start_time=time(10, 0),
end_time=time(11, 30),
room_id=rooms[0].id,
instructor_id=instructors[0].id,
)
db.add(existing)
db.flush()
enrollment = ClassEnrollment(class_id=existing.id, student_id=students[0].id)
db.add(enrollment)
db.commit()
# Try to create a class that conflicts on all fronts
conflicts = detect_conflicts(
db=db,
room_id=rooms[0].id, # Same room
instructor_id=instructors[0].id, # Same instructor
student_ids=[students[0].id], # Same student
class_date=date(2024, 1, 15),
start_time=time(10, 30),
end_time=time(12, 0),
)
# Should have room, instructor, and student conflicts
conflict_types = {c.type for c in conflicts}
assert "room" in conflict_types
assert "instructor" in conflict_types
assert "student" in conflict_types