From 9260f8813adc5bc4bb5e192cfe411f47cc8db524 Mon Sep 17 00:00:00 2001 From: rabiaiftikhar Date: Thu, 19 Oct 2017 22:26:36 +0500 Subject: [PATCH] EDUCATOR-1542 give access to Special Exam tab to the course team --- .../instructor/tests/test_proctoring.py | 97 +++++++++++++++---- .../instructor/views/instructor_dashboard.py | 18 ++-- 2 files changed, 90 insertions(+), 25 deletions(-) diff --git a/lms/djangoapps/instructor/tests/test_proctoring.py b/lms/djangoapps/instructor/tests/test_proctoring.py index 986c09891e..6dc03d187b 100644 --- a/lms/djangoapps/instructor/tests/test_proctoring.py +++ b/lms/djangoapps/instructor/tests/test_proctoring.py @@ -2,12 +2,13 @@ Unit tests for Edx Proctoring feature flag in new instructor dashboard. """ +import ddt from django.conf import settings from django.core.urlresolvers import reverse from mock import patch from nose.plugins.attrib import attr -from student.roles import CourseFinanceAdminRole +from student.roles import CourseStaffRole, CourseInstructorRole from student.tests.factories import AdminFactory from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @@ -15,6 +16,7 @@ from xmodule.modulestore.tests.factories import CourseFactory @attr(shard=1) @patch.dict(settings.FEATURES, {'ENABLE_SPECIAL_EXAMS': True}) +@ddt.ddt class TestProctoringDashboardViews(SharedModuleStoreTestCase): """ Check for Proctoring view on the new instructor dashboard @@ -22,10 +24,6 @@ class TestProctoringDashboardViews(SharedModuleStoreTestCase): @classmethod def setUpClass(cls): super(TestProctoringDashboardViews, cls).setUpClass() - cls.course = CourseFactory.create(enable_proctored_exams=True) - - # URL for instructor dash - cls.url = reverse('instructor_dashboard', kwargs={'course_id': cls.course.id.to_deprecated_string()}) button = '' cls.proctoring_link = button @@ -36,24 +34,74 @@ class TestProctoringDashboardViews(SharedModuleStoreTestCase): self.instructor = AdminFactory.create() self.client.login(username=self.instructor.username, password="test") - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) + def setup_course_url(self, course): + """ + Create URL for instructor dashboard + """ + self.url = reverse('instructor_dashboard', kwargs={'course_id': course.id.to_deprecated_string()}) - def test_pass_proctoring_tab_in_instructor_dashboard(self): + def setup_course(self, enable_proctored_exams, enable_timed_exams): """ - Test Pass Proctoring Tab is in the Instructor Dashboard + Create course based on proctored exams and timed exams values """ + self.course = CourseFactory.create(enable_proctored_exams=enable_proctored_exams, + enable_timed_exams=enable_timed_exams) + self.setup_course_url(self.course) + + @ddt.data( + (True, False), + (False, True) + ) + @ddt.unpack + def test_proctoring_tab_visible_for_global_staff(self, enable_proctored_exams, enable_timed_exams): + """ + Test Proctoring Tab is visible in the Instructor Dashboard + for global staff + """ + self.setup_course(enable_proctored_exams, enable_timed_exams) + self.instructor.is_staff = True self.instructor.save() - response = self.client.get(self.url) - self.assertIn(self.proctoring_link, response.content) - self.assertIn('Allowance Section', response.content) + # verify that proctoring tab is visible for global staff + self._assert_proctoring_tab_is_available() - def test_no_tab_non_global_staff(self): + @ddt.data( + (True, False), + (False, True) + ) + @ddt.unpack + def test_proctoring_tab_visible_for_course_staff_and_admin(self, enable_proctored_exams, enable_timed_exams): """ - Test Pass Proctoring Tab is not in the Instructor Dashboard - for non global staff users + Test Proctoring Tab is visible in the Instructor Dashboard + for course staff(role of STAFF or ADMIN) """ + self.setup_course(enable_proctored_exams, enable_timed_exams) + + self.instructor.is_staff = False + self.instructor.save() + + # verify that proctoring tab is visible for course staff + CourseStaffRole(self.course.id).add_users(self.instructor) + self._assert_proctoring_tab_is_available() + + # verify that proctoring tab is visible for course instructor + CourseStaffRole(self.course.id).remove_users(self.instructor) + CourseInstructorRole(self.course.id).add_users(self.instructor) + self._assert_proctoring_tab_is_available() + + @ddt.data( + (True, False), + (False, True) + ) + @ddt.unpack + def test_no_proctoring_tab_non_global_staff(self, enable_proctored_exams, enable_timed_exams): + """ + Test Proctoring Tab is not visible in the Instructor Dashboard + for course team other than role of staff or admin + """ + self.setup_course(enable_proctored_exams, enable_timed_exams) + self.instructor.is_staff = False self.instructor.save() @@ -62,14 +110,29 @@ class TestProctoringDashboardViews(SharedModuleStoreTestCase): self.assertNotIn('Allowance Section', response.content) @patch.dict(settings.FEATURES, {'ENABLE_SPECIAL_EXAMS': False}) - def test_no_tab_flag_unset(self): + @ddt.data( + (True, False), + (False, True) + ) + @ddt.unpack + def test_no_tab_flag_unset(self, enable_proctored_exams, enable_timed_exams): """ - Special Exams tab will not be visible if - the user is not a staff member. + Special Exams tab will not be visible if special exams settings are not enabled inspite of + proctored exams or timed exams is enabled """ + self.setup_course(enable_proctored_exams, enable_timed_exams) + self.instructor.is_staff = True self.instructor.save() response = self.client.get(self.url) self.assertNotIn(self.proctoring_link, response.content) self.assertNotIn('Allowance Section', response.content) + + def _assert_proctoring_tab_is_available(self): + """ + Asserts that proctoring tab is available for logged in user. + """ + response = self.client.get(self.url) + self.assertIn(self.proctoring_link, response.content) + self.assertIn('Allowance Section', response.content) diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index b4bce3ab0d..ea9fc15c30 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -49,7 +49,7 @@ from openedx.core.lib.url_utils import quote_slashes from openedx.core.lib.xblock_utils import wrap_xblock from shoppingcart.models import Coupon, CourseRegCodeItem, PaidCourseRegistration from student.models import CourseEnrollment -from student.roles import CourseFinanceAdminRole, CourseSalesAdminRole +from student.roles import CourseFinanceAdminRole, CourseSalesAdminRole, CourseStaffRole, CourseInstructorRole from util.json_request import JsonResponse from xmodule.html_module import HtmlDescriptor from xmodule.modulestore.django import modulestore @@ -174,13 +174,15 @@ def instructor_dashboard_2(request, course_id): # Gate access to Special Exam tab depending if either timed exams or proctored exams # are enabled in the course - # NOTE: For now, if we only have procotred exams enabled, then only platform Staff - # (user.is_staff) will be able to view the special exams tab. This may - # change in the future - can_see_special_exams = ( - ((course.enable_proctored_exams and request.user.is_staff) or course.enable_timed_exams) and - settings.FEATURES.get('ENABLE_SPECIAL_EXAMS', False) - ) + user_has_access = any([ + request.user.is_staff, + CourseStaffRole(course_key).has_user(request.user), + CourseInstructorRole(course_key).has_user(request.user) + ]) + course_has_special_exams = course.enable_proctored_exams or course.enable_timed_exams + can_see_special_exams = course_has_special_exams and user_has_access and settings.FEATURES.get( + 'ENABLE_SPECIAL_EXAMS', False) + if can_see_special_exams: sections.append(_section_special_exams(course, access))