Commit 289b7f92 by Ibrahim Committed by Douglas Hall

let the student take exam without proctoring if the course end date is passed

parent c115ff36
......@@ -893,7 +893,7 @@ def update_attempt_status(exam_id, user_id, to_status, raise_if_not_found=True,
credit_state = credit_service.get_credit_state(
exam_attempt_obj.user_id,
exam_attempt_obj.proctored_exam.course_id,
return_course_name=True
return_course_info=True
)
send_proctoring_attempt_status_email(
......@@ -1770,6 +1770,12 @@ def get_student_view(user_id, course_id, content_id,
if user_role != 'student':
return None
credit_service = get_runtime_service('credit')
# call service to get course end date.
credit_state = credit_service.get_credit_state(user_id, course_id, return_course_info=True)
course_end_date = credit_state.get('course_end_date', None)
exam_id = None
try:
exam = get_exam_by_content_id(course_id, content_id)
......@@ -1808,11 +1814,15 @@ def get_student_view(user_id, course_id, content_id,
is_proctored_exam = exam['is_proctored'] and not exam['is_practice_exam']
is_timed_exam = not exam['is_proctored'] and not exam['is_practice_exam']
sub_view_func = None
if is_timed_exam:
return _get_timed_exam_view(exam, context, exam_id, user_id, course_id)
elif is_practice_exam:
return _get_practice_exam_view(exam, context, exam_id, user_id, course_id)
elif is_proctored_exam:
return _get_proctored_exam_view(exam, context, exam_id, user_id, course_id)
return None
sub_view_func = _get_timed_exam_view
elif is_practice_exam and not has_due_date_passed(course_end_date):
sub_view_func = _get_practice_exam_view
elif is_proctored_exam and not has_due_date_passed(course_end_date):
sub_view_func = _get_proctored_exam_view
if sub_view_func:
return sub_view_func(exam, context, exam_id, user_id, course_id)
else:
return None
......@@ -71,7 +71,7 @@ from .utils import (
)
from edx_proctoring.tests.test_services import (
MockCreditService,
MockCreditService, MockCreditServiceWithCourseEndDate,
MockInstructorService,
)
from edx_proctoring.runtime import set_runtime_service, get_runtime_service
......@@ -1184,6 +1184,52 @@ class ProctoredExamApiTests(LoggedInTestCase):
)
self.assertIsNone(rendered_response)
def test_proctored_exam_passed_end_date(self):
"""
Verify that we get a None back on a proctored exam
if the course end date is passed
"""
set_runtime_service('credit', MockCreditServiceWithCourseEndDate())
rendered_response = get_student_view(
user_id=self.user_id,
course_id='foo',
content_id='bar',
context={
'is_proctored': True,
'is_practice_exam': False,
'display_name': self.exam_name,
'default_time_limit_mins': 90,
'due_date': None
},
user_role='student'
)
self.assertIsNone(rendered_response)
def test_practice_exam_passed_end_date(self):
"""
Verify that we get a None back on a practice exam
if the course end date is passed
"""
set_runtime_service('credit', MockCreditServiceWithCourseEndDate())
rendered_response = get_student_view(
user_id=self.user_id,
course_id='foo',
content_id='bar',
context={
'is_proctored': True,
'is_practice_exam': True,
'display_name': self.exam_name,
'default_time_limit_mins': 90,
'due_date': None
},
user_role='student'
)
self.assertIsNone(rendered_response)
def test_get_disabled_student_view(self):
"""
Assert that a disabled proctored exam will not override the
......
......@@ -5,6 +5,8 @@ Test for the xBlock service
"""
import unittest
import pytz
from datetime import datetime, timedelta
from edx_proctoring.services import (
ProctoringService
)
......@@ -31,11 +33,10 @@ class MockCreditService(object):
'credit_requirement_status': []
}
def get_credit_state(self, user_id, course_key, return_course_name=False): # pylint: disable=unused-argument
def get_credit_state(self, user_id, course_key, return_course_info=False): # pylint: disable=unused-argument
"""
Mock implementation
"""
return self.status
# pylint: disable=unused-argument
......@@ -87,6 +88,19 @@ class MockCreditService(object):
return True
class MockCreditServiceWithCourseEndDate(MockCreditService):
"""
mock of the Credit Service but overrides get_credit_state to return a past course_end_date
"""
def get_credit_state(self, user_id, course_key, return_course_info=False): # pylint: disable=unused-argument
"""
Mock implementation
"""
self.status['course_end_date'] = datetime.now(pytz.UTC) + timedelta(days=-1)
return self.status
class MockInstructorService(object):
"""
Simple mock of the Instructor Service
......
......@@ -34,7 +34,7 @@ def load_requirements(*requirements_paths):
setup(
name='edx-proctoring',
version='0.12.12',
version='0.12.13',
description='Proctoring subsystem for Open edX',
long_description=open('README.md').read(),
author='edX',
......
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