Commit 967c5364 by Afzal Wali Committed by Muhammad Shoaib

Return only active exams when asked for a list of proctored exams.

Don't allow addition of allowance for inactive exams.
Allow viewing and deleting allowances of inactive exams.
parent 8a1a8152
......@@ -805,7 +805,7 @@ def remove_exam_attempt(attempt_id):
)
def get_all_exams_for_course(course_id, timed_exams_only):
def get_all_exams_for_course(course_id, timed_exams_only, active_only=False):
"""
This method will return all exams for a course. This will return a list
of dictionaries, whose schema is the same as what is returned in
......@@ -829,7 +829,11 @@ def get_all_exams_for_course(course_id, timed_exams_only):
..
]
"""
exams = ProctoredExam.get_all_exams_for_course(course_id, timed_exams_only=timed_exams_only)
exams = ProctoredExam.get_all_exams_for_course(
course_id,
active_only=active_only,
timed_exams_only=timed_exams_only
)
return [ProctoredExamSerializer(proctored_exam).data for proctored_exam in exams]
......
......@@ -21,6 +21,12 @@ class ProctoredExamNotFoundException(ProctoredBaseException):
"""
class ProctoredExamNotActiveException(ProctoredBaseException):
"""
Raised when a look up fails.
"""
class StudentExamAttemptAlreadyExistsException(ProctoredBaseException):
"""
Raised when trying to start an exam when an Exam Attempt already exists.
......
......@@ -9,7 +9,10 @@ from model_utils.models import TimeStampedModel
from django.utils.translation import ugettext as _
from django.contrib.auth.models import User
from edx_proctoring.exceptions import UserNotFoundException
from edx_proctoring.exceptions import (
UserNotFoundException,
ProctoredExamNotActiveException,
)
from django.db.models.base import ObjectDoesNotExist
......@@ -671,6 +674,10 @@ class ProctoredExamStudentAllowance(TimeStampedModel):
user_id = users[0].id
exam = ProctoredExam.get_exam_by_id(exam_id)
if exam and not exam.is_active:
raise ProctoredExamNotActiveException
try:
student_allowance = cls.objects.get(proctored_exam_id=exam_id, user_id=user_id, key=key)
student_allowance.value = value
......
# pylint: disable=too-many-lines
# pylint: disable=too-many-lines, invalid-name
"""
All tests for the proctored_exams.py
"""
......@@ -323,7 +323,8 @@ class ProctoredExamViewTests(LoggedInTestCase):
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90
time_limit_mins=90,
is_active=True
)
response = self.client.get(
......@@ -1771,7 +1772,8 @@ class TestExamAllowanceView(LoggedInTestCase):
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90
time_limit_mins=90,
is_active=True
)
allowance_data = {
'exam_id': proctored_exam.id,
......@@ -1795,7 +1797,8 @@ class TestExamAllowanceView(LoggedInTestCase):
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90
time_limit_mins=90,
is_active=True
)
allowance_data = {
'exam_id': proctored_exam.id,
......@@ -1812,6 +1815,33 @@ class TestExamAllowanceView(LoggedInTestCase):
self.assertEqual(len(response_data), 1)
self.assertEqual(response_data['detail'], u"Cannot find user against invalid_user")
def test_add_allowance_for_inactive_exam(self):
"""
Adding allowance for an inactive exam returns a 400 error.
"""
# Create an inactive exam.
proctored_exam = ProctoredExam.objects.create(
course_id='a/b/c',
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90,
is_active=False
)
allowance_data = {
'exam_id': proctored_exam.id,
'user_info': self.student_taking_exam.username,
'key': 'a_key',
'value': '30'
}
# Try to add an allowance
response = self.client.put(
reverse('edx_proctoring.proctored_exam.allowance'),
allowance_data
)
# Returns a 400 status.
self.assertEqual(response.status_code, 400)
def test_remove_allowance_for_user(self):
"""
Remove allowance for a user for an exam.
......@@ -1822,7 +1852,8 @@ class TestExamAllowanceView(LoggedInTestCase):
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90
time_limit_mins=90,
is_active=True
)
allowance_data = {
'exam_id': proctored_exam.id,
......@@ -1877,7 +1908,7 @@ class TestExamAllowanceView(LoggedInTestCase):
def test_get_allowances_for_course(self):
"""
Remove allowance for a user for an exam.
Get allowances for a user for an exam.
"""
# Create an exam.
proctored_exam = ProctoredExam.objects.create(
......@@ -1885,7 +1916,8 @@ class TestExamAllowanceView(LoggedInTestCase):
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90
time_limit_mins=90,
is_active=True
)
allowance_data = {
'exam_id': proctored_exam.id,
......@@ -1923,6 +1955,7 @@ class TestExamAllowanceView(LoggedInTestCase):
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90,
is_active=True,
is_proctored=False
)
allowance_data = {
......@@ -1962,6 +1995,7 @@ class TestExamAllowanceView(LoggedInTestCase):
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90,
is_active=True,
is_proctored=False
)
allowance_data = {
......@@ -1983,6 +2017,7 @@ class TestExamAllowanceView(LoggedInTestCase):
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90,
is_active=True,
is_proctored=True
)
allowance_data = {
......@@ -2010,6 +2045,84 @@ class TestExamAllowanceView(LoggedInTestCase):
self.assertEqual(response_data[0]['proctored_exam']['content_id'], timed_exam.content_id)
self.assertEqual(response_data[0]['key'], allowance_data['key'])
def test_get_allowances_for_inactive_exam(self):
"""
Get allowances for a for an inactive exam should be allowed.
"""
# Create an exam.
proctored_exam = ProctoredExam.objects.create(
course_id='a/b/c',
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90,
is_active=True
)
allowance_data = {
'exam_id': proctored_exam.id,
'user_info': self.student_taking_exam.username,
'key': 'a_key',
'value': '30'
}
response = self.client.put(
reverse('edx_proctoring.proctored_exam.allowance'),
allowance_data
)
self.assertEqual(response.status_code, 200)
# now make the exam inactive
proctored_exam.is_active = False
proctored_exam.save()
response = self.client.get(
reverse('edx_proctoring.proctored_exam.allowance', kwargs={'course_id': proctored_exam.course_id})
)
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.content)
self.assertEqual(len(response_data), 1)
self.assertEqual(response_data[0]['proctored_exam']['course_id'], proctored_exam.course_id)
self.assertEqual(response_data[0]['key'], allowance_data['key'])
def test_remove_allowance_for_inactive_exam(self):
"""
Removing allowance for a user for an inactive exam should be allowed.
"""
# Create an exam.
proctored_exam = ProctoredExam.objects.create(
course_id='a/b/c',
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
time_limit_mins=90,
is_active=True
)
allowance_data = {
'exam_id': proctored_exam.id,
'user_info': self.student_taking_exam.email,
'key': 'a_key',
'value': '30'
}
# Add allowance
response = self.client.put(
reverse('edx_proctoring.proctored_exam.allowance'),
allowance_data
)
self.assertEqual(response.status_code, 200)
allowance_data.pop('value')
# now make the exam inactive
proctored_exam.is_active = False
proctored_exam.save()
response = self.client.delete(
reverse('edx_proctoring.proctored_exam.allowance'),
allowance_data
)
self.assertEqual(response.status_code, 200)
class TestActiveExamsForUserView(LoggedInTestCase):
"""
......
......@@ -38,6 +38,7 @@ from edx_proctoring.exceptions import (
ProctoredExamPermissionDenied,
StudentExamAttemptDoesNotExistsException,
ProctoredExamIllegalStatusTransition,
ProctoredExamNotActiveException,
)
from edx_proctoring.runtime import get_runtime_service
from edx_proctoring.serializers import ProctoredExamSerializer, ProctoredExamStudentAttemptSerializer
......@@ -254,7 +255,8 @@ class ProctoredExamView(AuthenticatedAPIView):
timed_exams_only = not request.user.is_staff
result_set = get_all_exams_for_course(
course_id=course_id,
timed_exams_only=timed_exams_only
timed_exams_only=timed_exams_only,
active_only=True
)
return Response(result_set)
......@@ -719,7 +721,7 @@ class ExamAllowanceView(AuthenticatedAPIView):
value=request.DATA.get('value', None)
))
except UserNotFoundException, ex:
except (UserNotFoundException, ProctoredExamNotActiveException) as ex:
LOG.exception(ex)
return Response(
status=status.HTTP_400_BAD_REQUEST,
......
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