"""Regression test for question ordering returned by the admin endpoint. Locks in the guarantee that ``Test.questions`` is loaded ordered by ``Question.order_index`` (declared on the relationship in ``app.models.models``). If that ``order_by`` is ever removed, this test will fail — protecting the ``get_questions`` endpoint which relies on it after the optimization that removed an in-Python ``sorted(...)`` call. """ import unittest from fastapi import FastAPI from fastapi.testclient import TestClient from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import StaticPool from app.api.deps import require_admin from app.api.routes.admin import router from app.core.database import Base, get_db from app.models.models import Question, QuestionType, Test, User, UserRole class AdminGetQuestionsOrderingTests(unittest.TestCase): def setUp(self): self.engine = create_engine( "sqlite:///:memory:", connect_args={"check_same_thread": False}, poolclass=StaticPool, ) # Creates the full schema including Question.order_index, since the # production model is imported above and Base is the shared metadata. Base.metadata.create_all(self.engine) self.SessionLocal = sessionmaker(bind=self.engine) # Seed an admin user and a Test with questions inserted in REVERSE # order_index so a missing ORDER BY would produce [5, 3, 1]. db = self.SessionLocal() try: self.admin = User( email="admin@example.com", full_name="Admin", role=UserRole.admin, ) self.test = Test( title="Ordering test", created_by=1, total_marks=0.0 ) db.add_all([self.admin, self.test]) db.commit() db.refresh(self.admin) db.refresh(self.test) self.test_id = self.test.id for order_index, text in [(5, "Q-five"), (1, "Q-one"), (3, "Q-three")]: db.add( Question( test_id=self.test_id, question_type=QuestionType.mcq, question_text=text, options=["A", "B", "C", "D"], correct_answer="A", marks=1.0, negative_marks=0.0, order_index=order_index, ) ) db.commit() finally: db.close() app = FastAPI() app.include_router(router) def override_get_db(): session = self.SessionLocal() try: yield session finally: session.close() def override_require_admin(): return self.admin app.dependency_overrides[get_db] = override_get_db app.dependency_overrides[require_admin] = override_require_admin self.client = TestClient(app, raise_server_exceptions=False) def test_get_questions_returns_questions_sorted_by_order_index(self): response = self.client.get(f"/admin/tests/{self.test_id}/questions") self.assertEqual(response.status_code, 200) payload = response.json() self.assertEqual(len(payload), 3) self.assertEqual( [item["order_index"] for item in payload], [1, 3, 5], ) self.assertEqual( [item["question_text"] for item in payload], ["Q-one", "Q-three", "Q-five"], ) def test_get_questions_returns_404_for_unknown_test(self): response = self.client.get("/admin/tests/9999/questions") self.assertEqual(response.status_code, 404) if __name__ == "__main__": unittest.main()