diff --git a/common/djangoapps/xmodule_modifiers.py b/common/djangoapps/xmodule_modifiers.py index fbad2dad4a..403a50fab4 100644 --- a/common/djangoapps/xmodule_modifiers.py +++ b/common/djangoapps/xmodule_modifiers.py @@ -157,7 +157,7 @@ def grade_histogram(module_id): return grades -def add_staff_markup(user, block, view, frag, context): # pylint: disable=unused-argument +def add_staff_markup(user, has_instructor_access, block, view, frag, context): # pylint: disable=unused-argument """ Updates the supplied module with a new get_html function that wraps the output of the old get_html function with additional information @@ -245,5 +245,6 @@ def add_staff_markup(user, block, view, frag, context): # pylint: disable=unuse 'render_histogram': render_histogram, 'block_content': frag.content, 'is_released': is_released, + 'has_instructor_access': has_instructor_access, } return wrap_fragment(frag, render_to_string("staff_problem_info.html", staff_context)) diff --git a/lms/djangoapps/courseware/access.py b/lms/djangoapps/courseware/access.py index 6f11943923..9badda2815 100644 --- a/lms/djangoapps/courseware/access.py +++ b/lms/djangoapps/courseware/access.py @@ -274,8 +274,9 @@ def _has_access_descriptor(user, action, descriptor, course_key=None): checkers = { 'load': can_load, - 'staff': lambda: _has_staff_access_to_descriptor(user, descriptor, course_key) - } + 'staff': lambda: _has_staff_access_to_descriptor(user, descriptor, course_key), + 'instructor': lambda: _has_instructor_access_to_descriptor(user, descriptor, course_key) + } return _dispatch(checkers, action, user, descriptor) diff --git a/lms/djangoapps/courseware/features/staff_debug_info.feature b/lms/djangoapps/courseware/features/staff_debug_info.feature new file mode 100644 index 0000000000..519e4b3c13 --- /dev/null +++ b/lms/djangoapps/courseware/features/staff_debug_info.feature @@ -0,0 +1,13 @@ +@shard_1 +Feature: LMS.Debug staff info links + As a course staff in an edX course + In order to test my understanding of the material + I want to click on staff debug info links + + Scenario: I can reset student attempts + When i am staff member for the course "model_course" + And I am viewing a "multiple choice" problem + And I can view staff debug info + Then I can reset student attempts + Then I cannot see delete student state link + Then I cannot see rescore student submission link diff --git a/lms/djangoapps/courseware/features/staff_debug_info.py b/lms/djangoapps/courseware/features/staff_debug_info.py new file mode 100644 index 0000000000..9d183a5be9 --- /dev/null +++ b/lms/djangoapps/courseware/features/staff_debug_info.py @@ -0,0 +1,51 @@ +""" +Steps for staff_debug_info.feature lettuce tests +""" + +from django.contrib.auth.models import User +from lettuce import world, step +from common import create_course, course_id +from courseware.courses import get_course_by_id +from instructor.access import allow_access + + +@step(u'i am staff member for the course "([^"]*)"$') +def i_am_staff_member_for_the_course(step, course_number): + # Create the course + create_course(step, course_number) + course = get_course_by_id(course_id(course_number)) + + # Create the user + world.create_user('robot', 'test') + user = User.objects.get(username='robot') + + # Add user as a course staff. + allow_access(course, user, "staff") + + world.log_in(username='robot', password='test') + + +@step(u'I can view staff debug info') +def view_staff_debug_info(step): + css_selector = "a.instructor-info-action" + world.css_click(css_selector) + world.wait_for_visible("section.staff-modal") + + +@step(u'I can reset student attempts') +def view_staff_debug_info(step): + css_selector = "a.staff-debug-reset" + world.css_click(css_selector) + world.wait_for_ajax_complete() + + +@step(u'I cannot see delete student state link') +def view_staff_debug_info(step): + css_selector = "a.staff-debug-sdelete" + world.is_css_not_present(css_selector) + + +@step(u'I cannot see rescore student submission link') +def view_staff_debug_info(step): + css_selector = "a.staff-debug-rescore" + world.is_css_not_present(css_selector) diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 3976a00fec..aaa1e02814 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -433,7 +433,8 @@ def get_module_system_for_user(user, field_data_cache, if settings.FEATURES.get('DISPLAY_DEBUG_INFO_TO_STAFF'): if has_access(user, 'staff', descriptor, course_id): - block_wrappers.append(partial(add_staff_markup, user)) + has_instructor_access = has_access(user, 'instructor', descriptor, course_id) + block_wrappers.append(partial(add_staff_markup, user, has_instructor_access)) # These modules store data using the anonymous_student_id as a key. # To prevent loss of data, we will continue to provide old modules with diff --git a/lms/djangoapps/courseware/tests/test_access.py b/lms/djangoapps/courseware/tests/test_access.py index fdee101347..e353c5bea6 100644 --- a/lms/djangoapps/courseware/tests/test_access.py +++ b/lms/djangoapps/courseware/tests/test_access.py @@ -90,6 +90,7 @@ class AccessTestCase(TestCase): # Always returns true because DISABLE_START_DATES is set in test.py self.assertTrue(access._has_access_descriptor(user, 'load', date)) + self.assertTrue(access._has_access_descriptor(user, 'instructor', date)) with self.assertRaises(ValueError): access._has_access_descriptor(user, 'not_load_or_staff', date) diff --git a/lms/templates/staff_problem_info.html b/lms/templates/staff_problem_info.html index d9a170089c..cef8e430b0 100644 --- a/lms/templates/staff_problem_info.html +++ b/lms/templates/staff_problem_info.html @@ -64,10 +64,12 @@ ${block_content}
[ ${_('Reset Student Attempts')} + % if has_instructor_access: | ${_('Delete Student State')} | ${_('Rescore Student Submission')} + % endif ]