diff --git a/tutorial/tests.py b/tutorial/tests.py new file mode 100644 index 0000000..598fbf3 --- /dev/null +++ b/tutorial/tests.py @@ -0,0 +1,144 @@ +from django.test import TestCase, Client +from django.contrib.auth import get_user_model +import json + +from tutorial.models import Tutorial, Exercise + +User = get_user_model() + + +def _json(response): + return json.loads(response.content) + + +class ExerciseAPITest(TestCase): + def setUp(self): + self.client = Client() + self.admin = User.objects.create( + username="admin_test", admin_type="Super Admin", is_staff=True + ) + self.admin.set_password("password") + self.admin.save() + + self.tutorial = Tutorial.objects.create( + title="Test Tutorial", + content="Hello [[exercise:1]]", + type="python", + is_public=True, + order=0, + created_by=self.admin, + ) + self.exercise = Exercise.objects.create( + tutorial=self.tutorial, + type="mcq", + data={ + "question": "Which is valid?", + "options": ["A", "B"], + "answer": 1, + }, + order=0, + ) + + def test_get_exercises_for_tutorial(self): + resp = self.client.get(f"/api/exercises?tutorial_id={self.tutorial.id}") + self.assertEqual(resp.status_code, 200) + data = _json(resp)["data"] + self.assertEqual(len(data), 1) + self.assertEqual(data[0]["type"], "mcq") + + def test_get_exercises_missing_tutorial_id(self): + resp = self.client.get("/api/exercises") + self.assertEqual(_json(resp)["error"], "error") + + def test_get_exercises_nonexistent_tutorial(self): + resp = self.client.get("/api/exercises?tutorial_id=99999") + self.assertEqual(_json(resp)["error"], "error") + + +class ExerciseAdminAPITest(TestCase): + def setUp(self): + self.client = Client() + self.admin = User.objects.create( + username="admin2_test", admin_type="Super Admin", is_staff=True + ) + self.admin.set_password("password") + self.admin.save() + self.client.login(username="admin2_test", password="password") + + self.tutorial = Tutorial.objects.create( + title="T", + content="", + type="python", + is_public=False, + order=0, + created_by=self.admin, + ) + + def test_create_mcq(self): + resp = self.client.post( + "/api/admin/exercise", + data=json.dumps({ + "tutorial_id": self.tutorial.id, + "type": "mcq", + "data": {"question": "Q?", "options": ["A", "B"], "answer": 0}, + "order": 0, + }), + content_type="application/json", + ) + self.assertEqual(resp.status_code, 200) + self.assertIsNone(_json(resp)["error"]) + self.assertEqual(Exercise.objects.count(), 1) + + def test_create_invalid_type(self): + resp = self.client.post( + "/api/admin/exercise", + data=json.dumps({ + "tutorial_id": self.tutorial.id, + "type": "bad_type", + "data": {}, + "order": 0, + }), + content_type="application/json", + ) + self.assertEqual(_json(resp)["error"], "error") + + def test_edit_exercise(self): + ex = Exercise.objects.create( + tutorial=self.tutorial, + type="mcq", + data={"question": "Old", "options": ["A", "B"], "answer": 0}, + order=0, + ) + resp = self.client.put( + "/api/admin/exercise", + data=json.dumps({ + "id": ex.id, + "type": "mcq", + "data": {"question": "New", "options": ["A", "B"], "answer": 1}, + "order": 0, + }), + content_type="application/json", + ) + self.assertEqual(resp.status_code, 200) + ex.refresh_from_db() + self.assertEqual(ex.data["question"], "New") + + def test_delete_exercise(self): + ex = Exercise.objects.create( + tutorial=self.tutorial, + type="sort", + data={"question": "Q", "lines": ["a", "b"]}, + order=0, + ) + resp = self.client.delete(f"/api/admin/exercise?id={ex.id}") + self.assertEqual(resp.status_code, 200) + self.assertEqual(Exercise.objects.count(), 0) + + def test_requires_admin(self): + self.client.logout() + resp = self.client.post( + "/api/admin/exercise", + data=json.dumps({"tutorial_id": 1, "type": "mcq", "data": {}, "order": 0}), + content_type="application/json", + ) + self.assertEqual(resp.status_code, 403)