Commit 79da1289 by Afzal Wali

More tests for the start exam attempt API.

parent 6596441a
"""
Tests for the custom StrictBooleanField serializer used by the ProctoredExamSerializer
"""
import unittest
from edx_proctoring.serializers import ProctoredExamSerializer
class TestProctoredExamSerializer(unittest.TestCase):
"""
Tests for ProctoredExamSerializer
"""
def test_boolean_fields(self):
"""
Tests the boolean fields. Should cause a validation error in case a field is required.
"""
data = {
'course_id': "a/b/c",
'exam_name': "midterm1",
'content_id': '123aXqe0',
'time_limit_mins': 90,
'external_id': '123',
'is_proctored': 'bla',
'is_active': 'f'
}
serializer = ProctoredExamSerializer(data=data)
self.assertFalse(serializer.is_valid())
self.assertDictEqual(
{'is_proctored': [u'This field is required.']}, serializer.errors
)
...@@ -19,7 +19,7 @@ urlpatterns = patterns( # pylint: disable=invalid-name ...@@ -19,7 +19,7 @@ urlpatterns = patterns( # pylint: disable=invalid-name
name='edx_proctoring.proctored_exam.exam_by_id' name='edx_proctoring.proctored_exam.exam_by_id'
), ),
url( url(
r'edx_proctoring/v1/proctored_exam/exam/course_id/{}/content_id/(?P<content_id>\d+)$'.format( r'edx_proctoring/v1/proctored_exam/exam/course_id/{}/content_id/(?P<content_id>[A-z0-9]+)$'.format(
settings.COURSE_ID_PATTERN), settings.COURSE_ID_PATTERN),
views.ProctoredExamView.as_view(), views.ProctoredExamView.as_view(),
name='edx_proctoring.proctored_exam.exam_by_content_id' name='edx_proctoring.proctored_exam.exam_by_content_id'
......
...@@ -8,7 +8,7 @@ from rest_framework import status ...@@ -8,7 +8,7 @@ from rest_framework import status
from rest_framework.response import Response from rest_framework.response import Response
from edx_proctoring.api import create_exam, update_exam, get_exam_by_id, get_exam_by_content_id, start_exam_attempt, \ from edx_proctoring.api import create_exam, update_exam, get_exam_by_id, get_exam_by_content_id, start_exam_attempt, \
stop_exam_attempt, add_allowance_for_user, remove_allowance_for_user, get_active_exams_for_user stop_exam_attempt, add_allowance_for_user, remove_allowance_for_user, get_active_exams_for_user
from edx_proctoring.exceptions import ProctoredExamNotFoundException, ProctoredExamAlreadyExists, \ from edx_proctoring.exceptions import ProctoredExamNotFoundException, \
StudentExamAttemptAlreadyExistsException, StudentExamAttemptDoesNotExistsException StudentExamAttemptAlreadyExistsException, StudentExamAttemptDoesNotExistsException
from edx_proctoring.serializers import ProctoredExamSerializer from edx_proctoring.serializers import ProctoredExamSerializer
...@@ -101,22 +101,16 @@ class ProctoredExamView(AuthenticatedAPIView): ...@@ -101,22 +101,16 @@ class ProctoredExamView(AuthenticatedAPIView):
""" """
serializer = ProctoredExamSerializer(data=request.DATA) serializer = ProctoredExamSerializer(data=request.DATA)
if serializer.is_valid(): if serializer.is_valid():
try: exam_id = create_exam(
exam_id = create_exam( course_id=request.DATA.get('course_id', None),
course_id=request.DATA.get('course_id', None), content_id=request.DATA.get('content_id', None),
content_id=request.DATA.get('content_id', None), exam_name=request.DATA.get('exam_name', None),
exam_name=request.DATA.get('exam_name', None), time_limit_mins=request.DATA.get('time_limit_mins', None),
time_limit_mins=request.DATA.get('time_limit_mins', None), is_proctored=request.DATA.get('is_proctored', None),
is_proctored=request.DATA.get('is_proctored', None), external_id=request.DATA.get('external_id', None),
external_id=request.DATA.get('external_id', None), is_active=request.DATA.get('is_active', None)
is_active=request.DATA.get('is_active', None) )
) return Response({'exam_id': exam_id})
return Response({'exam_id': exam_id})
except ProctoredExamAlreadyExists:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "Error Trying to create a duplicate exam."}
)
else: else:
return Response( return Response(
status=status.HTTP_400_BAD_REQUEST, status=status.HTTP_400_BAD_REQUEST,
...@@ -131,12 +125,12 @@ class ProctoredExamView(AuthenticatedAPIView): ...@@ -131,12 +125,12 @@ class ProctoredExamView(AuthenticatedAPIView):
""" """
try: try:
exam_id = update_exam( exam_id = update_exam(
exam_id=request.DATA.get('exam_id', ""), exam_id=request.DATA.get('exam_id', None),
exam_name=request.DATA.get('exam_name', ""), exam_name=request.DATA.get('exam_name', None),
time_limit_mins=request.DATA.get('time_limit_mins', ""), time_limit_mins=request.DATA.get('time_limit_mins', None),
is_proctored=request.DATA.get('is_proctored', False), is_proctored=request.DATA.get('is_proctored', None),
external_id=request.DATA.get('external_id', ""), external_id=request.DATA.get('external_id', None),
is_active=request.DATA.get('is_active', False), is_active=request.DATA.get('is_active', None),
) )
return Response({'exam_id': exam_id}) return Response({'exam_id': exam_id})
except ProctoredExamNotFoundException: except ProctoredExamNotFoundException:
...@@ -176,18 +170,16 @@ class ProctoredExamView(AuthenticatedAPIView): ...@@ -176,18 +170,16 @@ class ProctoredExamView(AuthenticatedAPIView):
status=status.HTTP_400_BAD_REQUEST, status=status.HTTP_400_BAD_REQUEST,
data={"detail": "The exam with course_id, content_id does not exist."} data={"detail": "The exam with course_id, content_id does not exist."}
) )
else:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"detail": "Bad input data."}
)
class StudentProctoredExamAttempt(AuthenticatedAPIView): class StudentProctoredExamAttempt(AuthenticatedAPIView):
""" """
Endpoint for the StudentProctoredExamAttempt Endpoint for the StudentProctoredExamAttempt
/edx_proctoring/v1/proctored_exam/exam /edx_proctoring/v1/proctored_exam/attempt
Supports:
HTTP POST: Starts an exam attempt.
HTTP PUT: Stops an exam attempt.
HTTP GET: Returns the status of an exam attempt.
""" """
def get(self, request): # pylint: disable=unused-argument def get(self, request): # pylint: disable=unused-argument
...@@ -217,9 +209,9 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView): ...@@ -217,9 +209,9 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView):
""" """
try: try:
exam_attempt_id = start_exam_attempt( exam_attempt_id = start_exam_attempt(
exam_id=request.DATA.get('exam_id', ""), exam_id=request.DATA.get('exam_id', None),
user_id=request.DATA.get('user_id', ""), user_id=request.DATA.get('user_id', None),
external_id=request.DATA.get('external_id', "") external_id=request.DATA.get('external_id', None)
) )
return Response({'exam_attempt_id': exam_attempt_id}) return Response({'exam_attempt_id': exam_attempt_id})
...@@ -269,7 +261,7 @@ class ExamAllowanceView(AuthenticatedAPIView): ...@@ -269,7 +261,7 @@ class ExamAllowanceView(AuthenticatedAPIView):
value=request.DATA.get('value', "") value=request.DATA.get('value', "")
)) ))
@require_staff @method_decorator(require_staff)
def delete(self, request): def delete(self, request):
""" """
HTTP DELETE handler. Removes Allowance. HTTP DELETE handler. Removes Allowance.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment