Skip to content

Commit

Permalink
let the student take exam without proctoring if the course end date …
Browse files Browse the repository at this point in the history
…is passed
  • Loading branch information
ibrahimahmed443 authored and Douglas Hall committed Mar 10, 2016
1 parent c115ff3 commit 289b7f9
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 12 deletions.
26 changes: 18 additions & 8 deletions edx_proctoring/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
48 changes: 47 additions & 1 deletion edx_proctoring/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
)

from edx_proctoring.tests.test_services import (
MockCreditService,
MockCreditService, MockCreditServiceWithCourseEndDate,
MockInstructorService,
)
from edx_proctoring.runtime import set_runtime_service, get_runtime_service
Expand Down Expand Up @@ -1184,6 +1184,52 @@ def test_wrong_exam_combo(self):
)
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
Expand Down
18 changes: 16 additions & 2 deletions edx_proctoring/tests/test_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"""

import unittest
import pytz
from datetime import datetime, timedelta
from edx_proctoring.services import (
ProctoringService
)
Expand All @@ -31,11 +33,10 @@ def __init__(self, enrollment_mode='verified', profile_fullname='Wolfgang von St
'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
Expand Down Expand Up @@ -87,6 +88,19 @@ def remove_credit_requirement_status(self, user_id, course_key_or_id, req_namesp
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
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down

0 comments on commit 289b7f9

Please sign in to comment.