Commit ac0115f7 by chrisndodge

Merge pull request #19 from edx/cdodge/add-get-exams-for-course

Add API method to get a list of all exams for a course
parents b17b841b 90853b76
......@@ -219,6 +219,17 @@ def stop_exam_attempt(exam_id, user_id):
return exam_attempt_obj.id
def get_all_exams_for_course(course_id):
"""
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
get_exam_by_id
"""
exams = ProctoredExam.get_all_exams_for_course(course_id)
return [ProctoredExamSerializer(proctored_exam).data for proctored_exam in exams]
def get_active_exams_for_user(user_id, course_id=None):
"""
This method will return a list of active exams for the user,
......@@ -277,9 +288,17 @@ def get_student_view(user_id, course_id, content_id, context):
exam_id = None
try:
exam = get_exam_by_content_id(course_id, content_id)
if not exam['is_active']:
# Exam is no longer active
# Note, we don't hard delete exams since we need to retain
# data
return None
exam_id = exam['id']
is_proctored = exam['is_proctored']
except ProctoredExamNotFoundException:
# This really shouldn't happen
# as Studio will be setting this up
is_proctored = context.get('is_proctored', False)
exam_id = create_exam(
course_id=course_id,
......
......@@ -65,6 +65,13 @@ class ProctoredExam(TimeStampedModel):
proctored_exam = None
return proctored_exam
@classmethod
def get_all_exams_for_course(cls, course_id):
"""
Returns all exams for a give course
"""
return cls.objects.filter(course_id=course_id)
class ProctoredExamStudentAttempt(TimeStampedModel):
"""
......
......@@ -16,6 +16,7 @@ from edx_proctoring.api import (
get_exam_attempt,
create_exam_attempt,
get_student_view,
get_all_exams_for_course,
)
from edx_proctoring.exceptions import (
ProctoredExamAlreadyExists,
......@@ -48,12 +49,14 @@ class ProctoredExamApiTests(LoggedInTestCase):
self.default_time_limit = 21
self.course_id = 'test_course'
self.content_id = 'test_content_id'
self.disabled_content_id = 'test_disabled_content_id'
self.exam_name = 'Test Exam'
self.user_id = 1
self.key = 'Test Key'
self.value = 'Test Value'
self.external_id = 'test_external_id'
self.proctored_exam_id = self._create_proctored_exam()
self.disabled_exam_id = self._create_disabled_exam()
# Messages for get_student_view
self.start_an_exam_msg = 'Would you like to take %s as a Proctored Exam?'
......@@ -72,6 +75,18 @@ class ProctoredExamApiTests(LoggedInTestCase):
time_limit_mins=self.default_time_limit
)
def _create_disabled_exam(self):
"""
Calls the api's create_exam to create an exam object.
"""
return create_exam(
course_id=self.course_id,
content_id=self.disabled_content_id,
exam_name=self.exam_name,
time_limit_mins=self.default_time_limit,
is_active=False
)
def _create_unstarted_exam_attempt(self):
"""
Creates the ProctoredExamStudentAttempt object.
......@@ -135,7 +150,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
which will throw the exception
"""
with self.assertRaises(ProctoredExamNotFoundException):
update_exam(2, exam_name='Updated Exam Name', time_limit_mins=30)
update_exam(0, exam_name='Updated Exam Name', time_limit_mins=30)
def test_get_proctored_exam(self):
"""
......@@ -152,6 +167,9 @@ class ProctoredExamApiTests(LoggedInTestCase):
self.assertEqual(proctored_exam['content_id'], self.content_id)
self.assertEqual(proctored_exam['exam_name'], self.exam_name)
exams = get_all_exams_for_course(self.course_id)
self.assertEqual(len(exams), 2)
def test_get_invalid_proctored_exam(self):
"""
test to get the exam by the invalid exam_id which will
......@@ -159,7 +177,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
"""
with self.assertRaises(ProctoredExamNotFoundException):
get_exam_by_id(2)
get_exam_by_id(0)
with self.assertRaises(ProctoredExamNotFoundException):
get_exam_by_content_id('teasd', 'tewasda')
......@@ -321,6 +339,24 @@ class ProctoredExamApiTests(LoggedInTestCase):
self.assertIn('data-exam-id="%d"' % self.proctored_exam_id, rendered_response)
self.assertIn(self.start_an_exam_msg % self.exam_name, rendered_response)
def test_get_disabled_student_view(self):
"""
Assert that a disabled proctored exam will not override the
student_view
"""
self.assertIsNone(
get_student_view(
user_id=self.user_id,
course_id=self.course_id,
content_id=self.disabled_content_id,
context={
'is_proctored': True,
'display_name': self.exam_name,
'default_time_limit_mins': 90
}
)
)
def test_getstudentview_timedexam(self):
"""
Test for get_student_view Timed exam which is not proctored.
......
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