test_lms_user_preview.py 13.5 KB
Newer Older
1 2
# -*- coding: utf-8 -*-
"""
3
Tests the "preview" selector in the LMS that allows changing between Staff, Student, and Content Groups.
4 5
"""

6
from ..helpers import UniqueCourseTest, create_user_partition_json
7 8 9
from ...pages.studio.auto_auth import AutoAuthPage
from ...pages.lms.courseware import CoursewarePage
from ...pages.lms.staff_view import StaffPage
10
from ...pages.lms.course_nav import CourseNavPage
11
from ...fixtures.course import CourseFixture, XBlockFixtureDesc
12
from xmodule.partitions.partitions import Group
13 14 15
from textwrap import dedent


16
class StaffViewTest(UniqueCourseTest):
17
    """
18
    Tests that verify the staff view.
19
    """
20
    USERNAME = "STAFF_TESTER"
21
    EMAIL = "johndoe@example.com"
22 23

    def setUp(self):
24
        super(StaffViewTest, self).setUp()
25 26 27 28

        self.courseware_page = CoursewarePage(self.browser, self.course_id)

        # Install a course with sections/problems, tabs, updates, and handouts
29
        self.course_fixture = CourseFixture(
30 31 32 33
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name']
        )

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
        self.populate_course_fixture(self.course_fixture)  # pylint: disable=no-member

        self.course_fixture.install()

        # Auto-auth register for the course.
        # Do this as global staff so that you will see the Staff View
        AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL,
                     course_id=self.course_id, staff=True).visit()

    def _goto_staff_page(self):
        """
        Open staff page with assertion
        """
        self.courseware_page.visit()
        staff_page = StaffPage(self.browser, self.course_id)
        self.assertEqual(staff_page.staff_view_mode, 'Staff')
        return staff_page


class CourseWithoutContentGroupsTest(StaffViewTest):
    """
    Setup for tests that have no content restricted to specific content groups.
    """

    def populate_course_fixture(self, course_fixture):
        """
        Populates test course with chapter, sequential, and 2 problems.
        """
62 63 64 65 66 67 68 69 70 71 72
        problem_data = dedent("""
            <problem markdown="Simple Problem" max_attempts="" weight="">
              <p>Choose Yes.</p>
              <choiceresponse>
                <checkboxgroup direction="vertical">
                  <choice correct="true">Yes</choice>
                </checkboxgroup>
              </choiceresponse>
            </problem>
        """)

73
        course_fixture.add_children(
74 75
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
76 77
                    XBlockFixtureDesc('problem', 'Test Problem 1', data=problem_data),
                    XBlockFixtureDesc('problem', 'Test Problem 2', data=problem_data)
78 79
                )
            )
80
        )
81

82

83
class StaffViewToggleTest(CourseWithoutContentGroupsTest):
84 85 86 87 88 89 90 91 92 93
    """
    Tests for the staff view toggle button.
    """
    def test_instructor_tab_visibility(self):
        """
        Test that the instructor tab is hidden when viewing as a student.
        """

        course_page = self._goto_staff_page()
        self.assertTrue(course_page.has_tab('Instructor'))
94 95
        course_page.set_staff_view_mode('Student')
        self.assertEqual(course_page.staff_view_mode, 'Student')
96 97 98
        self.assertFalse(course_page.has_tab('Instructor'))


99
class StaffDebugTest(CourseWithoutContentGroupsTest):
100 101 102
    """
    Tests that verify the staff debug info.
    """
103 104
    def test_reset_attempts_empty(self):
        """
105
        Test that we reset even when there is no student state
106 107 108 109 110
        """

        staff_debug_page = self._goto_staff_page().open_staff_debug_info()
        staff_debug_page.reset_attempts()
        msg = staff_debug_page.idash_msg[0]
111 112
        self.assertEqual(u'Successfully reset the attempts '
                         'for user {}'.format(self.USERNAME), msg)
113 114 115 116 117 118 119 120

    def test_delete_state_empty(self):
        """
        Test that we delete properly even when there isn't state to delete.
        """
        staff_debug_page = self._goto_staff_page().open_staff_debug_info()
        staff_debug_page.delete_state()
        msg = staff_debug_page.idash_msg[0]
121 122
        self.assertEqual(u'Successfully deleted student state '
                         'for user {}'.format(self.USERNAME), msg)
123 124 125 126 127 128 129 130

    def test_reset_attempts_state(self):
        """
        Successfully reset the student attempts
        """
        staff_page = self._goto_staff_page()
        staff_page.answer_problem()

131 132
        staff_debug_page = staff_page.open_staff_debug_info()
        staff_debug_page.reset_attempts()
133
        msg = staff_debug_page.idash_msg[0]
134 135
        self.assertEqual(u'Successfully reset the attempts '
                         'for user {}'.format(self.USERNAME), msg)
136

137 138 139 140 141 142 143 144 145 146
    def test_rescore_state(self):
        """
        Rescore the student
        """
        staff_page = self._goto_staff_page()
        staff_page.answer_problem()

        staff_debug_page = staff_page.open_staff_debug_info()
        staff_debug_page.rescore()
        msg = staff_debug_page.idash_msg[0]
147
        self.assertEqual(u'Successfully rescored problem for user STAFF_TESTER', msg)
148 149

    def test_student_state_delete(self):
150 151 152 153 154 155 156 157 158
        """
        Successfully delete the student state with an answer
        """
        staff_page = self._goto_staff_page()
        staff_page.answer_problem()

        staff_debug_page = staff_page.open_staff_debug_info()
        staff_debug_page.delete_state()
        msg = staff_debug_page.idash_msg[0]
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
        self.assertEqual(u'Successfully deleted student state '
                         'for user {}'.format(self.USERNAME), msg)

    def test_student_by_email(self):
        """
        Successfully reset the student attempts using their email address
        """
        staff_page = self._goto_staff_page()
        staff_page.answer_problem()

        staff_debug_page = staff_page.open_staff_debug_info()
        staff_debug_page.reset_attempts(self.EMAIL)
        msg = staff_debug_page.idash_msg[0]
        self.assertEqual(u'Successfully reset the attempts '
                         'for user {}'.format(self.EMAIL), msg)

    def test_bad_student(self):
        """
        Test negative response with invalid user
        """
        staff_page = self._goto_staff_page()
        staff_page.answer_problem()

        staff_debug_page = staff_page.open_staff_debug_info()
        staff_debug_page.delete_state('INVALIDUSER')
        msg = staff_debug_page.idash_msg[0]
185
        self.assertEqual(u'Failed to delete student state. '
186
                         'User does not exist.', msg)
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212

    def test_reset_attempts_for_problem_loaded_via_ajax(self):
        """
        Successfully reset the student attempts for problem loaded via ajax.
        """
        staff_page = self._goto_staff_page()
        staff_page.load_problem_via_ajax()
        staff_page.answer_problem()

        staff_debug_page = staff_page.open_staff_debug_info()
        staff_debug_page.reset_attempts()
        msg = staff_debug_page.idash_msg[0]
        self.assertEqual(u'Successfully reset the attempts '
                         'for user {}'.format(self.USERNAME), msg)

    def test_rescore_state_for_problem_loaded_via_ajax(self):
        """
        Rescore the student for problem loaded via ajax.
        """
        staff_page = self._goto_staff_page()
        staff_page.load_problem_via_ajax()
        staff_page.answer_problem()

        staff_debug_page = staff_page.open_staff_debug_info()
        staff_debug_page.rescore()
        msg = staff_debug_page.idash_msg[0]
213
        self.assertEqual(u'Successfully rescored problem for user STAFF_TESTER', msg)
214 215 216 217 218 219 220 221 222 223 224 225 226 227

    def test_student_state_delete_for_problem_loaded_via_ajax(self):
        """
        Successfully delete the student state for problem loaded via ajax.
        """
        staff_page = self._goto_staff_page()
        staff_page.load_problem_via_ajax()
        staff_page.answer_problem()

        staff_debug_page = staff_page.open_staff_debug_info()
        staff_debug_page.delete_state()
        msg = staff_debug_page.idash_msg[0]
        self.assertEqual(u'Successfully deleted student state '
                         'for user {}'.format(self.USERNAME), msg)
228 229 230 231


class CourseWithContentGroupsTest(StaffViewTest):
    """
232
    Verifies that changing the "View this course as" selector works properly for content groups.
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
    """

    def setUp(self):
        super(CourseWithContentGroupsTest, self).setUp()
        # pylint: disable=protected-access
        self.course_fixture._update_xblock(self.course_fixture._course_location, {
            "metadata": {
                u"user_partitions": [
                    create_user_partition_json(
                        0,
                        'Configuration alpha,beta',
                        'Content Group Partition',
                        [Group("0", 'alpha'), Group("1", 'beta')],
                        scheme="cohort"
                    )
                ],
            },
        })

    def populate_course_fixture(self, course_fixture):
        """
        Populates test course with chapter, sequential, and 3 problems.
        One problem is visible to all, one problem is visible only to Group "alpha", and
        one problem is visible only to Group "beta".
        """
        problem_data = dedent("""
            <problem markdown="Simple Problem" max_attempts="" weight="">
              <p>Choose Yes.</p>
              <choiceresponse>
                <checkboxgroup direction="vertical">
                  <choice correct="true">Yes</choice>
                </checkboxgroup>
              </choiceresponse>
            </problem>
        """)

269 270 271 272
        self.alpha_text = "VISIBLE TO ALPHA"
        self.beta_text = "VISIBLE TO BETA"
        self.everyone_text = "VISIBLE TO EVERYONE"

273 274 275
        course_fixture.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
276 277 278 279 280 281 282 283 284
                    XBlockFixtureDesc('vertical', 'Test Unit').add_children(
                        XBlockFixtureDesc(
                            'problem', self.alpha_text, data=problem_data, metadata={"group_access": {0: [0]}}
                        ),
                        XBlockFixtureDesc(
                            'problem', self.beta_text, data=problem_data, metadata={"group_access": {0: [1]}}
                        ),
                        XBlockFixtureDesc('problem', self.everyone_text, data=problem_data)
                    )
285 286 287 288 289 290 291 292 293 294 295 296
                )
            )
        )

    def test_staff_sees_all_problems(self):
        """
        Scenario: Staff see all problems
        Given I have a course with a cohort user partition
        And problems that are associated with specific groups in the user partition
        When I view the courseware in the LMS with staff access
        Then I see all the problems, regardless of their group_access property
        """
297 298
        course_page = self._goto_staff_page()
        verify_expected_problem_visibility(self, course_page, [self.alpha_text, self.beta_text, self.everyone_text])
299 300 301 302 303 304 305 306 307 308 309 310

    def test_student_not_in_content_group(self):
        """
        Scenario: When previewing as a student, only content visible to all is shown
        Given I have a course with a cohort user partition
        And problems that are associated with specific groups in the user partition
        When I view the courseware in the LMS with staff access
        And I change to previewing as a Student
        Then I see only problems visible to all users
        """
        course_page = self._goto_staff_page()
        course_page.set_staff_view_mode('Student')
311
        verify_expected_problem_visibility(self, course_page, [self.everyone_text])
312 313 314 315 316 317 318 319 320 321 322 323

    def test_as_student_in_alpha(self):
        """
        Scenario: When previewing as a student in group alpha, only content visible to alpha is shown
        Given I have a course with a cohort user partition
        And problems that are associated with specific groups in the user partition
        When I view the courseware in the LMS with staff access
        And I change to previewing as a Student in group alpha
        Then I see only problems visible to group alpha
        """
        course_page = self._goto_staff_page()
        course_page.set_staff_view_mode('Student in alpha')
324
        verify_expected_problem_visibility(self, course_page, [self.alpha_text, self.everyone_text])
325 326 327 328 329 330 331 332 333 334 335 336

    def test_as_student_in_beta(self):
        """
        Scenario: When previewing as a student in group beta, only content visible to beta is shown
        Given I have a course with a cohort user partition
        And problems that are associated with specific groups in the user partition
        When I view the courseware in the LMS with staff access
        And I change to previewing as a Student in group beta
        Then I see only problems visible to group beta
        """
        course_page = self._goto_staff_page()
        course_page.set_staff_view_mode('Student in beta')
337 338 339 340 341 342 343 344 345 346 347 348
        verify_expected_problem_visibility(self, course_page, [self.beta_text, self.everyone_text])


def verify_expected_problem_visibility(test, courseware_page, expected_problems):
    """
    Helper method that checks that the expected problems are visible on the current page.
    """
    test.assertEqual(
        len(expected_problems), courseware_page.num_xblock_components, "Incorrect number of visible problems"
    )
    for index, expected_problem in enumerate(expected_problems):
        test.assertIn(expected_problem, courseware_page.xblock_components[index].text)