Commit 9bb6f6e8 by Zia Fazal

use a generic function check if entrance_exam is enabled or not

parent 450e625d
...@@ -67,8 +67,7 @@ from contentstore.tasks import rerun_course ...@@ -67,8 +67,7 @@ from contentstore.tasks import rerun_course
from contentstore.views.entrance_exam import ( from contentstore.views.entrance_exam import (
create_entrance_exam, create_entrance_exam,
update_entrance_exam, update_entrance_exam,
delete_entrance_exam, delete_entrance_exam
is_entrance_exams_enabled
) )
from .library import LIBRARIES_ENABLED from .library import LIBRARIES_ENABLED
...@@ -89,7 +88,8 @@ from student.auth import has_course_author_access ...@@ -89,7 +88,8 @@ from student.auth import has_course_author_access
from util.milestones_helpers import ( from util.milestones_helpers import (
set_prerequisite_courses, set_prerequisite_courses,
is_valid_course_key, is_valid_course_key,
is_prerequisite_courses_enabled is_prerequisite_courses_enabled,
is_entrance_exams_enabled
) )
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -983,7 +983,7 @@ def settings_handler(request, course_key_string): ...@@ -983,7 +983,7 @@ def settings_handler(request, course_key_string):
# feature-specific settings and handle them accordingly # feature-specific settings and handle them accordingly
# We have to be careful that we're only executing the following logic if we actually # We have to be careful that we're only executing the following logic if we actually
# need to create or delete an entrance exam from the specified course # need to create or delete an entrance exam from the specified course
if settings.FEATURES.get('ENTRANCE_EXAMS', False): if is_entrance_exams_enabled():
course_entrance_exam_present = course_module.entrance_exam_enabled course_entrance_exam_present = course_module.entrance_exam_enabled
entrance_exam_enabled = request.json.get('entrance_exam_enabled', '') == 'true' entrance_exam_enabled = request.json.get('entrance_exam_enabled', '') == 'true'
ee_min_score_pct = request.json.get('entrance_exam_minimum_score_pct', None) ee_min_score_pct = request.json.get('entrance_exam_minimum_score_pct', None)
......
...@@ -54,13 +54,6 @@ def check_feature_enabled(feature_name): ...@@ -54,13 +54,6 @@ def check_feature_enabled(feature_name):
return _check_feature_enabled return _check_feature_enabled
def is_entrance_exams_enabled():
"""
Returns a boolean indicating entrance exam feature is enable or not.
"""
return settings.FEATURES.get('ENTRANCE_EXAMS', False)
@login_required @login_required
@ensure_csrf_cookie @ensure_csrf_cookie
@check_feature_enabled(feature_name='ENTRANCE_EXAMS') @check_feature_enabled(feature_name='ENTRANCE_EXAMS')
......
...@@ -22,6 +22,7 @@ from xmodule.tabs import StaticTab ...@@ -22,6 +22,7 @@ from xmodule.tabs import StaticTab
from contentstore.utils import reverse_course_url, reverse_library_url, reverse_usage_url from contentstore.utils import reverse_course_url, reverse_library_url, reverse_usage_url
from models.settings.course_grading import CourseGradingModel from models.settings.course_grading import CourseGradingModel
from util.milestones_helpers import is_entrance_exams_enabled
__all__ = ['edge', 'event', 'landing'] __all__ = ['edge', 'event', 'landing']
...@@ -226,7 +227,7 @@ def create_xblock(parent_locator, user, category, display_name, boilerplate=None ...@@ -226,7 +227,7 @@ def create_xblock(parent_locator, user, category, display_name, boilerplate=None
# Entrance Exams: Chapter module positioning # Entrance Exams: Chapter module positioning
child_position = None child_position = None
if settings.FEATURES.get('ENTRANCE_EXAMS', False): if is_entrance_exams_enabled():
if category == 'chapter' and is_entrance_exam: if category == 'chapter' and is_entrance_exam:
fields['is_entrance_exam'] = is_entrance_exam fields['is_entrance_exam'] = is_entrance_exam
fields['in_entrance_exam'] = True # Inherited metadata, all children will have it fields['in_entrance_exam'] = True # Inherited metadata, all children will have it
...@@ -250,7 +251,7 @@ def create_xblock(parent_locator, user, category, display_name, boilerplate=None ...@@ -250,7 +251,7 @@ def create_xblock(parent_locator, user, category, display_name, boilerplate=None
) )
# Entrance Exams: Grader assignment # Entrance Exams: Grader assignment
if settings.FEATURES.get('ENTRANCE_EXAMS', False): if is_entrance_exams_enabled():
course_key = usage_key.course_key course_key = usage_key.course_key
course = store.get_course(course_key) course = store.get_course(course_key)
if hasattr(course, 'entrance_exam_enabled') and course.entrance_exam_enabled: if hasattr(course, 'entrance_exam_enabled') and course.entrance_exam_enabled:
......
...@@ -38,6 +38,7 @@ from django.contrib.auth.models import User ...@@ -38,6 +38,7 @@ from django.contrib.auth.models import User
from util.date_utils import get_default_time_display from util.date_utils import get_default_time_display
from util.json_request import expect_json, JsonResponse from util.json_request import expect_json, JsonResponse
from util.milestones_helpers import is_entrance_exams_enabled
from student.auth import has_studio_write_access, has_studio_read_access from student.auth import has_studio_write_access, has_studio_read_access
from contentstore.utils import ( from contentstore.utils import (
...@@ -89,7 +90,7 @@ def _filter_entrance_exam_grader(graders): ...@@ -89,7 +90,7 @@ def _filter_entrance_exam_grader(graders):
views/controls like the 'Grade as' dropdown that allows a course author to select views/controls like the 'Grade as' dropdown that allows a course author to select
the grader type for a given section of a course the grader type for a given section of a course
""" """
if settings.FEATURES.get('ENTRANCE_EXAMS', False): if is_entrance_exams_enabled():
graders = [grader for grader in graders if grader.get('type') != u'Entrance Exam'] graders = [grader for grader in graders if grader.get('type') != u'Entrance Exam']
return graders return graders
......
...@@ -52,6 +52,7 @@ import lms.lib.comment_client as cc ...@@ -52,6 +52,7 @@ import lms.lib.comment_client as cc
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from util.model_utils import emit_field_changed_events, get_changed_fields_dict from util.model_utils import emit_field_changed_events, get_changed_fields_dict
from util.query import use_read_replica_if_available from util.query import use_read_replica_if_available
from util.milestones_helpers import is_entrance_exams_enabled
UNENROLL_DONE = Signal(providing_args=["course_enrollment", "skip_refund"]) UNENROLL_DONE = Signal(providing_args=["course_enrollment", "skip_refund"])
...@@ -1896,7 +1897,7 @@ class EntranceExamConfiguration(models.Model): ...@@ -1896,7 +1897,7 @@ class EntranceExamConfiguration(models.Model):
Return True if given user can skip entrance exam for given course otherwise False. Return True if given user can skip entrance exam for given course otherwise False.
""" """
can_skip = False can_skip = False
if settings.FEATURES.get('ENTRANCE_EXAMS', False): if is_entrance_exams_enabled():
try: try:
record = EntranceExamConfiguration.objects.get(user=user, course_id=course_key) record = EntranceExamConfiguration.objects.get(user=user, course_id=course_key)
can_skip = record.skip_entrance_exam can_skip = record.skip_entrance_exam
......
...@@ -24,6 +24,14 @@ def get_namespace_choices(): ...@@ -24,6 +24,14 @@ def get_namespace_choices():
return NAMESPACE_CHOICES return NAMESPACE_CHOICES
def is_entrance_exams_enabled():
"""
Checks to see if the Entrance Exams feature is enabled
Use this operation instead of checking the feature flag all over the place
"""
return settings.FEATURES.get('ENTRANCE_EXAMS', False)
def is_prerequisite_courses_enabled(): def is_prerequisite_courses_enabled():
""" """
Returns boolean indicating prerequisite courses enabled system wide or not. Returns boolean indicating prerequisite courses enabled system wide or not.
......
...@@ -8,24 +8,16 @@ from courseware.model_data import FieldDataCache, ScoresClient ...@@ -8,24 +8,16 @@ from courseware.model_data import FieldDataCache, ScoresClient
from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.keys import UsageKey
from opaque_keys.edx.locator import BlockUsageLocator from opaque_keys.edx.locator import BlockUsageLocator
from student.models import EntranceExamConfiguration from student.models import EntranceExamConfiguration
from util.milestones_helpers import get_required_content from util.milestones_helpers import get_required_content, is_entrance_exams_enabled
from util.module_utils import yield_dynamic_descriptor_descendants from util.module_utils import yield_dynamic_descriptor_descendants
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
def feature_is_enabled():
"""
Checks to see if the Entrance Exams feature is enabled
Use this operation instead of checking the feature flag all over the place
"""
return settings.FEATURES.get('ENTRANCE_EXAMS', False)
def course_has_entrance_exam(course): def course_has_entrance_exam(course):
""" """
Checks to see if a course is properly configured for an entrance exam Checks to see if a course is properly configured for an entrance exam
""" """
if not feature_is_enabled(): if not is_entrance_exams_enabled():
return False return False
if not course.entrance_exam_enabled: if not course.entrance_exam_enabled:
return False return False
......
...@@ -470,7 +470,7 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to ...@@ -470,7 +470,7 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to
# Fulfillment Use Case: Entrance Exam # Fulfillment Use Case: Entrance Exam
# If this module is part of an entrance exam, we'll need to see if the student # If this module is part of an entrance exam, we'll need to see if the student
# has reached the point at which they can collect the associated milestone # has reached the point at which they can collect the associated milestone
if settings.FEATURES.get('ENTRANCE_EXAMS', False): if milestones_helpers.is_entrance_exams_enabled():
course = modulestore().get_course(course_key) course = modulestore().get_course(course_key)
content = modulestore().get_item(content_key) content = modulestore().get_item(content_key)
entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False) entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False)
......
...@@ -19,7 +19,13 @@ from courseware.tests.factories import InstructorFactory, StaffFactory ...@@ -19,7 +19,13 @@ from courseware.tests.factories import InstructorFactory, StaffFactory
from courseware.views import get_static_tab_contents, static_tab from courseware.views import get_static_tab_contents, static_tab
from student.models import CourseEnrollment from student.models import CourseEnrollment
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from util import milestones_helpers from util.milestones_helpers import (
seed_milestone_relationship_types,
get_milestone_relationship_types,
add_milestone,
add_course_milestone,
add_course_content_milestone
)
from xmodule import tabs as xmodule_tabs from xmodule import tabs as xmodule_tabs
from xmodule.modulestore.tests.django_utils import ( from xmodule.modulestore.tests.django_utils import (
TEST_DATA_MIXED_TOY_MODULESTORE, TEST_DATA_MIXED_CLOSED_MODULESTORE TEST_DATA_MIXED_TOY_MODULESTORE, TEST_DATA_MIXED_CLOSED_MODULESTORE
...@@ -303,112 +309,112 @@ class StaticTabDateTestCaseXML(LoginEnrollmentTestCase, ModuleStoreTestCase): ...@@ -303,112 +309,112 @@ class StaticTabDateTestCaseXML(LoginEnrollmentTestCase, ModuleStoreTestCase):
@attr('shard_1') @attr('shard_1')
@patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': True, 'MILESTONES_APP': True})
class EntranceExamsTabsTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase): class EntranceExamsTabsTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
""" """
Validate tab behavior when dealing with Entrance Exams Validate tab behavior when dealing with Entrance Exams
""" """
MODULESTORE = TEST_DATA_MIXED_CLOSED_MODULESTORE MODULESTORE = TEST_DATA_MIXED_CLOSED_MODULESTORE
if settings.FEATURES.get('ENTRANCE_EXAMS', False): @patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': True, 'MILESTONES_APP': True})
def setUp(self):
"""
Test case scaffolding
"""
super(EntranceExamsTabsTestCase, self).setUp()
def setUp(self): self.course = CourseFactory.create()
""" self.instructor_tab = ItemFactory.create(
Test case scaffolding category="instructor", parent_location=self.course.location,
""" data="Instructor Tab", display_name="Instructor"
super(EntranceExamsTabsTestCase, self).setUp() )
self.extra_tab_2 = ItemFactory.create(
category="static_tab", parent_location=self.course.location,
data="Extra Tab", display_name="Extra Tab 2"
)
self.extra_tab_3 = ItemFactory.create(
category="static_tab", parent_location=self.course.location,
data="Extra Tab", display_name="Extra Tab 3"
)
self.setup_user()
self.enroll(self.course)
self.user.is_staff = True
seed_milestone_relationship_types()
self.relationship_types = get_milestone_relationship_types()
self.course = CourseFactory.create() def test_get_course_tabs_list_entrance_exam_enabled(self):
self.instructor_tab = ItemFactory.create( """
category="instructor", parent_location=self.course.location, Unit Test: test_get_course_tabs_list_entrance_exam_enabled
data="Instructor Tab", display_name="Instructor" """
) entrance_exam = ItemFactory.create(
self.extra_tab_2 = ItemFactory.create( category="chapter",
category="static_tab", parent_location=self.course.location, parent_location=self.course.location,
data="Extra Tab", display_name="Extra Tab 2" data="Exam Data",
) display_name="Entrance Exam",
self.extra_tab_3 = ItemFactory.create( is_entrance_exam=True
category="static_tab", parent_location=self.course.location, )
data="Extra Tab", display_name="Extra Tab 3" milestone = {
) 'name': 'Test Milestone',
self.setup_user() 'namespace': '{}.entrance_exams'.format(unicode(self.course.id)),
self.enroll(self.course) 'description': 'Testing Courseware Tabs'
self.user.is_staff = True }
self.relationship_types = milestones_helpers.get_milestone_relationship_types() self.user.is_staff = False
milestones_helpers.seed_milestone_relationship_types() request = get_request_for_user(self.user)
self.course.entrance_exam_enabled = True
def test_get_course_tabs_list_entrance_exam_enabled(self): self.course.entrance_exam_id = unicode(entrance_exam.location)
""" milestone = add_milestone(milestone)
Unit Test: test_get_course_tabs_list_entrance_exam_enabled add_course_milestone(
""" unicode(self.course.id),
entrance_exam = ItemFactory.create( self.relationship_types['REQUIRES'],
category="chapter", milestone
parent_location=self.course.location, )
data="Exam Data", add_course_content_milestone(
display_name="Entrance Exam", unicode(self.course.id),
is_entrance_exam=True unicode(entrance_exam.location),
) self.relationship_types['FULFILLS'],
milestone = { milestone
'name': 'Test Milestone', )
'namespace': '{}.entrance_exams'.format(unicode(self.course.id)), course_tab_list = get_course_tab_list(request, self.course)
'description': 'Testing Courseware Tabs' self.assertEqual(len(course_tab_list), 1)
} self.assertEqual(course_tab_list[0]['tab_id'], 'courseware')
self.user.is_staff = False self.assertEqual(course_tab_list[0]['name'], 'Entrance Exam')
request = get_request_for_user(self.user)
self.course.entrance_exam_enabled = True def test_get_course_tabs_list_skipped_entrance_exam(self):
self.course.entrance_exam_id = unicode(entrance_exam.location) """
milestone = milestones_helpers.add_milestone(milestone) Tests tab list is not limited if user is allowed to skip entrance exam.
milestones_helpers.add_course_milestone( """
unicode(self.course.id), #create a user
self.relationship_types['REQUIRES'], student = UserFactory()
milestone # login as instructor hit skip entrance exam api in instructor app
) instructor = InstructorFactory(course_key=self.course.id)
milestones_helpers.add_course_content_milestone( self.client.logout()
unicode(self.course.id), self.client.login(username=instructor.username, password='test')
unicode(entrance_exam.location),
self.relationship_types['FULFILLS'], url = reverse('mark_student_can_skip_entrance_exam', kwargs={'course_id': unicode(self.course.id)})
milestone response = self.client.post(url, {
) 'unique_student_identifier': student.email,
course_tab_list = get_course_tab_list(request, self.course) })
self.assertEqual(len(course_tab_list), 1) self.assertEqual(response.status_code, 200)
self.assertEqual(course_tab_list[0]['tab_id'], 'courseware')
self.assertEqual(course_tab_list[0]['name'], 'Entrance Exam') # log in again as student
self.client.logout()
def test_get_course_tabs_list_skipped_entrance_exam(self): self.login(self.email, self.password)
""" request = get_request_for_user(self.user)
Tests tab list is not limited if user is allowed to skip entrance exam. course_tab_list = get_course_tab_list(request, self.course)
""" self.assertEqual(len(course_tab_list), 5)
#create a user
student = UserFactory() def test_course_tabs_list_for_staff_members(self):
# login as instructor hit skip entrance exam api in instructor app """
instructor = InstructorFactory(course_key=self.course.id) Tests tab list is not limited if user is member of staff
self.client.logout() and has not passed entrance exam.
self.client.login(username=instructor.username, password='test') """
# Login as member of staff
url = reverse('mark_student_can_skip_entrance_exam', kwargs={'course_id': unicode(self.course.id)}) self.client.logout()
response = self.client.post(url, { staff_user = StaffFactory(course_key=self.course.id)
'unique_student_identifier': student.email, self.client.login(username=staff_user.username, password='test')
}) request = get_request_for_user(staff_user)
self.assertEqual(response.status_code, 200) course_tab_list = get_course_tab_list(request, self.course)
self.assertEqual(len(course_tab_list), 5)
# log in again as student
self.client.logout()
self.login(self.email, self.password)
request = get_request_for_user(self.user)
course_tab_list = get_course_tab_list(request, self.course)
self.assertEqual(len(course_tab_list), 5)
def test_course_tabs_list_for_staff_members(self):
"""
Tests tab list is not limited if user is member of staff
and has not passed entrance exam.
"""
# Login as member of staff
self.client.logout()
staff_user = StaffFactory(course_key=self.course.id)
self.client.login(username=staff_user.username, password='test')
request = get_request_for_user(staff_user)
course_tab_list = get_course_tab_list(request, self.course)
self.assertEqual(len(course_tab_list), 5)
@attr('shard_1') @attr('shard_1')
......
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