Beispiel #1
0
    def test_course_updated_with_entrance_exam(self):
        """
        Given that I visit an empty course before import
        I should not see a section named 'Section' or 'Entrance Exam'
        When I visit the import page
        And I upload a course that has an entrance exam section named 'Entrance Exam'
        And I visit the course outline page again
        The section named 'Entrance Exam' should now be available.
        And when I switch the view mode to student view and Visit CourseWare
        Then I see one section in the sidebar that is 'Entrance Exam'
        """
        self.landing_page.visit()
        # Should not exist yet.
        self.assertRaises(IndexError, self.landing_page.section, "Section")
        self.assertRaises(IndexError, self.landing_page.section,
                          "Entrance Exam")
        self.import_page.visit()
        self.import_page.wait_for_choose_file_click_handler()
        self.import_page.upload_tarball(self.tarball_name)
        self.import_page.wait_for_upload()
        self.landing_page.visit()
        # There should be two sections. 'Entrance Exam' and 'Section' on the landing page.
        self.landing_page.section("Entrance Exam")
        self.landing_page.section("Section")

        self.landing_page.view_live()
        courseware = CoursewarePage(self.browser, self.course_id)
        courseware.wait_for_page()
        StaffCoursewarePage(self.browser,
                            self.course_id).set_staff_view_mode('Student')
        self.assertEqual(courseware.num_sections, 1)
        self.assertIn("To access course materials, you must score",
                      courseware.entrance_exam_message_selector.text[0])
    def test_course_updated_with_entrance_exam(self):
        """
        Given that I visit an empty course before import
        I should not see a section named 'Section' or 'Entrance Exam'
        When I visit the import page
        And I upload a course that has an entrance exam section named 'Entrance Exam'
        And I visit the course outline page again
        The section named 'Entrance Exam' should now be available.
        And when I switch the view mode to student view and Visit CourseWare
        Then I see one section in the sidebar that is 'Entrance Exam'
        """
        self.landing_page.visit()
        # Should not exist yet.
        self.assertRaises(IndexError, self.landing_page.section, "Section")
        self.assertRaises(IndexError, self.landing_page.section, "Entrance Exam")
        self.import_page.visit()
        self.import_page.upload_tarball(self.tarball_name)
        self.import_page.wait_for_upload()
        self.landing_page.visit()
        # There should be two sections. 'Entrance Exam' and 'Section' on the landing page.
        self.landing_page.section("Entrance Exam")
        self.landing_page.section("Section")

        self.landing_page.view_live()
        courseware = CoursewarePage(self.browser, self.course_id)
        courseware.wait_for_page()
        StaffPage(self.browser, self.course_id).set_staff_view_mode('Student')
        self.assertEqual(courseware.num_sections, 1)
        self.assertIn(
            "To access course materials, you must score", courseware.entrance_exam_message_selector.text[0]
        )
 def resume_course_from_header(self):
     """
     Navigate to courseware using Resume Course button in the header.
     """
     self.q(css=self.HEADER_RESUME_COURSE_SELECTOR).first.click()
     courseware_page = CoursewarePage(self.browser, self.course_id)
     courseware_page.wait_for_page()
Beispiel #4
0
    def test_hinted_login(self):
        """ Test the login page when coming from course URL that specified which third party provider to use """
        # Create a user account and link it to third party auth with the dummy provider:
        AutoAuthPage(self.browser, course_id=self.course_id).visit()
        self._link_dummy_account()
        try:
            LogoutPage(self.browser).visit()

            # When not logged in, try to load a course URL that includes the provider hint ?tpa_hint=...
            course_page = CoursewarePage(self.browser, self.course_id)
            self.browser.get(course_page.url + '?tpa_hint=oa2-dummy')

            # We should now be redirected to the login page
            self.login_page.wait_for_page()
            self.assertIn(
                "Would you like to sign in using your Dummy credentials?",
                self.login_page.hinted_login_prompt)

            # Baseline screen-shots are different for chrome and firefox.
            #self.assertScreenshot('#hinted-login-form', 'hinted-login-{}'.format(self.browser.name), .25)
            #The line above is commented out temporarily see SOL-1937
            self.login_page.click_third_party_dummy_provider()

            # We should now be redirected to the course page
            course_page.wait_for_page()
        finally:
            self._unlink_dummy_account()
Beispiel #5
0
    def test_hinted_login(self):
        """ Test the login page when coming from course URL that specified which third party provider to use """
        # Create a user account and link it to third party auth with the dummy provider:
        AutoAuthPage(self.browser, course_id=self.course_id).visit()
        self._link_dummy_account()
        try:
            LogoutPage(self.browser).visit()

            # When not logged in, try to load a course URL that includes the provider hint ?tpa_hint=...
            course_page = CoursewarePage(self.browser, self.course_id)
            self.browser.get(course_page.url + '?tpa_hint=oa2-dummy')

            # We should now be redirected to the login page
            self.login_page.wait_for_page()
            self.assertIn(
                "Would you like to sign in using your Dummy credentials?",
                self.login_page.hinted_login_prompt
            )

            # Baseline screen-shots are different for chrome and firefox.
            #self.assertScreenshot('#hinted-login-form', 'hinted-login-{}'.format(self.browser.name), .25)
            #The line above is commented out temporarily see SOL-1937
            self.login_page.click_third_party_dummy_provider()

            # We should now be redirected to the course page
            course_page.wait_for_page()
        finally:
            self._unlink_dummy_account()
    def test_course_rerun(self):
        """
        Scenario: Courses can be rerun
            Given I have a course with a section, subsesction, vertical, and html component with content 'Test Content'
            When I visit the course rerun page
            And I type 'test_rerun' in the course run field
            And I click Create Rerun
            And I visit the course listing page
            And I wait for all courses to finish processing
            And I click on the course with run 'test_rerun'
            Then I see a rerun notification on the course outline page
            And when I click 'Dismiss' on the notification
            Then I do not see a rerun notification
            And when I expand the subsection and click on the unit
            And I click 'View Live Version'
            Then I see one html component with the content 'Test Content'
        """
        course_info = (self.course_info['org'], self.course_info['number'], self.course_info['run'])
        updated_course_info = course_info[0] + "+" + course_info[1] + "+" + course_info[2]

        self.dashboard_page.visit()
        self.dashboard_page.scroll_to_course(course_info[1])
        self.dashboard_page.create_rerun(updated_course_info)

        rerun_page = CourseRerunPage(self.browser, *course_info)
        rerun_page.wait_for_page()
        course_run = 'test_rerun_' + str(random.randrange(1000000, 9999999))
        rerun_page.course_run = course_run
        rerun_page.create_rerun()

        def finished_processing():
            self.dashboard_page.visit()
            return not self.dashboard_page.has_processing_courses

        EmptyPromise(finished_processing, "Rerun finished processing", try_interval=5, timeout=60).fulfill()

        assert course_run in self.dashboard_page.course_runs
        self.dashboard_page.click_course_run(course_run)

        outline_page = CourseOutlinePage(self.browser, *course_info)
        outline_page.wait_for_page()
        self.assertTrue(outline_page.has_rerun_notification)

        outline_page.dismiss_rerun_notification()
        EmptyPromise(lambda: not outline_page.has_rerun_notification, "Rerun notification dismissed").fulfill()

        subsection = outline_page.section(self.SECTION_NAME).subsection(self.SUBSECITON_NAME)
        subsection.expand_subsection()
        unit_page = subsection.unit(self.UNIT_NAME).go_to()

        unit_page.view_published_version()
        courseware = CoursewarePage(self.browser, self.course_id)
        courseware.wait_for_page()
        self.assertEqual(courseware.num_xblock_components, 1)
        self.assertEqual(courseware.xblock_component_html_content(), self.COMPONENT_CONTENT)
    def test_course_rerun(self):
        """
        Scenario: Courses can be rerun
            Given I have a course with a section, subsesction, vertical, and html component with content 'Test Content'
            When I visit the course rerun page
            And I type 'test_rerun' in the course run field
            And I click Create Rerun
            And I visit the course listing page
            And I wait for all courses to finish processing
            And I click on the course with run 'test_rerun'
            Then I see a rerun notification on the course outline page
            And when I click 'Dismiss' on the notification
            Then I do not see a rerun notification
            And when I expand the subsection and click on the unit
            And I click 'View Live Version'
            Then I see one html component with the content 'Test Content'
        """
        course_info = (self.course_info['org'], self.course_info['number'], self.course_info['run'])
        updated_course_info = course_info[0] + "+" + course_info[1] + "+" + course_info[2]

        self.dashboard_page.visit()
        self.dashboard_page.scroll_to_course(course_info[1])
        self.dashboard_page.create_rerun(updated_course_info)

        rerun_page = CourseRerunPage(self.browser, *course_info)
        rerun_page.wait_for_page()
        course_run = 'test_rerun_' + str(random.randrange(1000000, 9999999))
        rerun_page.course_run = course_run
        rerun_page.create_rerun()

        def finished_processing():
            self.dashboard_page.visit()
            return not self.dashboard_page.has_processing_courses

        EmptyPromise(finished_processing, "Rerun finished processing", try_interval=5, timeout=60).fulfill()

        assert_in(course_run, self.dashboard_page.course_runs)
        self.dashboard_page.click_course_run(course_run)

        outline_page = CourseOutlinePage(self.browser, *course_info)
        outline_page.wait_for_page()
        self.assertTrue(outline_page.has_rerun_notification)

        outline_page.dismiss_rerun_notification()
        EmptyPromise(lambda: not outline_page.has_rerun_notification, "Rerun notification dismissed").fulfill()

        subsection = outline_page.section(self.SECTION_NAME).subsection(self.SUBSECITON_NAME)
        subsection.expand_subsection()
        unit_page = subsection.unit(self.UNIT_NAME).go_to()

        unit_page.view_published_version()
        courseware = CoursewarePage(self.browser, self.course_id)
        courseware.wait_for_page()
        self.assertEqual(courseware.num_xblock_components, 1)
        self.assertEqual(courseware.xblock_component_html_content(), self.COMPONENT_CONTENT)
    def _wait_for_course_section(self, section_title, subsection_title):
        """
        Ensures the user navigates to the course content page with the correct section and subsection.
        """
        courseware_page = CoursewarePage(self.browser,
                                         self.parent_page.course_id)
        courseware_page.wait_for_page()

        # TODO: TNL-6546: Remove this if/visit_unified_course_view
        if self.parent_page.unified_course_view:
            courseware_page.nav.visit_unified_course_view()

        self.wait_for(
            promise_check_func=lambda: courseware_page.nav.is_on_section(
                section_title, subsection_title),
            description=
            "Waiting for course page with section '{0}' and subsection '{1}'".
            format(section_title, subsection_title))
Beispiel #9
0
    def test_entrance_exam_section_2(self):
        """
         Scenario: Any course that is enabled for an entrance exam, should have entrance exam chapter at course
         page.
            Given that I am on the course page
            When I view the course that has an entrance exam
            Then there should be an "Entrance Exam" chapter.'
        """
        courseware_page = CoursewarePage(self.browser, self.course_id)
        entrance_exam_link_selector = '.accordion .course-navigation .chapter .group-heading'
        # visit course page and make sure there is not entrance exam chapter.
        courseware_page.visit()
        courseware_page.wait_for_page()
        self.assertFalse(
            element_has_text(page=courseware_page,
                             css_selector=entrance_exam_link_selector,
                             text='Entrance Exam'))

        # Logout and login as a staff.
        LogoutPage(self.browser).visit()
        AutoAuthPage(self.browser, course_id=self.course_id,
                     staff=True).visit()

        # visit course settings page and set/enabled entrance exam for that course.
        self.settings_page.visit()
        self.settings_page.require_entrance_exam()
        self.settings_page.save_changes()

        # Logout and login as a student.
        LogoutPage(self.browser).visit()
        AutoAuthPage(self.browser, course_id=self.course_id,
                     staff=False).visit()

        # visit course info page and make sure there is an "Entrance Exam" section.
        courseware_page.visit()
        courseware_page.wait_for_page()
        self.assertTrue(
            element_has_text(page=courseware_page,
                             css_selector=entrance_exam_link_selector,
                             text='Entrance Exam'))
Beispiel #10
0
    def test_entrance_exam_section_2(self):
        """
         Scenario: Any course that is enabled for an entrance exam, should have entrance exam chapter at course
         page.
            Given that I am on the course page
            When I view the course that has an entrance exam
            Then there should be an "Entrance Exam" chapter.'
        """
        courseware_page = CoursewarePage(self.browser, self.course_id)
        entrance_exam_link_selector = '.accordion .course-navigation .chapter .group-heading'
        # visit course page and make sure there is not entrance exam chapter.
        courseware_page.visit()
        courseware_page.wait_for_page()
        self.assertFalse(element_has_text(
            page=courseware_page,
            css_selector=entrance_exam_link_selector,
            text='Entrance Exam'
        ))

        # Logout and login as a staff.
        LogoutPage(self.browser).visit()
        AutoAuthPage(self.browser, course_id=self.course_id, staff=True).visit()

        # visit course settings page and set/enabled entrance exam for that course.
        self.settings_page.visit()
        self.settings_page.require_entrance_exam()
        self.settings_page.save_changes()

        # Logout and login as a student.
        LogoutPage(self.browser).visit()
        AutoAuthPage(self.browser, course_id=self.course_id, staff=False).visit()

        # visit course info page and make sure there is an "Entrance Exam" section.
        courseware_page.visit()
        courseware_page.wait_for_page()
        self.assertTrue(element_has_text(
            page=courseware_page,
            css_selector=entrance_exam_link_selector,
            text='Entrance Exam'
        ))
Beispiel #11
0
class CourseOutlinePage(PageObject):
    """
    Course outline fragment of page.
    """

    url = None

    def __init__(self, browser, parent_page):
        super(CourseOutlinePage, self).__init__(browser)
        self.parent_page = parent_page
        self.courseware_page = CoursewarePage(self.browser,
                                              self.parent_page.course_id)

    def is_browser_on_page(self):
        return self.parent_page.is_browser_on_page

    @property
    def sections(self):
        """
        Return a dictionary representation of sections and subsections.

        Example:

            {
                'Introduction': ['Course Overview'],
                'Week 1': ['Lesson 1', 'Lesson 2', 'Homework']
                'Final Exam': ['Final Exam']
            }

        You can use these titles in `go_to_section` to navigate to the section.
        """
        # Dict to store the result
        outline_dict = dict()

        section_titles = self._section_titles()

        # Get the section titles for each chapter
        for sec_index, sec_title in enumerate(section_titles):

            if len(section_titles) < 1:
                self.warning(
                    "Could not find subsections for '{0}'".format(sec_title))
            else:
                # Add one to convert list index (starts at 0) to CSS index (starts at 1)
                outline_dict[sec_title] = self._subsection_titles(sec_index +
                                                                  1)

        return outline_dict

    def go_to_section(self, section_title, subsection_title):
        """
        Go to the section in the courseware.
        Every section must have at least one subsection, so specify
        both the section and subsection title.

        Example:
            go_to_section("Week 1", "Lesson 1")
        """

        # Get the section by index
        try:
            section_index = self._section_titles().index(section_title)
        except ValueError:
            self.warning("Could not find section '{0}'".format(section_title))
            return

        # Get the subsection by index
        try:
            subsection_index = self._subsection_titles(
                section_index + 1).index(subsection_title)
        except ValueError:
            msg = "Could not find subsection '{0}' in section '{1}'".format(
                subsection_title, section_title)
            self.warning(msg)
            return

        # Convert list indices (start at zero) to CSS indices (start at 1)
        subsection_css = (
            ".outline-item.section:nth-of-type({0}) .subsection:nth-of-type({1}) .outline-item"
        ).format(section_index + 1, subsection_index + 1)

        # Click the subsection and ensure that the page finishes reloading
        self.q(css=subsection_css).first.click()
        self.courseware_page.wait_for_page()

        # TODO: TNL-6546: Remove this if/visit_unified_course_view
        if self.parent_page.unified_course_view:
            self.courseware_page.nav.visit_unified_course_view()

        self._wait_for_course_section(section_title, subsection_title)

    def _section_titles(self):
        """
        Return a list of all section titles on the page.
        """
        section_css = '.section-name span'
        return self.q(css=section_css).map(lambda el: el.text.strip()).results

    def _subsection_titles(self, section_index):
        """
        Return a list of all subsection titles on the page
        for the section at index `section_index` (starts at 1).
        """
        # Retrieve the subsection title for the section
        # Add one to the list index to get the CSS index, which starts at one
        subsection_css = (
            # TODO: TNL-6387: Will need to switch to this selector for subsections
            # ".outline-item.section:nth-of-type({0}) .subsection span:nth-of-type(1)"
            ".outline-item.section:nth-of-type({0}) .subsection a"
        ).format(section_index)

        return self.q(css=subsection_css).map(
            lambda el: el.get_attribute('innerHTML').strip()).results

    def _wait_for_course_section(self, section_title, subsection_title):
        """
        Ensures the user navigates to the course content page with the correct section and subsection.
        """
        self.wait_for(
            promise_check_func=lambda: self.courseware_page.nav.is_on_section(
                section_title, subsection_title),
            description=
            "Waiting for course page with section '{0}' and subsection '{1}'".
            format(section_title, subsection_title))
Beispiel #12
0
class GatingTest(UniqueCourseTest):
    """
    Test gating feature in LMS.
    """
    STAFF_USERNAME = "******"
    STAFF_EMAIL = "*****@*****.**"

    STUDENT_USERNAME = "******"
    STUDENT_EMAIL = "*****@*****.**"

    def setUp(self):
        super(GatingTest, self).setUp()

        self.logout_page = LogoutPage(self.browser)
        self.course_home_page = CourseHomePage(self.browser, self.course_id)
        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.studio_course_outline = StudioCourseOutlinePage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )

        xml = dedent("""
        <problem>
        <p>What is height of eiffel tower without the antenna?.</p>
        <multiplechoiceresponse>
          <choicegroup label="What is height of eiffel tower without the antenna?" type="MultipleChoice">
            <choice correct="false">324 meters<choicehint>Antenna is 24 meters high</choicehint></choice>
            <choice correct="true">300 meters</choice>
            <choice correct="false">224 meters</choice>
            <choice correct="false">400 meters</choice>
          </choicegroup>
        </multiplechoiceresponse>
        </problem>
        """)
        self.problem1 = XBlockFixtureDesc('problem', 'HEIGHT OF EIFFEL TOWER', data=xml)

        # Install a course with sections/problems
        course_fixture = CourseFixture(
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run'],
            self.course_info['display_name']
        )
        course_fixture.add_advanced_settings({
            "enable_subsection_gating": {"value": "true"}
        })

        course_fixture.add_children(
            XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children(
                    self.problem1
                ),
                XBlockFixtureDesc('sequential', 'Test Subsection 2').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 2')
                )
            )
        ).install()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        self.logout_page.visit()
        AutoAuthPage(self.browser, username=username, email=email,
                     course_id=self.course_id, staff=staff).visit()

    def _setup_prereq(self):
        """
        Make the first subsection a prerequisite
        """
        # Login as staff
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)

        # Make the first subsection a prerequisite
        self.studio_course_outline.visit()
        self.studio_course_outline.open_subsection_settings_dialog(0)
        self.studio_course_outline.select_advanced_tab(desired_item='gated_content')
        self.studio_course_outline.make_gating_prerequisite()

    def _setup_gated_subsection(self):
        """
        Gate the second subsection on the first subsection
        """
        # Login as staff
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)

        # Gate the second subsection based on the score achieved in the first subsection
        self.studio_course_outline.visit()
        self.studio_course_outline.open_subsection_settings_dialog(1)
        self.studio_course_outline.select_advanced_tab(desired_item='gated_content')
        self.studio_course_outline.add_prerequisite_to_subsection("80")

    def _fulfill_prerequisite(self):
        """
        Fulfill the prerequisite needed to see gated content
        """
        problem_page = ProblemPage(self.browser)
        self.assertEqual(problem_page.wait_for_page().problem_name, 'HEIGHT OF EIFFEL TOWER')
        problem_page.click_choice('choice_1')
        problem_page.click_submit()

    def test_subsection_gating_in_studio(self):
        """
        Given that I am a staff member
        When I visit the course outline page in studio.
        And open the subsection edit dialog
        Then I can view all settings related to Gating
        And update those settings to gate a subsection
        """
        self._setup_prereq()

        # Assert settings are displayed correctly for a prerequisite subsection
        self.studio_course_outline.visit()
        self.studio_course_outline.open_subsection_settings_dialog(0)
        self.studio_course_outline.select_advanced_tab(desired_item='gated_content')
        self.assertTrue(self.studio_course_outline.gating_prerequisite_checkbox_is_visible())
        self.assertTrue(self.studio_course_outline.gating_prerequisite_checkbox_is_checked())
        self.assertFalse(self.studio_course_outline.gating_prerequisites_dropdown_is_visible())
        self.assertFalse(self.studio_course_outline.gating_prerequisite_min_score_is_visible())

        self._setup_gated_subsection()

        # Assert settings are displayed correctly for a gated subsection
        self.studio_course_outline.visit()
        self.studio_course_outline.open_subsection_settings_dialog(1)
        self.studio_course_outline.select_advanced_tab(desired_item='gated_content')
        self.assertTrue(self.studio_course_outline.gating_prerequisite_checkbox_is_visible())
        self.assertTrue(self.studio_course_outline.gating_prerequisites_dropdown_is_visible())
        self.assertTrue(self.studio_course_outline.gating_prerequisite_min_score_is_visible())

    def test_gated_subsection_in_lms_for_student(self):
        """
        Given that I am a student
        When I visit the LMS Courseware
        Then I cannot see a gated subsection
        When I fulfill the gating Prerequisite
        Then I can see the gated subsection
        """
        self._setup_prereq()
        self._setup_gated_subsection()

        self._auto_auth(self.STUDENT_USERNAME, self.STUDENT_EMAIL, False)

        self.course_home_page.visit()
        self.assertEqual(self.course_home_page.outline.num_subsections, 1)

        # Fulfill prerequisite and verify that gated subsection is shown
        self.courseware_page.visit()
        self._fulfill_prerequisite()
        self.course_home_page.visit()
        self.assertEqual(self.course_home_page.outline.num_subsections, 2)

    def test_gated_subsection_in_lms_for_staff(self):
        """
        Given that I am a staff member
        When I visit the LMS Courseware
        Then I can see all gated subsections
        Displayed along with notification banners
        Then if I masquerade as a student
        Then I cannot see a gated subsection
        When I fufill the gating prerequisite
        Then I can see the gated subsection (without a banner)
        """
        self._setup_prereq()
        self._setup_gated_subsection()

        # Fulfill prerequisites for specific student
        self._auto_auth(self.STUDENT_USERNAME, self.STUDENT_EMAIL, False)
        self.courseware_page.visit()
        self._fulfill_prerequisite()

        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)

        self.course_home_page.visit()
        self.assertEqual(self.course_home_page.preview.staff_view_mode, 'Staff')
        self.assertEqual(self.course_home_page.outline.num_subsections, 2)

        # Click on gated section and check for banner
        self.course_home_page.outline.go_to_section('Test Section 1', 'Test Subsection 2')
        self.courseware_page.wait_for_page()
        self.assertTrue(self.courseware_page.has_banner())

        self.course_home_page.visit()
        self.course_home_page.outline.go_to_section('Test Section 1', 'Test Subsection 1')
        self.courseware_page.wait_for_page()

        self.course_home_page.visit()
        self.course_home_page.preview.set_staff_view_mode('Learner')
        self.assertEqual(self.course_home_page.outline.num_subsections, 1)
        self.course_home_page.outline.go_to_section('Test Section 1', 'Test Subsection 1')
        self.courseware_page.wait_for_page()
        self.assertFalse(self.courseware_page.has_banner())

        self.course_home_page.visit()
        self.course_home_page.preview.set_staff_view_mode_specific_student(self.STUDENT_USERNAME)
        self.assertEqual(self.course_home_page.outline.num_subsections, 2)
        self.course_home_page.outline.go_to_section('Test Section 1', 'Test Subsection 2')
        self.courseware_page.wait_for_page()
        self.assertFalse(self.courseware_page.has_banner())
Beispiel #13
0
class GatingTest(UniqueCourseTest):
    """
    Test gating feature in LMS.
    """
    STAFF_USERNAME = "******"
    STAFF_EMAIL = "*****@*****.**"

    STUDENT_USERNAME = "******"
    STUDENT_EMAIL = "*****@*****.**"

    def setUp(self):
        super(GatingTest, self).setUp()

        self.logout_page = LogoutPage(self.browser)
        self.course_home_page = CourseHomePage(self.browser, self.course_id)
        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.studio_course_outline = StudioCourseOutlinePage(
            self.browser, self.course_info['org'], self.course_info['number'],
            self.course_info['run'])

        xml = dedent("""
        <problem>
        <p>What is height of eiffel tower without the antenna?.</p>
        <multiplechoiceresponse>
          <choicegroup label="What is height of eiffel tower without the antenna?" type="MultipleChoice">
            <choice correct="false">324 meters<choicehint>Antenna is 24 meters high</choicehint></choice>
            <choice correct="true">300 meters</choice>
            <choice correct="false">224 meters</choice>
            <choice correct="false">400 meters</choice>
          </choicegroup>
        </multiplechoiceresponse>
        </problem>
        """)
        self.problem1 = XBlockFixtureDesc('problem',
                                          'HEIGHT OF EIFFEL TOWER',
                                          data=xml)

        # Install a course with sections/problems
        course_fixture = CourseFixture(self.course_info['org'],
                                       self.course_info['number'],
                                       self.course_info['run'],
                                       self.course_info['display_name'])
        course_fixture.add_advanced_settings(
            {"enable_subsection_gating": {
                "value": "true"
            }})

        course_fixture.add_children(
            XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
                XBlockFixtureDesc('sequential',
                                  'Test Subsection 1').add_children(
                                      self.problem1),
                XBlockFixtureDesc('sequential',
                                  'Test Subsection 2').add_children(
                                      XBlockFixtureDesc(
                                          'problem',
                                          'Test Problem 2')))).install()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        self.logout_page.visit()
        AutoAuthPage(self.browser,
                     username=username,
                     email=email,
                     course_id=self.course_id,
                     staff=staff).visit()

    def _setup_prereq(self):
        """
        Make the first subsection a prerequisite
        """
        # Login as staff
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)

        # Make the first subsection a prerequisite
        self.studio_course_outline.visit()
        self.studio_course_outline.open_subsection_settings_dialog(0)
        self.studio_course_outline.select_advanced_tab(
            desired_item='gated_content')
        self.studio_course_outline.make_gating_prerequisite()

    def _setup_gated_subsection(self):
        """
        Gate the second subsection on the first subsection
        """
        # Login as staff
        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)

        # Gate the second subsection based on the score achieved in the first subsection
        self.studio_course_outline.visit()
        self.studio_course_outline.open_subsection_settings_dialog(1)
        self.studio_course_outline.select_advanced_tab(
            desired_item='gated_content')
        self.studio_course_outline.add_prerequisite_to_subsection("80")

    def _fulfill_prerequisite(self):
        """
        Fulfill the prerequisite needed to see gated content
        """
        problem_page = ProblemPage(self.browser)
        self.assertEqual(problem_page.wait_for_page().problem_name,
                         'HEIGHT OF EIFFEL TOWER')
        problem_page.click_choice('choice_1')
        problem_page.click_submit()

    def test_subsection_gating_in_studio(self):
        """
        Given that I am a staff member
        When I visit the course outline page in studio.
        And open the subsection edit dialog
        Then I can view all settings related to Gating
        And update those settings to gate a subsection
        """
        self._setup_prereq()

        # Assert settings are displayed correctly for a prerequisite subsection
        self.studio_course_outline.visit()
        self.studio_course_outline.open_subsection_settings_dialog(0)
        self.studio_course_outline.select_advanced_tab(
            desired_item='gated_content')
        self.assertTrue(self.studio_course_outline.
                        gating_prerequisite_checkbox_is_visible())
        self.assertTrue(self.studio_course_outline.
                        gating_prerequisite_checkbox_is_checked())
        self.assertFalse(self.studio_course_outline.
                         gating_prerequisites_dropdown_is_visible())
        self.assertFalse(self.studio_course_outline.
                         gating_prerequisite_min_score_is_visible())

        self._setup_gated_subsection()

        # Assert settings are displayed correctly for a gated subsection
        self.studio_course_outline.visit()
        self.studio_course_outline.open_subsection_settings_dialog(1)
        self.studio_course_outline.select_advanced_tab(
            desired_item='gated_content')
        self.assertTrue(self.studio_course_outline.
                        gating_prerequisite_checkbox_is_visible())
        self.assertTrue(self.studio_course_outline.
                        gating_prerequisites_dropdown_is_visible())
        self.assertTrue(self.studio_course_outline.
                        gating_prerequisite_min_score_is_visible())

    def test_gated_subsection_in_lms_for_student(self):
        """
        Given that I am a student
        When I visit the LMS Courseware
        Then I can see a gated subsection
            The gated subsection should have a lock icon
            and be in the format: "<Subsection Title> (Prerequisite Required)"
        When I fulfill the gating Prerequisite
        Then I can see the gated subsection
            Now the gated subsection should have an unlock icon
            and screen readers should read the section as: "<Subsection Title> Unlocked"
        """
        self._setup_prereq()
        self._setup_gated_subsection()

        self._auto_auth(self.STUDENT_USERNAME, self.STUDENT_EMAIL, False)

        self.course_home_page.visit()
        self.assertEqual(self.course_home_page.outline.num_subsections, 2)

        # Fulfill prerequisite and verify that gated subsection is shown
        self.courseware_page.visit()
        self._fulfill_prerequisite()
        self.course_home_page.visit()
        self.assertEqual(self.course_home_page.outline.num_subsections, 2)

    def test_gated_subsection_in_lms_for_staff(self):
        """
        Given that I am a staff member
        When I visit the LMS Courseware
        Then I can see all gated subsections
        Displayed along with notification banners
        Then if I masquerade as a student
        Then I can see a gated subsection
            The gated subsection should have a lock icon
            and be in the format: "<Subsection Title> (Prerequisite Required)"
        """
        self._setup_prereq()
        self._setup_gated_subsection()

        self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)

        self.course_home_page.visit()
        self.assertEqual(self.course_home_page.preview.staff_view_mode,
                         'Staff')
        self.assertEqual(self.course_home_page.outline.num_subsections, 2)

        # Click on gated section and check for banner
        self.course_home_page.outline.go_to_section('Test Section 1',
                                                    'Test Subsection 2')
        self.courseware_page.wait_for_page()
        self.assertTrue(self.courseware_page.has_banner())

        self.course_home_page.visit()
        self.course_home_page.outline.go_to_section('Test Section 1',
                                                    'Test Subsection 1')
        self.courseware_page.wait_for_page()

        self.course_home_page.visit()
        self.course_home_page.preview.set_staff_view_mode('Learner')
        self.course_home_page.wait_for_page()
        self.assertEqual(self.course_home_page.outline.num_subsections, 2)
        self.course_home_page.outline.go_to_section('Test Section 1',
                                                    'Test Subsection 1')
        self.courseware_page.wait_for_page()
        # banner displayed informing section is a prereq
        self.assertTrue(self.courseware_page.has_banner())
Beispiel #14
0
class VisibleToStaffOnlyTest(UniqueCourseTest):
    """
    Tests that content with visible_to_staff_only set to True cannot be viewed by students.
    """
    def setUp(self):
        super(VisibleToStaffOnlyTest, self).setUp()

        course_fix = CourseFixture(self.course_info['org'],
                                   self.course_info['number'],
                                   self.course_info['run'],
                                   self.course_info['display_name'])

        course_fix.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Subsection With Locked Unit').
                add_children(
                    XBlockFixtureDesc(
                        'vertical',
                        'Locked Unit',
                        metadata={
                            'visible_to_staff_only': True
                        }).add_children(
                            XBlockFixtureDesc(
                                'html',
                                'Html Child in locked unit',
                                data="<html>Visible only to staff</html>"), ),
                    XBlockFixtureDesc(
                        'vertical', 'Unlocked Unit').add_children(
                            XBlockFixtureDesc(
                                'html',
                                'Html Child in unlocked unit',
                                data="<html>Visible only to all</html>"), )),
                XBlockFixtureDesc(
                    'sequential', 'Unlocked Subsection').add_children(
                        XBlockFixtureDesc(
                            'vertical', 'Test Unit').add_children(
                                XBlockFixtureDesc(
                                    'html',
                                    'Html Child in visible unit',
                                    data="<html>Visible to all</html>"), )),
                XBlockFixtureDesc(
                    'sequential',
                    'Locked Subsection',
                    metadata={
                        'visible_to_staff_only': True
                    }).add_children(
                        XBlockFixtureDesc(
                            'vertical', 'Test Unit').add_children(
                                XBlockFixtureDesc(
                                    'html',
                                    'Html Child in locked subsection',
                                    data="<html>Visible only to staff</html>"))
                    ))).install()

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

    def test_visible_to_staff(self):
        """
        Scenario: All content is visible for a user marked is_staff (different from course staff)
            Given some of the course content has been marked 'visible_to_staff_only'
            And I am logged on with an account marked 'is_staff'
            Then I can see all course content
        """
        AutoAuthPage(self.browser,
                     username="******",
                     email="*****@*****.**",
                     course_id=self.course_id,
                     staff=True).visit()

        self.course_home_page.visit()
        self.assertEqual(
            3, len(self.course_home_page.outline.sections['Test Section']))

        self.course_home_page.outline.go_to_section(
            "Test Section", "Subsection With Locked Unit")
        self.courseware_page.wait_for_page()
        self.assertEqual([u'Locked Unit', u'Unlocked Unit'],
                         self.courseware_page.nav.sequence_items)

        self.course_home_page.visit()
        self.course_home_page.outline.go_to_section("Test Section",
                                                    "Unlocked Subsection")
        self.courseware_page.wait_for_page()
        self.assertEqual([u'Test Unit'],
                         self.courseware_page.nav.sequence_items)

        self.course_home_page.visit()
        self.course_home_page.outline.go_to_section("Test Section",
                                                    "Locked Subsection")
        self.courseware_page.wait_for_page()
        self.assertEqual([u'Test Unit'],
                         self.courseware_page.nav.sequence_items)

    def test_visible_to_student(self):
        """
        Scenario: Content marked 'visible_to_staff_only' is not visible for students in the course
            Given some of the course content has been marked 'visible_to_staff_only'
            And I am logged on with an authorized student account
            Then I can only see content without 'visible_to_staff_only' set to True
        """
        AutoAuthPage(self.browser,
                     username="******",
                     email="*****@*****.**",
                     course_id=self.course_id,
                     staff=False).visit()

        self.course_home_page.visit()
        self.assertEqual(
            2, len(self.course_home_page.outline.sections['Test Section']))

        self.course_home_page.outline.go_to_section(
            "Test Section", "Subsection With Locked Unit")
        self.courseware_page.wait_for_page()
        self.assertEqual([u'Unlocked Unit'],
                         self.courseware_page.nav.sequence_items)

        self.course_home_page.visit()
        self.course_home_page.outline.go_to_section("Test Section",
                                                    "Unlocked Subsection")
        self.courseware_page.wait_for_page()
        self.assertEqual([u'Test Unit'],
                         self.courseware_page.nav.sequence_items)
Beispiel #15
0
class BookmarksTest(BookmarksTestMixin):
    """
    Tests to verify bookmarks functionality.
    """
    def setUp(self):
        """
        Initialize test setup.
        """
        super(BookmarksTest, self).setUp()

        self.course_outline_page = CourseOutlinePage(
            self.browser, self.course_info['org'], self.course_info['number'],
            self.course_info['run'])

        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.bookmarks_page = BookmarksPage(self.browser, self.course_id)
        self.course_nav = CourseNavPage(self.browser)

        # Get session to be used for bookmarking units
        self.session = requests.Session()
        params = {
            'username': self.USERNAME,
            'email': self.EMAIL,
            'course_id': self.course_id
        }
        response = self.session.get(BASE_URL + "/auto_auth", params=params)
        self.assertTrue(response.ok, "Failed to get session")

    def _test_setup(self, num_chapters=2):
        """
        Setup test settings.

        Arguments:
            num_chapters: number of chapters to create in course
        """
        self.create_course_fixture(num_chapters)

        # Auto-auth register for the course.
        LmsAutoAuthPage(self.browser,
                        username=self.USERNAME,
                        email=self.EMAIL,
                        course_id=self.course_id).visit()

        self.courseware_page.visit()

    def _bookmark_unit(self, location):
        """
        Bookmark a unit

        Arguments:
            location (str): unit location
        """
        _headers = {
            'Content-type': 'application/json',
            'X-CSRFToken': self.session.cookies['csrftoken'],
        }
        params = {'course_id': self.course_id}
        data = json.dumps({'usage_id': location})
        response = self.session.post(BASE_URL + '/api/bookmarks/v1/bookmarks/',
                                     data=data,
                                     params=params,
                                     headers=_headers)
        self.assertTrue(response.ok, "Failed to bookmark unit")

    def _bookmark_units(self, num_units):
        """
        Bookmark first `num_units` units

        Arguments:
            num_units(int): Number of units to bookmarks
        """
        xblocks = self.course_fixture.get_nested_xblocks(category="vertical")
        for index in range(num_units):
            self._bookmark_unit(xblocks[index].locator)

    def _breadcrumb(self, num_units, modified_name=None):
        """
        Creates breadcrumbs for the first `num_units`

        Arguments:
            num_units(int): Number of units for which we want to create breadcrumbs

        Returns:
            list of breadcrumbs
        """
        breadcrumbs = []
        for index in range(num_units):
            breadcrumbs.append([
                'TestSection{}'.format(index),
                'TestSubsection{}'.format(index), modified_name
                if modified_name else 'TestVertical{}'.format(index)
            ])
        return breadcrumbs

    def _delete_section(self, index):
        """ Delete a section at index `index` """

        # Logout and login as staff
        LogoutPage(self.browser).visit()
        StudioAutoAuthPage(self.browser,
                           username=self.USERNAME,
                           email=self.EMAIL,
                           course_id=self.course_id,
                           staff=True).visit()

        # Visit course outline page in studio.
        self.course_outline_page.visit()
        self.course_outline_page.wait_for_page()

        self.course_outline_page.section_at(index).delete()

        # Logout and login as a student.
        LogoutPage(self.browser).visit()
        LmsAutoAuthPage(self.browser,
                        username=self.USERNAME,
                        email=self.EMAIL,
                        course_id=self.course_id).visit()

        # Visit courseware as a student.
        self.courseware_page.visit()
        self.courseware_page.wait_for_page()

    def _toggle_bookmark_and_verify(self, bookmark_icon_state,
                                    bookmark_button_state, bookmarked_count):
        """
        Bookmark/Un-Bookmark a unit and then verify
        """
        self.assertTrue(self.courseware_page.bookmark_button_visible)
        self.courseware_page.click_bookmark_unit_button()
        self.assertEqual(self.courseware_page.bookmark_icon_visible,
                         bookmark_icon_state)
        self.assertEqual(self.courseware_page.bookmark_button_state,
                         bookmark_button_state)
        self.bookmarks_page.click_bookmarks_button()
        self.assertEqual(self.bookmarks_page.count(), bookmarked_count)

    def _verify_pagination_info(self, bookmark_count_on_current_page,
                                header_text, previous_button_enabled,
                                next_button_enabled, current_page_number,
                                total_pages):
        """
        Verify pagination info
        """
        self.assertEqual(self.bookmarks_page.count(),
                         bookmark_count_on_current_page)
        self.assertEqual(self.bookmarks_page.get_pagination_header_text(),
                         header_text)
        self.assertEqual(self.bookmarks_page.is_previous_page_button_enabled(),
                         previous_button_enabled)
        self.assertEqual(self.bookmarks_page.is_next_page_button_enabled(),
                         next_button_enabled)
        self.assertEqual(self.bookmarks_page.get_current_page_number(),
                         current_page_number)
        self.assertEqual(self.bookmarks_page.get_total_pages, total_pages)

    def _navigate_to_bookmarks_list(self):
        """
        Navigates and verifies the bookmarks list page.
        """
        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())
        self.assertEqual(self.bookmarks_page.results_header_text(),
                         'My Bookmarks')

    def _verify_breadcrumbs(self, num_units, modified_name=None):
        """
        Verifies the breadcrumb trail.
        """
        bookmarked_breadcrumbs = self.bookmarks_page.breadcrumbs()

        # Verify bookmarked breadcrumbs.
        breadcrumbs = self._breadcrumb(num_units=num_units,
                                       modified_name=modified_name)
        breadcrumbs.reverse()
        self.assertEqual(bookmarked_breadcrumbs, breadcrumbs)

    def update_and_publish_block_display_name(self, modified_name):
        """
        Update and publish the block/unit display name.
        """
        self.course_outline_page.visit()
        self.course_outline_page.wait_for_page()

        self.course_outline_page.expand_all_subsections()
        section = self.course_outline_page.section_at(0)
        container_page = section.subsection_at(0).unit_at(0).go_to()

        self.course_fixture._update_xblock(
            container_page.locator,
            {  # pylint: disable=protected-access
                "metadata": {
                    "display_name": modified_name
                }
            })

        container_page.visit()
        container_page.wait_for_page()

        self.assertEqual(container_page.name, modified_name)
        container_page.publish_action.click()

    def test_bookmark_button(self):
        """
        Scenario: Bookmark unit button toggles correctly

        Given that I am a registered user
        And I visit my courseware page
        For first 2 units
            I visit the unit
            And I can see the Bookmark button
            When I click on Bookmark button
            Then unit should be bookmarked
            Then I click again on the bookmark button
            And I should see a unit un-bookmarked
        """
        self._test_setup()
        for index in range(2):
            self.course_nav.go_to_section('TestSection{}'.format(index),
                                          'TestSubsection{}'.format(index))

            self._toggle_bookmark_and_verify(True, 'bookmarked', 1)
            self.bookmarks_page.click_bookmarks_button(False)
            self._toggle_bookmark_and_verify(False, '', 0)

    def test_empty_bookmarks_list(self):
        """
        Scenario: An empty bookmarks list is shown if there are no bookmarked units.

        Given that I am a registered user
        And I visit my courseware page
        And I can see the Bookmarks button
        When I click on Bookmarks button
        Then I should see an empty bookmarks list
        And empty bookmarks list content is correct
        """
        self._test_setup()
        self.assertTrue(self.bookmarks_page.bookmarks_button_visible())
        self.bookmarks_page.click_bookmarks_button()
        self.assertEqual(self.bookmarks_page.results_header_text(),
                         'My Bookmarks')
        self.assertEqual(self.bookmarks_page.empty_header_text(),
                         'You have not bookmarked any courseware pages yet.')

        empty_list_text = (
            "Use bookmarks to help you easily return to courseware pages. To bookmark a page, "
            "select Bookmark in the upper right corner of that page. To see a list of all your "
            "bookmarks, select Bookmarks in the upper left corner of any courseware page."
        )
        self.assertEqual(self.bookmarks_page.empty_list_text(),
                         empty_list_text)

    def test_bookmarks_list(self):
        """
        Scenario: A bookmarks list is shown if there are bookmarked units.

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked 2 units
        When I click on Bookmarks button
        Then I should see a bookmarked list with 2 bookmark links
        And breadcrumb trail is correct for a bookmark
        When I click on bookmarked link
        Then I can navigate to correct bookmarked unit
        """
        self._test_setup()
        self._bookmark_units(2)

        self._navigate_to_bookmarks_list()
        self._verify_breadcrumbs(num_units=2)

        self._verify_pagination_info(bookmark_count_on_current_page=2,
                                     header_text='Showing 1-2 out of 2 total',
                                     previous_button_enabled=False,
                                     next_button_enabled=False,
                                     current_page_number=1,
                                     total_pages=1)

        # get usage ids for units
        xblocks = self.course_fixture.get_nested_xblocks(category="vertical")
        xblock_usage_ids = [xblock.locator for xblock in xblocks]
        # Verify link navigation
        for index in range(2):
            self.bookmarks_page.click_bookmarked_block(index)
            self.courseware_page.wait_for_page()
            self.assertIn(self.courseware_page.active_usage_id(),
                          xblock_usage_ids)
            self.courseware_page.visit().wait_for_page()
            self.bookmarks_page.click_bookmarks_button()

    def test_bookmark_shows_updated_breadcrumb_after_publish(self):
        """
        Scenario: A bookmark breadcrumb trail is updated after publishing the changed display name.

        Given that I am a registered user
        And I visit my courseware page
        And I can see bookmarked unit
        Then I visit unit page in studio
        Then I change unit display_name
        And I publish the changes
        Then I visit my courseware page
        And I visit bookmarks list page
        When I see the bookmark
        Then I can see the breadcrumb trail
        with updated display_name.
        """
        self._test_setup(num_chapters=1)
        self._bookmark_units(num_units=1)

        self._navigate_to_bookmarks_list()
        self._verify_breadcrumbs(num_units=1)

        LogoutPage(self.browser).visit()
        LmsAutoAuthPage(self.browser,
                        username=self.USERNAME,
                        email=self.EMAIL,
                        course_id=self.course_id,
                        staff=True).visit()

        modified_name = "Updated name"
        self.update_and_publish_block_display_name(modified_name)

        LogoutPage(self.browser).visit()
        LmsAutoAuthPage(self.browser,
                        username=self.USERNAME,
                        email=self.EMAIL,
                        course_id=self.course_id).visit()
        self.courseware_page.visit()

        self._navigate_to_bookmarks_list()
        self._verify_breadcrumbs(num_units=1, modified_name=modified_name)

    def test_unreachable_bookmark(self):
        """
        Scenario: We should get a HTTP 404 for an unreachable bookmark.

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked 2 units
        Then I delete a bookmarked unit
        Then I click on Bookmarks button
        And I should see a bookmarked list
        When I click on deleted bookmark
        Then I should navigated to 404 page
        """
        self._test_setup(num_chapters=1)
        self._bookmark_units(1)
        self._delete_section(0)

        self._navigate_to_bookmarks_list()

        self._verify_pagination_info(bookmark_count_on_current_page=1,
                                     header_text='Showing 1 out of 1 total',
                                     previous_button_enabled=False,
                                     next_button_enabled=False,
                                     current_page_number=1,
                                     total_pages=1)

        self.bookmarks_page.click_bookmarked_block(0)
        self.assertTrue(is_404_page(self.browser))

    def test_page_size_limit(self):
        """
        Scenario: We can't get bookmarks more than default page size.

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 11 units available
        Then I click on Bookmarks button
        And I should see a bookmarked list
        And bookmark list contains 10 bookmarked items
        """
        self._test_setup(11)
        self._bookmark_units(11)
        self._navigate_to_bookmarks_list()

        self._verify_pagination_info(
            bookmark_count_on_current_page=10,
            header_text='Showing 1-10 out of 11 total',
            previous_button_enabled=False,
            next_button_enabled=True,
            current_page_number=1,
            total_pages=2)

    def test_pagination_with_single_page(self):
        """
        Scenario: Bookmarks list pagination is working as expected for single page
        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 2 units available
        Then I click on Bookmarks button
        And I should see a bookmarked list with 2 bookmarked items
        And I should see paging header and footer with correct data
        And previous and next buttons are disabled
        """
        self._test_setup(num_chapters=2)
        self._bookmark_units(num_units=2)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())
        self._verify_pagination_info(bookmark_count_on_current_page=2,
                                     header_text='Showing 1-2 out of 2 total',
                                     previous_button_enabled=False,
                                     next_button_enabled=False,
                                     current_page_number=1,
                                     total_pages=1)

    def test_next_page_button(self):
        """
        Scenario: Next button is working as expected for bookmarks list pagination

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 12 units available

        Then I click on Bookmarks button
        And I should see a bookmarked list of 10 items
        And I should see paging header and footer with correct info

        Then I click on next page button in footer
        And I should be navigated to second page
        And I should see a bookmarked list with 2 items
        And I should see paging header and footer with correct info
        """
        self._test_setup(num_chapters=12)
        self._bookmark_units(num_units=12)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())

        self._verify_pagination_info(
            bookmark_count_on_current_page=10,
            header_text='Showing 1-10 out of 12 total',
            previous_button_enabled=False,
            next_button_enabled=True,
            current_page_number=1,
            total_pages=2)

        self.bookmarks_page.press_next_page_button()
        self._verify_pagination_info(
            bookmark_count_on_current_page=2,
            header_text='Showing 11-12 out of 12 total',
            previous_button_enabled=True,
            next_button_enabled=False,
            current_page_number=2,
            total_pages=2)

    def test_previous_page_button(self):
        """
        Scenario: Previous button is working as expected for bookmarks list pagination

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 12 units available
        And I click on Bookmarks button

        Then I click on next page button in footer
        And I should be navigated to second page
        And I should see a bookmarked list with 2 items
        And I should see paging header and footer with correct info

        Then I click on previous page button
        And I should be navigated to first page
        And I should see paging header and footer with correct info
        """
        self._test_setup(num_chapters=12)
        self._bookmark_units(num_units=12)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())

        self.bookmarks_page.press_next_page_button()
        self._verify_pagination_info(
            bookmark_count_on_current_page=2,
            header_text='Showing 11-12 out of 12 total',
            previous_button_enabled=True,
            next_button_enabled=False,
            current_page_number=2,
            total_pages=2)

        self.bookmarks_page.press_previous_page_button()
        self._verify_pagination_info(
            bookmark_count_on_current_page=10,
            header_text='Showing 1-10 out of 12 total',
            previous_button_enabled=False,
            next_button_enabled=True,
            current_page_number=1,
            total_pages=2)

    def test_pagination_with_valid_page_number(self):
        """
        Scenario: Bookmarks list pagination works as expected for valid page number

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 12 units available

        Then I click on Bookmarks button
        And I should see a bookmarked list
        And I should see total page value is 2
        Then I enter 2 in the page number input
        And I should be navigated to page 2
        """
        self._test_setup(num_chapters=11)
        self._bookmark_units(num_units=11)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())
        self.assertEqual(self.bookmarks_page.get_total_pages, 2)

        self.bookmarks_page.go_to_page(2)
        self._verify_pagination_info(
            bookmark_count_on_current_page=1,
            header_text='Showing 11-11 out of 11 total',
            previous_button_enabled=True,
            next_button_enabled=False,
            current_page_number=2,
            total_pages=2)

    def test_pagination_with_invalid_page_number(self):
        """
        Scenario: Bookmarks list pagination works as expected for invalid page number

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 11 units available
        Then I click on Bookmarks button
        And I should see a bookmarked list
        And I should see total page value is 2
        Then I enter 3 in the page number input
        And I should stay at page 1
        """
        self._test_setup(num_chapters=11)
        self._bookmark_units(num_units=11)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())
        self.assertEqual(self.bookmarks_page.get_total_pages, 2)

        self.bookmarks_page.go_to_page(3)
        self._verify_pagination_info(
            bookmark_count_on_current_page=10,
            header_text='Showing 1-10 out of 11 total',
            previous_button_enabled=False,
            next_button_enabled=True,
            current_page_number=1,
            total_pages=2)

    def test_bookmarked_unit_accessed_event(self):
        """
        Scenario: Bookmark events are emitted with correct data when we access/visit a bookmarked unit.

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked a unit
        When I click on bookmarked unit
        Then `edx.course.bookmark.accessed` event is emitted
        """
        self._test_setup(num_chapters=1)
        self.reset_event_tracking()

        # create expected event data
        xblocks = self.course_fixture.get_nested_xblocks(category="vertical")
        event_data = [{
            'event': {
                'bookmark_id': '{},{}'.format(self.USERNAME,
                                              xblocks[0].locator),
                'component_type': xblocks[0].category,
                'component_usage_id': xblocks[0].locator,
            }
        }]
        self._bookmark_units(num_units=1)
        self.bookmarks_page.click_bookmarks_button()

        self._verify_pagination_info(bookmark_count_on_current_page=1,
                                     header_text='Showing 1 out of 1 total',
                                     previous_button_enabled=False,
                                     next_button_enabled=False,
                                     current_page_number=1,
                                     total_pages=1)

        self.bookmarks_page.click_bookmarked_block(0)
        self.verify_event_data('edx.bookmark.accessed', event_data)
Beispiel #16
0
class VisibleToStaffOnlyTest(UniqueCourseTest):
    """
    Tests that content with visible_to_staff_only set to True cannot be viewed by students.
    """
    def setUp(self):
        super(VisibleToStaffOnlyTest, self).setUp()

        course_fix = CourseFixture(
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run'],
            self.course_info['display_name']
        )

        course_fix.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Subsection With Locked Unit').add_children(
                    XBlockFixtureDesc('vertical', 'Locked Unit', metadata={'visible_to_staff_only': True}).add_children(
                        XBlockFixtureDesc('html', 'Html Child in locked unit', data="<html>Visible only to staff</html>"),
                    ),
                    XBlockFixtureDesc('vertical', 'Unlocked Unit').add_children(
                        XBlockFixtureDesc('html', 'Html Child in unlocked unit', data="<html>Visible only to all</html>"),
                    )
                ),
                XBlockFixtureDesc('sequential', 'Unlocked Subsection').add_children(
                    XBlockFixtureDesc('vertical', 'Test Unit').add_children(
                        XBlockFixtureDesc('html', 'Html Child in visible unit', data="<html>Visible to all</html>"),
                    )
                ),
                XBlockFixtureDesc('sequential', 'Locked Subsection', metadata={'visible_to_staff_only': True}).add_children(
                    XBlockFixtureDesc('vertical', 'Test Unit').add_children(
                        XBlockFixtureDesc(
                            'html', 'Html Child in locked subsection', data="<html>Visible only to staff</html>"
                        )
                    )
                )
            )
        ).install()

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

    def test_visible_to_student(self):
        """
        Scenario: Content marked 'visible_to_staff_only' is not visible for students in the course
            Given some of the course content has been marked 'visible_to_staff_only'
            And I am logged on with an authorized student account
            Then I can only see content without 'visible_to_staff_only' set to True
        """
        AutoAuthPage(self.browser, username="******", email="*****@*****.**",
                     course_id=self.course_id, staff=False).visit()

        self.course_home_page.visit()
        self.assertEqual(2, len(self.course_home_page.outline.sections['Test Section']))

        self.course_home_page.outline.go_to_section("Test Section", "Subsection With Locked Unit")
        self.courseware_page.wait_for_page()
        self.assertEqual([u'Unlocked Unit'], self.courseware_page.nav.sequence_items)

        self.course_home_page.visit()
        self.course_home_page.outline.go_to_section("Test Section", "Unlocked Subsection")
        self.courseware_page.wait_for_page()
        self.assertEqual([u'Test Unit'], self.courseware_page.nav.sequence_items)
class BookmarksTest(BookmarksTestMixin):
    """
    Tests to verify bookmarks functionality.
    """

    def setUp(self):
        """
        Initialize test setup.
        """
        super(BookmarksTest, self).setUp()

        self.course_outline_page = CourseOutlinePage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )

        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.bookmarks_page = BookmarksPage(self.browser, self.course_id)
        self.course_nav = CourseNavPage(self.browser)

        # Get session to be used for bookmarking units
        self.session = requests.Session()
        params = {'username': self.USERNAME, 'email': self.EMAIL, 'course_id': self.course_id}
        response = self.session.get(BASE_URL + "/auto_auth", params=params)
        self.assertTrue(response.ok, "Failed to get session")

    def _test_setup(self, num_chapters=2):
        """
        Setup test settings.

        Arguments:
            num_chapters: number of chapters to create in course
        """
        self.create_course_fixture(num_chapters)

        # Auto-auth register for the course.
        LmsAutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit()

        self.courseware_page.visit()

    def _bookmark_unit(self, location):
        """
        Bookmark a unit

        Arguments:
            location (str): unit location
        """
        _headers = {
            'Content-type': 'application/json',
            'X-CSRFToken': self.session.cookies['csrftoken'],
        }
        params = {'course_id': self.course_id}
        data = json.dumps({'usage_id': location})
        response = self.session.post(
            BASE_URL + '/api/bookmarks/v1/bookmarks/',
            data=data,
            params=params,
            headers=_headers
        )
        self.assertTrue(response.ok, "Failed to bookmark unit")

    def _bookmark_units(self, num_units):
        """
        Bookmark first `num_units` units

        Arguments:
            num_units(int): Number of units to bookmarks
        """
        xblocks = self.course_fixture.get_nested_xblocks(category="vertical")
        for index in range(num_units):
            self._bookmark_unit(xblocks[index].locator)

    def _breadcrumb(self, num_units, modified_name=None):
        """
        Creates breadcrumbs for the first `num_units`

        Arguments:
            num_units(int): Number of units for which we want to create breadcrumbs

        Returns:
            list of breadcrumbs
        """
        breadcrumbs = []
        for index in range(num_units):
            breadcrumbs.append(
                [
                    'TestSection{}'.format(index),
                    'TestSubsection{}'.format(index),
                    modified_name if modified_name else 'TestVertical{}'.format(index)
                ]
            )
        return breadcrumbs

    def _delete_section(self, index):
        """ Delete a section at index `index` """

        # Logout and login as staff
        LogoutPage(self.browser).visit()
        StudioAutoAuthPage(
            self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id, staff=True
        ).visit()

        # Visit course outline page in studio.
        self.course_outline_page.visit()
        self.course_outline_page.wait_for_page()

        self.course_outline_page.section_at(index).delete()

        # Logout and login as a student.
        LogoutPage(self.browser).visit()
        LmsAutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit()

        # Visit courseware as a student.
        self.courseware_page.visit()
        self.courseware_page.wait_for_page()

    def _toggle_bookmark_and_verify(self, bookmark_icon_state, bookmark_button_state, bookmarked_count):
        """
        Bookmark/Un-Bookmark a unit and then verify
        """
        self.assertTrue(self.courseware_page.bookmark_button_visible)
        self.courseware_page.click_bookmark_unit_button()
        self.assertEqual(self.courseware_page.bookmark_icon_visible, bookmark_icon_state)
        self.assertEqual(self.courseware_page.bookmark_button_state, bookmark_button_state)
        self.bookmarks_page.click_bookmarks_button()
        self.assertEqual(self.bookmarks_page.count(), bookmarked_count)

    def _verify_pagination_info(
            self,
            bookmark_count_on_current_page,
            header_text,
            previous_button_enabled,
            next_button_enabled,
            current_page_number,
            total_pages
    ):
        """
        Verify pagination info
        """
        self.assertEqual(self.bookmarks_page.count(), bookmark_count_on_current_page)
        self.assertEqual(self.bookmarks_page.get_pagination_header_text(), header_text)
        self.assertEqual(self.bookmarks_page.is_previous_page_button_enabled(), previous_button_enabled)
        self.assertEqual(self.bookmarks_page.is_next_page_button_enabled(), next_button_enabled)
        self.assertEqual(self.bookmarks_page.get_current_page_number(), current_page_number)
        self.assertEqual(self.bookmarks_page.get_total_pages, total_pages)

    def _navigate_to_bookmarks_list(self):
        """
        Navigates and verifies the bookmarks list page.
        """
        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())
        self.assertEqual(self.bookmarks_page.results_header_text(), 'My Bookmarks')

    def _verify_breadcrumbs(self, num_units, modified_name=None):
        """
        Verifies the breadcrumb trail.
        """
        bookmarked_breadcrumbs = self.bookmarks_page.breadcrumbs()

        # Verify bookmarked breadcrumbs.
        breadcrumbs = self._breadcrumb(num_units=num_units, modified_name=modified_name)
        breadcrumbs.reverse()
        self.assertEqual(bookmarked_breadcrumbs, breadcrumbs)

    def update_and_publish_block_display_name(self, modified_name):
        """
        Update and publish the block/unit display name.
        """
        self.course_outline_page.visit()
        self.course_outline_page.wait_for_page()

        self.course_outline_page.expand_all_subsections()
        section = self.course_outline_page.section_at(0)
        container_page = section.subsection_at(0).unit_at(0).go_to()

        self.course_fixture._update_xblock(container_page.locator, {  # pylint: disable=protected-access
            "metadata": {
                "display_name": modified_name
            }
        })

        container_page.visit()
        container_page.wait_for_page()

        self.assertEqual(container_page.name, modified_name)
        container_page.publish_action.click()

    def test_bookmark_button(self):
        """
        Scenario: Bookmark unit button toggles correctly

        Given that I am a registered user
        And I visit my courseware page
        For first 2 units
            I visit the unit
            And I can see the Bookmark button
            When I click on Bookmark button
            Then unit should be bookmarked
            Then I click again on the bookmark button
            And I should see a unit un-bookmarked
        """
        self._test_setup()
        for index in range(2):
            self.course_nav.go_to_section('TestSection{}'.format(index), 'TestSubsection{}'.format(index))

            self._toggle_bookmark_and_verify(True, 'bookmarked', 1)
            self.bookmarks_page.click_bookmarks_button(False)
            self._toggle_bookmark_and_verify(False, '', 0)

    def test_empty_bookmarks_list(self):
        """
        Scenario: An empty bookmarks list is shown if there are no bookmarked units.

        Given that I am a registered user
        And I visit my courseware page
        And I can see the Bookmarks button
        When I click on Bookmarks button
        Then I should see an empty bookmarks list
        And empty bookmarks list content is correct
        """
        self._test_setup()
        self.assertTrue(self.bookmarks_page.bookmarks_button_visible())
        self.bookmarks_page.click_bookmarks_button()
        self.assertEqual(self.bookmarks_page.results_header_text(), 'My Bookmarks')
        self.assertEqual(self.bookmarks_page.empty_header_text(), 'You have not bookmarked any courseware pages yet.')

        empty_list_text = ("Use bookmarks to help you easily return to courseware pages. To bookmark a page, "
                           "select Bookmark in the upper right corner of that page. To see a list of all your "
                           "bookmarks, select Bookmarks in the upper left corner of any courseware page.")
        self.assertEqual(self.bookmarks_page.empty_list_text(), empty_list_text)

    def test_bookmarks_list(self):
        """
        Scenario: A bookmarks list is shown if there are bookmarked units.

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked 2 units
        When I click on Bookmarks button
        Then I should see a bookmarked list with 2 bookmark links
        And breadcrumb trail is correct for a bookmark
        When I click on bookmarked link
        Then I can navigate to correct bookmarked unit
        """
        self._test_setup()
        self._bookmark_units(2)

        self._navigate_to_bookmarks_list()
        self._verify_breadcrumbs(num_units=2)

        self._verify_pagination_info(
            bookmark_count_on_current_page=2,
            header_text='Showing 1-2 out of 2 total',
            previous_button_enabled=False,
            next_button_enabled=False,
            current_page_number=1,
            total_pages=1
        )

        # get usage ids for units
        xblocks = self.course_fixture.get_nested_xblocks(category="vertical")
        xblock_usage_ids = [xblock.locator for xblock in xblocks]
        # Verify link navigation
        for index in range(2):
            self.bookmarks_page.click_bookmarked_block(index)
            self.courseware_page.wait_for_page()
            self.assertIn(self.courseware_page.active_usage_id(), xblock_usage_ids)
            self.courseware_page.visit().wait_for_page()
            self.bookmarks_page.click_bookmarks_button()

    def test_bookmark_shows_updated_breadcrumb_after_publish(self):
        """
        Scenario: A bookmark breadcrumb trail is updated after publishing the changed display name.

        Given that I am a registered user
        And I visit my courseware page
        And I can see bookmarked unit
        Then I visit unit page in studio
        Then I change unit display_name
        And I publish the changes
        Then I visit my courseware page
        And I visit bookmarks list page
        When I see the bookmark
        Then I can see the breadcrumb trail
        with updated display_name.
        """
        self._test_setup(num_chapters=1)
        self._bookmark_units(num_units=1)

        self._navigate_to_bookmarks_list()
        self._verify_breadcrumbs(num_units=1)

        LogoutPage(self.browser).visit()
        LmsAutoAuthPage(
            self.browser,
            username=self.USERNAME,
            email=self.EMAIL,
            course_id=self.course_id,
            staff=True
        ).visit()

        modified_name = "Updated name"
        self.update_and_publish_block_display_name(modified_name)

        LogoutPage(self.browser).visit()
        LmsAutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit()
        self.courseware_page.visit()

        self._navigate_to_bookmarks_list()
        self._verify_breadcrumbs(num_units=1, modified_name=modified_name)

    def test_unreachable_bookmark(self):
        """
        Scenario: We should get a HTTP 404 for an unreachable bookmark.

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked 2 units
        Then I delete a bookmarked unit
        Then I click on Bookmarks button
        And I should see a bookmarked list
        When I click on deleted bookmark
        Then I should navigated to 404 page
        """
        self._test_setup(num_chapters=1)
        self._bookmark_units(1)
        self._delete_section(0)

        self._navigate_to_bookmarks_list()

        self._verify_pagination_info(
            bookmark_count_on_current_page=1,
            header_text='Showing 1 out of 1 total',
            previous_button_enabled=False,
            next_button_enabled=False,
            current_page_number=1,
            total_pages=1
        )

        self.bookmarks_page.click_bookmarked_block(0)
        self.assertTrue(is_404_page(self.browser))

    def test_page_size_limit(self):
        """
        Scenario: We can't get bookmarks more than default page size.

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 11 units available
        Then I click on Bookmarks button
        And I should see a bookmarked list
        And bookmark list contains 10 bookmarked items
        """
        self._test_setup(11)
        self._bookmark_units(11)
        self._navigate_to_bookmarks_list()

        self._verify_pagination_info(
            bookmark_count_on_current_page=10,
            header_text='Showing 1-10 out of 11 total',
            previous_button_enabled=False,
            next_button_enabled=True,
            current_page_number=1,
            total_pages=2
        )

    def test_pagination_with_single_page(self):
        """
        Scenario: Bookmarks list pagination is working as expected for single page
        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 2 units available
        Then I click on Bookmarks button
        And I should see a bookmarked list with 2 bookmarked items
        And I should see paging header and footer with correct data
        And previous and next buttons are disabled
        """
        self._test_setup(num_chapters=2)
        self._bookmark_units(num_units=2)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())
        self._verify_pagination_info(
            bookmark_count_on_current_page=2,
            header_text='Showing 1-2 out of 2 total',
            previous_button_enabled=False,
            next_button_enabled=False,
            current_page_number=1,
            total_pages=1
        )

    def test_next_page_button(self):
        """
        Scenario: Next button is working as expected for bookmarks list pagination

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 12 units available

        Then I click on Bookmarks button
        And I should see a bookmarked list of 10 items
        And I should see paging header and footer with correct info

        Then I click on next page button in footer
        And I should be navigated to second page
        And I should see a bookmarked list with 2 items
        And I should see paging header and footer with correct info
        """
        self._test_setup(num_chapters=12)
        self._bookmark_units(num_units=12)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())

        self._verify_pagination_info(
            bookmark_count_on_current_page=10,
            header_text='Showing 1-10 out of 12 total',
            previous_button_enabled=False,
            next_button_enabled=True,
            current_page_number=1,
            total_pages=2
        )

        self.bookmarks_page.press_next_page_button()
        self._verify_pagination_info(
            bookmark_count_on_current_page=2,
            header_text='Showing 11-12 out of 12 total',
            previous_button_enabled=True,
            next_button_enabled=False,
            current_page_number=2,
            total_pages=2
        )

    def test_previous_page_button(self):
        """
        Scenario: Previous button is working as expected for bookmarks list pagination

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 12 units available
        And I click on Bookmarks button

        Then I click on next page button in footer
        And I should be navigated to second page
        And I should see a bookmarked list with 2 items
        And I should see paging header and footer with correct info

        Then I click on previous page button
        And I should be navigated to first page
        And I should see paging header and footer with correct info
        """
        self._test_setup(num_chapters=12)
        self._bookmark_units(num_units=12)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())

        self.bookmarks_page.press_next_page_button()
        self._verify_pagination_info(
            bookmark_count_on_current_page=2,
            header_text='Showing 11-12 out of 12 total',
            previous_button_enabled=True,
            next_button_enabled=False,
            current_page_number=2,
            total_pages=2
        )

        self.bookmarks_page.press_previous_page_button()
        self._verify_pagination_info(
            bookmark_count_on_current_page=10,
            header_text='Showing 1-10 out of 12 total',
            previous_button_enabled=False,
            next_button_enabled=True,
            current_page_number=1,
            total_pages=2
        )

    def test_pagination_with_valid_page_number(self):
        """
        Scenario: Bookmarks list pagination works as expected for valid page number

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 12 units available

        Then I click on Bookmarks button
        And I should see a bookmarked list
        And I should see total page value is 2
        Then I enter 2 in the page number input
        And I should be navigated to page 2
        """
        self._test_setup(num_chapters=11)
        self._bookmark_units(num_units=11)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())
        self.assertEqual(self.bookmarks_page.get_total_pages, 2)

        self.bookmarks_page.go_to_page(2)
        self._verify_pagination_info(
            bookmark_count_on_current_page=1,
            header_text='Showing 11-11 out of 11 total',
            previous_button_enabled=True,
            next_button_enabled=False,
            current_page_number=2,
            total_pages=2
        )

    def test_pagination_with_invalid_page_number(self):
        """
        Scenario: Bookmarks list pagination works as expected for invalid page number

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked all the 11 units available
        Then I click on Bookmarks button
        And I should see a bookmarked list
        And I should see total page value is 2
        Then I enter 3 in the page number input
        And I should stay at page 1
        """
        self._test_setup(num_chapters=11)
        self._bookmark_units(num_units=11)

        self.bookmarks_page.click_bookmarks_button()
        self.assertTrue(self.bookmarks_page.results_present())
        self.assertEqual(self.bookmarks_page.get_total_pages, 2)

        self.bookmarks_page.go_to_page(3)
        self._verify_pagination_info(
            bookmark_count_on_current_page=10,
            header_text='Showing 1-10 out of 11 total',
            previous_button_enabled=False,
            next_button_enabled=True,
            current_page_number=1,
            total_pages=2
        )

    def test_bookmarked_unit_accessed_event(self):
        """
        Scenario: Bookmark events are emitted with correct data when we access/visit a bookmarked unit.

        Given that I am a registered user
        And I visit my courseware page
        And I have bookmarked a unit
        When I click on bookmarked unit
        Then `edx.course.bookmark.accessed` event is emitted
        """
        self._test_setup(num_chapters=1)
        self.reset_event_tracking()

        # create expected event data
        xblocks = self.course_fixture.get_nested_xblocks(category="vertical")
        event_data = [
            {
                'event': {
                    'bookmark_id': '{},{}'.format(self.USERNAME, xblocks[0].locator),
                    'component_type': xblocks[0].category,
                    'component_usage_id': xblocks[0].locator,
                }
            }
        ]
        self._bookmark_units(num_units=1)
        self.bookmarks_page.click_bookmarks_button()

        self._verify_pagination_info(
            bookmark_count_on_current_page=1,
            header_text='Showing 1 out of 1 total',
            previous_button_enabled=False,
            next_button_enabled=False,
            current_page_number=1,
            total_pages=1
        )

        self.bookmarks_page.click_bookmarked_block(0)
        self.verify_event_data('edx.bookmark.accessed', event_data)