Example #1
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_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]
        )
class StaffViewTest(UniqueCourseTest):
    """
    Tests that verify the staff view.
    """
    USERNAME = "******"
    EMAIL = "*****@*****.**"

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

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

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

        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
    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 setUp(self):
        super(CoursewareTest, self).setUp()

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

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

        # Install a course with sections/problems, tabs, updates, and handouts
        self.course_fix = CourseFixture(
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name']
        )

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

        # Auto-auth register for the course.
        self._auto_auth(self.USERNAME, self.EMAIL, False)
    def setUp(self):
        super(ProblemStateOnNavigationTest, self).setUp()

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

        # Install a course with section, tabs and multiple choice problems.
        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 1').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection 1,1').add_children(
                    self.create_multiple_choice_problem(self.problem1_name),
                    self.create_multiple_choice_problem(self.problem2_name),
                ),
            ),
        ).install()

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

        self.courseware_page.visit()
        self.problem_page = ProblemPage(self.browser)
Example #7
0
    def setUp(self):
        """
        Initialize pages and install a course fixture.
        """
        super(TooltipTest, self).setUp()

        self.course_home_page = CourseHomePage(self.browser, self.course_id)
        self.tab_nav = TabNavPage(self.browser)

        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('static_tab', 'Test Static Tab'),
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 1', data=load_data_str('multiple_choice.xml')),
                    XBlockFixtureDesc('problem', 'Test Problem 2', data=load_data_str('formula_problem.xml')),
                    XBlockFixtureDesc('html', 'Test HTML'),
                )
            )
        ).install()

        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        # Auto-auth register for the course
        AutoAuthPage(self.browser, course_id=self.course_id).visit()
    def setUp(self):
        """
        Initialization of pages and course fixture for video tests
        """
        super(VideoBaseTest, self).setUp()
        self.longMessage = True

        self.video = VideoPage(self.browser)
        self.tab_nav = TabNavPage(self.browser)
        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.course_info_page = CourseInfoPage(self.browser, self.course_id)
        self.auth_page = AutoAuthPage(self.browser, course_id=self.course_id)

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

        self.metadata = None
        self.assets = []
        self.contents_of_verticals = None
        self.youtube_configuration = {}
        self.user_info = {}

        # reset youtube stub server
        self.addCleanup(YouTubeStubConfig.reset)
    def setUp(self):
        super(CertificateProgressPageTest, self).setUp()

        # set same course number as we have in fixture json
        self.course_info['number'] = "3355358979513794782079645765720179311111"

        test_certificate_config = {
            'id': 1,
            'name': 'Certificate name',
            'description': 'Certificate description',
            'course_title': 'Course title override',
            'signatories': [],
            'version': 1,
            'is_active': True
        }
        course_settings = {'certificates': test_certificate_config}

        self.course_fixture = CourseFixture(
            self.course_info["org"],
            self.course_info["number"],
            self.course_info["run"],
            self.course_info["display_name"],
            settings=course_settings
        )

        self.course_fixture.add_advanced_settings({
            "cert_html_view_enabled": {"value": "true"},
            "certificates_show_before_end": {"value": "true"}
        })

        self.course_fixture.add_update(
            CourseUpdateDesc(date='January 29, 2014', content='Test course update1')
        )

        self.course_fixture.add_children(
            XBlockFixtureDesc('static_tab', 'Test Static Tab'),
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection', grader_type='Final Exam').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 1', data=load_data_str('multiple_choice.xml')),
                    XBlockFixtureDesc('html', 'Test HTML'),
                )
            ),
            XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection 2', grader_type='Midterm Exam').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 2', data=load_data_str('formula_problem.xml')),
                )
            )
        )

        self.course_fixture.install()
        self.user_id = "99"  # we have created a user with this id in fixture
        self.cert_fixture = CertificateConfigFixture(self.course_id, test_certificate_config)

        self.course_info_page = CourseInfoPage(self.browser, self.course_id)
        self.progress_page = ProgressPage(self.browser, self.course_id)
        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.course_home_page = CourseHomePage(self.browser, self.course_id)
        self.tab_nav = TabNavPage(self.browser)
    def setUp(self):
        super(ConditionalTest, self).setUp()

        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        AutoAuthPage(
            self.browser,
            course_id=self.course_id,
            staff=False
        ).visit()
    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"}, 'enable_proctored_exams': {"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')
                ),
                XBlockFixtureDesc('sequential', 'Test Subsection 3').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 3')
                ),

            )
        ).install()
    def setUp(self):  # pylint: disable=arguments-differ
        super(VideoLicenseTest, self).setUp()

        self.lms_courseware = CoursewarePage(
            self.browser,
            self.course_id,
        )
        self.studio_course_outline = CourseOutlinePage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )
    def setUp(self):
        super(CoursewareMultipleVerticalsTest, self).setUp()

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

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

        # Install a course with sections/problems, tabs, updates, and handouts
        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 1').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection 1,1').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 1', data='<problem>problem 1 dummy body</problem>'),
                    XBlockFixtureDesc('html', 'html 1', data="<html>html 1 dummy body</html>"),
                    XBlockFixtureDesc('problem', 'Test Problem 2', data="<problem>problem 2 dummy body</problem>"),
                    XBlockFixtureDesc('html', 'html 2', data="<html>html 2 dummy body</html>"),
                ),
                XBlockFixtureDesc('sequential', 'Test Subsection 1,2').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 3', data='<problem>problem 3 dummy body</problem>'),
                ),
                XBlockFixtureDesc(
                    'sequential', 'Test HIDDEN Subsection', metadata={'visible_to_staff_only': True}
                ).add_children(
                    XBlockFixtureDesc('problem', 'Test HIDDEN Problem', data='<problem>hidden problem</problem>'),
                ),
            ),
            XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection 2,1').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 4', data='<problem>problem 4 dummy body</problem>'),
                ),
            ),
            XBlockFixtureDesc('chapter', 'Test HIDDEN Section', metadata={'visible_to_staff_only': True}).add_children(
                XBlockFixtureDesc('sequential', 'Test HIDDEN Subsection'),
            ),
        ).install()

        # Auto-auth register for the course.
        AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL,
                     course_id=self.course_id, staff=False).visit()
        self.courseware_page.visit()
        self.course_nav = CourseNavPage(self.browser)
Example #14
0
    def setUp(self):
        """
        Set up library, course and library content XBlock
        """
        super(LibraryContentTestBase, self).setUp()

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

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

        self.library_fixture = LibraryFixture('test_org', self.unique_id, 'Test Library {}'.format(self.unique_id))
        self.populate_library_fixture(self.library_fixture)

        self.library_fixture.install()
        self.library_info = self.library_fixture.library_info
        self.library_key = self.library_fixture.library_key

        # Install a course with library content xblock
        self.course_fixture = CourseFixture(
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name']
        )

        library_content_metadata = {
            'source_library_id': unicode(self.library_key),
            'mode': 'random',
            'max_count': 1,
            'has_score': False
        }

        self.lib_block = XBlockFixtureDesc('library_content', "Library Content", metadata=library_content_metadata)

        self.course_fixture.add_children(
            XBlockFixtureDesc('chapter', SECTION_NAME).add_children(
                XBlockFixtureDesc('sequential', SUBSECTION_NAME).add_children(
                    XBlockFixtureDesc('vertical', UNIT_NAME).add_children(
                        self.lib_block
                    )
                )
            )
        )

        self.course_fixture.install()
Example #15
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'
        ))
    def setUp(self):
        super(ProctoredExamTest, self).setUp()

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

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

        # Install a course with sections/problems, tabs, updates, and handouts
        course_fix = CourseFixture(
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name']
        )
        course_fix.add_advanced_settings({
            "enable_proctored_exams": {"value": "true"}
        })

        course_fix.add_children(
            XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children(
                    XBlockFixtureDesc('problem', 'Test Problem 1')
                )
            )
        ).install()

        self.track_selection_page = TrackSelectionPage(self.browser, self.course_id)
        self.payment_and_verification_flow = PaymentAndVerificationFlow(self.browser, self.course_id)
        self.immediate_verification_page = PaymentAndVerificationFlow(
            self.browser, self.course_id, entry_point='verify-now'
        )
        self.upgrade_page = PaymentAndVerificationFlow(self.browser, self.course_id, entry_point='upgrade')
        self.fake_payment_page = FakePaymentPage(self.browser, self.course_id)
        self.dashboard_page = DashboardPage(self.browser)
        self.problem_page = ProblemPage(self.browser)

        # Add a verified mode to the course
        ModeCreationPage(
            self.browser, self.course_id, mode_slug=u'verified', mode_display_name=u'Verified Certificate',
            min_price=10, suggested_prices='10,20'
        ).visit()

        # Auto-auth register for the course.
        self._auto_auth(self.USERNAME, self.EMAIL, False)
Example #17
0
    def setUp(self):
        """
        Set up library, course and library content XBlock
        """
        super(LibraryContentTestBase, self).setUp()

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

        self.course_outline = CourseOutlinePage(
            self.browser, self.course_info["org"], self.course_info["number"], self.course_info["run"]
        )

        self.library_fixture = LibraryFixture("test_org", self.unique_id, "Test Library {}".format(self.unique_id))
        self.populate_library_fixture(self.library_fixture)

        self.library_fixture.install()
        self.library_info = self.library_fixture.library_info
        self.library_key = self.library_fixture.library_key

        # Install a course with library content xblock
        self.course_fixture = CourseFixture(
            self.course_info["org"],
            self.course_info["number"],
            self.course_info["run"],
            self.course_info["display_name"],
        )

        library_content_metadata = {
            "source_library_id": unicode(self.library_key),
            "mode": "random",
            "max_count": 1,
            "has_score": False,
        }

        self.lib_block = XBlockFixtureDesc("library_content", "Library Content", metadata=library_content_metadata)

        self.course_fixture.add_children(
            XBlockFixtureDesc("chapter", SECTION_NAME).add_children(
                XBlockFixtureDesc("sequential", SUBSECTION_NAME).add_children(
                    XBlockFixtureDesc("vertical", UNIT_NAME).add_children(self.lib_block)
                )
            )
        )

        self.course_fixture.install()
    def setUp(self):
        super(StaffViewTest, self).setUp()

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

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

        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 setUp(self):  # pylint: disable=arguments-differ
     super(ContentLicenseTest, self).setUp()
     self.outline_page = CourseOutlinePage(
         self.browser,
         self.course_info['org'],
         self.course_info['number'],
         self.course_info['run']
     )
     self.settings_page = SettingsPage(
         self.browser,
         self.course_info['org'],
         self.course_info['number'],
         self.course_info['run']
     )
     self.lms_courseware = CoursewarePage(
         self.browser,
         self.course_id,
     )
     self.settings_page.visit()
Example #20
0
    def setUp(self):
        super(BookmarksTestMixin, self).setUp()

        self.studio_course_outline_page = StudioCourseOutlinePage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )

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

        # 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 setUp(self):
        super(AnnotatableProblemTest, self).setUp()

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

        # Install a course with two annotations and two annotations problems.
        course_fix = CourseFixture(
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name']
        )

        self.annotation_count = 2
        course_fix.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
                    XBlockFixtureDesc('vertical', 'Test Annotation Vertical').add_children(
                        XBlockFixtureDesc('annotatable', 'Test Annotation Module',
                                          data=self.DATA_TEMPLATE.format("\n".join(
                                              self.ANNOTATION_TEMPLATE.format(i) for i in xrange(self.annotation_count)
                                          ))),
                        XBlockFixtureDesc('problem', 'Test Annotation Problem 0',
                                          data=self.PROBLEM_TEMPLATE.format(number=0, options="\n".join(
                                              self.OPTION_TEMPLATE.format(
                                                  number=k,
                                                  correctness=_correctness(k, 0))
                                              for k in xrange(self.annotation_count)
                                          ))),
                        XBlockFixtureDesc('problem', 'Test Annotation Problem 1',
                                          data=self.PROBLEM_TEMPLATE.format(number=1, options="\n".join(
                                              self.OPTION_TEMPLATE.format(
                                                  number=k,
                                                  correctness=_correctness(k, 1))
                                              for k in xrange(self.annotation_count)
                                          )))
                    )
                )
            )
        ).install()

        # Auto-auth register for the course.
        AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL,
                     course_id=self.course_id, staff=False).visit()
    def setUp(self):
        super(CrowdsourcehinterProblemTest, self).setUp()

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

        # Install a course with sections/problems, tabs, updates, and handouts
        course_fix = CourseFixture(
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name']
        )
        problem_data = dedent('''
            <problem>
                <p>A text input problem accepts a line of text from the student, and evaluates the input for correctness based on an expected answer.</p>
                <p>The answer is correct if it matches every character of the expected answer. This can be a problem with international spelling, dates, or anything where the format of the answer is not clear.</p>
                <p>Which US state has Lansing as its capital?</p>
                <stringresponse answer="Michigan" type="ci" >
                      <textline label="Which US state has Lansing as its capital?" size="20"/>
                </stringresponse>
                <solution>
                <div class="detailed-solution">
                <p>Explanation</p>
                <p>Lansing is the capital of Michigan, although it is not Michigan's largest city, or even the seat of the county in which it resides.</p>
                </div>
                </solution>
            </problem>
        ''')

        children = XBlockFixtureDesc('chapter', 'Test Section').add_children(
            XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
                XBlockFixtureDesc('vertical', 'Test Unit').add_children(
                    XBlockFixtureDesc('problem', 'text input problem', data=problem_data),
                    XBlockFixtureDesc('crowdsourcehinter', 'test crowdsourcehinter')
                )
            )
        )

        course_fix.add_children(children).install()

        # Auto-auth register for the course.
        AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL,
                     course_id=self.course_id, staff=False).visit()
Example #23
0
    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)
Example #24
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)
Example #25
0
    def setUp(self):
        super(CertificateProgressPageTest, self).setUp()

        # set same course number as we have in fixture json
        self.course_info['number'] = "3355358979513794782079645765720179311111"

        test_certificate_config = {
            'id': 1,
            'name': 'Certificate name',
            'description': 'Certificate description',
            'course_title': 'Course title override',
            'signatories': [],
            'version': 1,
            'is_active': True
        }
        course_settings = {'certificates': test_certificate_config}

        self.course_fixture = CourseFixture(self.course_info["org"],
                                            self.course_info["number"],
                                            self.course_info["run"],
                                            self.course_info["display_name"],
                                            settings=course_settings)

        self.course_fixture.add_advanced_settings(
            {"cert_html_view_enabled": {
                "value": "true"
            }})

        self.course_fixture.add_update(
            CourseUpdateDesc(date='January 29, 2014',
                             content='Test course update1'))

        self.course_fixture.add_children(
            XBlockFixtureDesc('static_tab', 'Test Static Tab'),
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc(
                    'sequential', 'Test Subsection',
                    grader_type='Final Exam').add_children(
                        XBlockFixtureDesc(
                            'problem',
                            'Test Problem 1',
                            data=load_data_str('multiple_choice.xml')),
                        XBlockFixtureDesc('html', 'Test HTML'),
                    )),
            XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
                XBlockFixtureDesc(
                    'sequential',
                    'Test Subsection 2',
                    grader_type='Midterm Exam').add_children(
                        XBlockFixtureDesc(
                            'problem',
                            'Test Problem 2',
                            data=load_data_str('formula_problem.xml')), )))

        self.course_fixture.install()
        self.user_id = "99"  # we have created a user with this id in fixture
        self.cert_fixture = CertificateConfigFixture(self.course_id,
                                                     test_certificate_config)

        self.course_info_page = CourseInfoPage(self.browser, self.course_id)
        self.progress_page = ProgressPage(self.browser, self.course_id)
        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.course_home_page = CourseHomePage(self.browser, self.course_id)
        self.tab_nav = TabNavPage(self.browser)
Example #26
0
class LibraryContentTestBase(UniqueCourseTest):
    """ Base class for library content block tests """
    USERNAME = "******"
    EMAIL = "*****@*****.**"

    STAFF_USERNAME = "******"
    STAFF_EMAIL = "*****@*****.**"

    def populate_library_fixture(self, library_fixture):
        """
        To be overwritten by subclassed tests. Used to install a library to
        run tests on.
        """

    def setUp(self):
        """
        Set up library, course and library content XBlock
        """
        super(LibraryContentTestBase, self).setUp()

        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']
        )

        self.library_fixture = LibraryFixture('test_org', self.unique_id, 'Test Library {}'.format(self.unique_id))
        self.populate_library_fixture(self.library_fixture)

        self.library_fixture.install()
        self.library_info = self.library_fixture.library_info
        self.library_key = self.library_fixture.library_key

        # Install a course with library content xblock
        self.course_fixture = CourseFixture(
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name']
        )

        library_content_metadata = {
            'source_library_id': unicode(self.library_key),
            'mode': 'random',
            'max_count': 1,
        }

        self.lib_block = XBlockFixtureDesc('library_content', "Library Content", metadata=library_content_metadata)

        self.course_fixture.add_children(
            XBlockFixtureDesc('chapter', SECTION_NAME).add_children(
                XBlockFixtureDesc('sequential', SUBSECTION_NAME).add_children(
                    XBlockFixtureDesc('vertical', UNIT_NAME).add_children(
                        self.lib_block
                    )
                )
            )
        )

        self.course_fixture.install()

    def _change_library_content_settings(self, count=1, capa_type=None):
        """
        Performs library block refresh in Studio, configuring it to show {count} children
        """
        unit_page = self._go_to_unit_page(True)
        library_container_block = StudioLibraryContainerXBlockWrapper.from_xblock_wrapper(unit_page.xblocks[1])
        library_container_block.edit()
        editor = StudioLibraryContentEditor(self.browser, library_container_block.locator)
        editor.count = count
        if capa_type is not None:
            editor.capa_type = capa_type
        editor.save()
        self._go_to_unit_page(change_login=False)
        unit_page.wait_for_page()
        unit_page.publish_action.click()
        unit_page.wait_for_ajax()
        self.assertIn("Published and Live", unit_page.publish_title)

    @property
    def library_xblocks_texts(self):
        """
        Gets texts of all xblocks in library
        """
        return frozenset(child.data for child in self.library_fixture.children)

    def _go_to_unit_page(self, change_login=True):
        """
        Open unit page in Studio
        """
        if change_login:
            LogoutPage(self.browser).visit()
            self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.studio_course_outline.visit()

        subsection = self.studio_course_outline.section(SECTION_NAME).subsection(SUBSECTION_NAME)
        return subsection.expand_subsection().unit(UNIT_NAME).go_to()

    def _goto_library_block_page(self, block_id=None):
        """
        Open library page in LMS
        """
        self.courseware_page.visit()
        paragraphs = self.courseware_page.q(css='.course-content p').results
        if not paragraphs:
            course_home_page = CourseHomePage(self.browser, self.course_id)
            course_home_page.visit()
            course_home_page.outline.go_to_section_by_index(0, 0)
        block_id = block_id if block_id is not None else self.lib_block.locator
        #pylint: disable=attribute-defined-outside-init
        self.library_content_page = LibraryContentXBlockWrapper(self.browser, block_id)
        self.library_content_page.wait_for_page()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        AutoAuthPage(self.browser, username=username, email=email,
                     course_id=self.course_id, staff=staff).visit()
Example #27
0
class CertificateProgressPageTest(UniqueCourseTest):
    """
    Tests for verifying Certificate info on Progress tab of course page.
    """
    def setUp(self):
        super(CertificateProgressPageTest, self).setUp()

        # set same course number as we have in fixture json
        self.course_info['number'] = "3355358979513794782079645765720179311111"

        test_certificate_config = {
            'id': 1,
            'name': 'Certificate name',
            'description': 'Certificate description',
            'course_title': 'Course title override',
            'signatories': [],
            'version': 1,
            'is_active': True
        }
        course_settings = {'certificates': test_certificate_config}

        self.course_fixture = CourseFixture(self.course_info["org"],
                                            self.course_info["number"],
                                            self.course_info["run"],
                                            self.course_info["display_name"],
                                            settings=course_settings)

        self.course_fixture.add_advanced_settings(
            {"cert_html_view_enabled": {
                "value": "true"
            }})

        self.course_fixture.add_update(
            CourseUpdateDesc(date='January 29, 2014',
                             content='Test course update1'))

        self.course_fixture.add_children(
            XBlockFixtureDesc('static_tab', 'Test Static Tab'),
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc(
                    'sequential', 'Test Subsection',
                    grader_type='Final Exam').add_children(
                        XBlockFixtureDesc(
                            'problem',
                            'Test Problem 1',
                            data=load_data_str('multiple_choice.xml')),
                        XBlockFixtureDesc('html', 'Test HTML'),
                    )),
            XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
                XBlockFixtureDesc(
                    'sequential',
                    'Test Subsection 2',
                    grader_type='Midterm Exam').add_children(
                        XBlockFixtureDesc(
                            'problem',
                            'Test Problem 2',
                            data=load_data_str('formula_problem.xml')), )))

        self.course_fixture.install()
        self.user_id = "99"  # we have created a user with this id in fixture
        self.cert_fixture = CertificateConfigFixture(self.course_id,
                                                     test_certificate_config)

        self.course_info_page = CourseInfoPage(self.browser, self.course_id)
        self.progress_page = ProgressPage(self.browser, self.course_id)
        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.course_home_page = CourseHomePage(self.browser, self.course_id)
        self.tab_nav = TabNavPage(self.browser)

    def log_in_as_unique_user(self):
        """
        Log in as a valid lms user.
        """
        AutoAuthPage(self.browser,
                     username="******",
                     email="*****@*****.**",
                     password="******",
                     course_id=self.course_id).visit()

    def test_progress_page_has_view_certificate_button(self):
        """
        Scenario: View Certificate option should be present on Course Progress menu if the user is
        awarded a certificate.
        And their should be no padding around the box containing certificate info. (See SOL-1196 for details on this)

        As a Student
        Given there is a course with certificate configuration
        And I have passed the course and certificate is generated
        When I go on the Progress tab for the course
        Then I should see a 'View Certificate' button
        And their should be no padding around Certificate info box.
        """
        self.cert_fixture.install()
        self.log_in_as_unique_user()

        self.complete_course_problems()

        self.course_info_page.visit()
        self.tab_nav.go_to_tab('Progress')

        self.assertTrue(
            self.progress_page.q(css='.auto-cert-message').first.visible)

        actual_padding = get_element_padding(self.progress_page,
                                             '.wrapper-msg.wrapper-auto-cert')
        actual_padding = [
            int(padding) for padding in actual_padding.itervalues()
        ]
        expected_padding = [0, 0, 0, 0]

        # Verify that their is no padding around the box containing certificate info.
        self.assertEqual(actual_padding, expected_padding)

    def complete_course_problems(self):
        """
        Complete Course Problems.

        Problems were added in the setUp
        """
        # self.course_info_page.visit()
        # self.tab_nav.go_to_tab('Course')
        #
        # # TODO: TNL-6546: Remove extra visit call.
        self.course_home_page.visit()

        # Navigate to Test Subsection in Test Section Section
        self.course_home_page.outline.go_to_section('Test Section',
                                                    'Test Subsection')

        # Navigate to Test Problem 1
        self.courseware_page.nav.go_to_vertical('Test Problem 1')

        # Select correct value for from select menu
        self.courseware_page.q(
            css='select option[value="{}"]'.format('blue')).first.click()

        # Select correct radio button for the answer
        self.courseware_page.q(
            css='fieldset div.field:nth-child(4) input').nth(0).click()

        # Select correct radio buttons for the answer
        self.courseware_page.q(
            css='fieldset div.field:nth-child(2) input').nth(1).click()
        self.courseware_page.q(
            css='fieldset div.field:nth-child(4) input').nth(1).click()

        # Submit the answer
        self.courseware_page.q(css='button.submit').click()
        self.courseware_page.wait_for_ajax()

        # Navigate to the 'Test Subsection 2' of 'Test Section 2'
        self.course_home_page.visit()
        self.course_home_page.outline.go_to_section('Test Section 2',
                                                    'Test Subsection 2')

        # Navigate to Test Problem 2
        self.courseware_page.nav.go_to_vertical('Test Problem 2')

        # Fill in the answer of the problem
        self.courseware_page.q(
            css='input[id^=input_][id$=_2_1]').fill('A*x^2 + sqrt(y)')

        # Submit the answer
        self.courseware_page.q(css='button.submit').click()
        self.courseware_page.wait_for_ajax()
Example #28
0
class VideoBaseTest(UniqueCourseTest):
    """
    Base class for tests of the Video Player
    Sets up the course and provides helper functions for the Video tests.
    """
    def setUp(self):
        """
        Initialization of pages and course fixture for video tests
        """
        super(VideoBaseTest, self).setUp()
        self.longMessage = True

        self.video = VideoPage(self.browser)
        self.tab_nav = TabNavPage(self.browser)
        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.course_info_page = CourseInfoPage(self.browser, self.course_id)
        self.auth_page = AutoAuthPage(self.browser, course_id=self.course_id)

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

        self.metadata = None
        self.assets = []
        self.contents_of_verticals = None
        self.youtube_configuration = {}
        self.user_info = {}

        # reset youtube stub server
        self.addCleanup(YouTubeStubConfig.reset)

    def navigate_to_video(self):
        """ Prepare the course and get to the video and render it """
        self._install_course_fixture()
        self._navigate_to_courseware_video_and_render()

    def navigate_to_video_no_render(self):
        """
        Prepare the course and get to the video unit
        however do not wait for it to render, because
        the has been an error.
        """
        self._install_course_fixture()
        self._navigate_to_courseware_video_no_render()

    def _install_course_fixture(self):
        """ Install the course fixture that has been defined """
        if self.assets:
            self.course_fixture.add_asset(self.assets)

        chapter_sequential = XBlockFixtureDesc('sequential', 'Test Section')
        chapter_sequential.add_children(*self._add_course_verticals())
        chapter = XBlockFixtureDesc(
            'chapter', 'Test Chapter').add_children(chapter_sequential)
        self.course_fixture.add_children(chapter)
        self.course_fixture.install()

        if len(self.youtube_configuration) > 0:
            YouTubeStubConfig.configure(self.youtube_configuration)

    def _add_course_verticals(self):
        """
        Create XBlockFixtureDesc verticals
        :return: a list of XBlockFixtureDesc
        """
        xblock_verticals = []
        _contents_of_verticals = self.contents_of_verticals

        # Video tests require at least one vertical with a single video.
        if not _contents_of_verticals:
            _contents_of_verticals = [[{
                'display_name': 'Video',
                'metadata': self.metadata
            }]]

        for vertical_index, vertical in enumerate(_contents_of_verticals):
            xblock_verticals.append(
                self._create_single_vertical(vertical, vertical_index))

        return xblock_verticals

    def _create_single_vertical(self, vertical_contents, vertical_index):
        """
        Create a single course vertical of type XBlockFixtureDesc with category `vertical`.
        A single course vertical can contain single or multiple video modules.
        :param vertical_contents: a list of items for the vertical to contain
        :param vertical_index: index for the vertical display name
        :return: XBlockFixtureDesc
        """
        xblock_course_vertical = XBlockFixtureDesc(
            'vertical', 'Test Vertical-{0}'.format(vertical_index))

        for video in vertical_contents:
            xblock_course_vertical.add_children(
                XBlockFixtureDesc('video',
                                  video['display_name'],
                                  metadata=video.get('metadata')))

        return xblock_course_vertical

    def _navigate_to_courseware_video(self):
        """ Register for the course and navigate to the video unit """
        self.auth_page.visit()
        self.user_info = self.auth_page.user_info
        self.courseware_page.visit()

    def _navigate_to_courseware_video_and_render(self):
        """ Wait for the video player to render """
        self._navigate_to_courseware_video()
        self.video.wait_for_video_player_render()

    def _navigate_to_courseware_video_no_render(self):
        """ Wait for the video Xmodule but not for rendering """
        self._navigate_to_courseware_video()
        self.video.wait_for_video_class()

    def metadata_for_mode(self, player_mode, additional_data=None):
        """
        Create a dictionary for video player configuration according to `player_mode`
        :param player_mode (str): Video player mode
        :param additional_data (dict): Optional additional metadata.
        :return: dict
        """
        metadata = {}
        youtube_ids = {
            'youtube_id_1_0': '',
            'youtube_id_0_75': '',
            'youtube_id_1_25': '',
            'youtube_id_1_5': '',
        }

        if player_mode == 'html5':
            metadata.update(youtube_ids)
            metadata.update({'html5_sources': HTML5_SOURCES})

        if player_mode == 'youtube_html5':
            metadata.update({
                'html5_sources': HTML5_SOURCES,
            })

        if player_mode == 'youtube_html5_unsupported_video':
            metadata.update({'html5_sources': HTML5_SOURCES_INCORRECT})

        if player_mode == 'html5_unsupported_video':
            metadata.update(youtube_ids)
            metadata.update({'html5_sources': HTML5_SOURCES_INCORRECT})

        if player_mode == 'hls':
            metadata.update(youtube_ids)
            metadata.update({
                'html5_sources': HLS_SOURCES,
            })

        if player_mode == 'html5_and_hls':
            metadata.update(youtube_ids)
            metadata.update({
                'html5_sources': HTML5_SOURCES + HLS_SOURCES,
            })

        if additional_data:
            metadata.update(additional_data)

        return metadata

    def go_to_sequential_position(self, position):
        """
        Navigate to sequential specified by `video_display_name`
        """
        self.courseware_page.go_to_sequential_position(position)
        self.video.wait_for_video_player_render()
class LibraryContentTestBase(UniqueCourseTest):
    """ Base class for library content block tests """
    USERNAME = "******"
    EMAIL = "*****@*****.**"

    STAFF_USERNAME = "******"
    STAFF_EMAIL = "*****@*****.**"

    def populate_library_fixture(self, library_fixture):
        """
        To be overwritten by subclassed tests. Used to install a library to
        run tests on.
        """

    def setUp(self):
        """
        Set up library, course and library content XBlock
        """
        super(LibraryContentTestBase, self).setUp()

        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'])

        self.library_fixture = LibraryFixture(
            'test_org', self.unique_id,
            'Test Library {}'.format(self.unique_id))
        self.populate_library_fixture(self.library_fixture)

        self.library_fixture.install()
        self.library_info = self.library_fixture.library_info
        self.library_key = self.library_fixture.library_key

        # Install a course with library content xblock
        self.course_fixture = CourseFixture(self.course_info['org'],
                                            self.course_info['number'],
                                            self.course_info['run'],
                                            self.course_info['display_name'])

        library_content_metadata = {
            'source_library_id': unicode(self.library_key),
            'mode': 'random',
            'max_count': 1,
        }

        self.lib_block = XBlockFixtureDesc('library_content',
                                           "Library Content",
                                           metadata=library_content_metadata)

        self.course_fixture.add_children(
            XBlockFixtureDesc('chapter', SECTION_NAME).add_children(
                XBlockFixtureDesc('sequential', SUBSECTION_NAME).add_children(
                    XBlockFixtureDesc('vertical', UNIT_NAME).add_children(
                        self.lib_block))))

        self.course_fixture.install()

    def _change_library_content_settings(self, count=1, capa_type=None):
        """
        Performs library block refresh in Studio, configuring it to show {count} children
        """
        unit_page = self._go_to_unit_page(True)
        library_container_block = StudioLibraryContainerXBlockWrapper.from_xblock_wrapper(
            unit_page.xblocks[1])
        library_container_block.edit()
        editor = StudioLibraryContentEditor(self.browser,
                                            library_container_block.locator)
        editor.count = count
        if capa_type is not None:
            editor.capa_type = capa_type
        editor.save()
        self._go_to_unit_page(change_login=False)
        unit_page.wait_for_page()
        unit_page.publish_action.click()
        unit_page.wait_for_ajax()
        self.assertIn("Published and Live", unit_page.publish_title)

    @property
    def library_xblocks_texts(self):
        """
        Gets texts of all xblocks in library
        """
        return frozenset(child.data for child in self.library_fixture.children)

    def _go_to_unit_page(self, change_login=True):
        """
        Open unit page in Studio
        """
        if change_login:
            LogoutPage(self.browser).visit()
            self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
        self.studio_course_outline.visit()

        subsection = self.studio_course_outline.section(
            SECTION_NAME).subsection(SUBSECTION_NAME)
        return subsection.expand_subsection().unit(UNIT_NAME).go_to()

    def _goto_library_block_page(self, block_id=None):
        """
        Open library page in LMS
        """
        self.courseware_page.visit()
        paragraphs = self.courseware_page.q(css='.course-content p').results
        if not paragraphs:
            course_home_page = CourseHomePage(self.browser, self.course_id)
            course_home_page.visit()
            course_home_page.outline.go_to_section_by_index(0, 0)
        block_id = block_id if block_id is not None else self.lib_block.locator
        #pylint: disable=attribute-defined-outside-init
        self.library_content_page = LibraryContentXBlockWrapper(
            self.browser, block_id)
        self.library_content_page.wait_for_page()

    def _auto_auth(self, username, email, staff):
        """
        Logout and login with given credentials.
        """
        AutoAuthPage(self.browser,
                     username=username,
                     email=email,
                     course_id=self.course_id,
                     staff=staff).visit()
Example #30
0
 def is_browser_on_page(self):
     if not CoursewarePage.is_browser_on_page(self):
         return False
     return StaffPreviewPage.is_browser_on_page(self)
Example #31
0
class VideoLicenseTest(StudioCourseTest):
    """
    Tests for video module-level licensing (that is, setting the license,
    for a specific video module, to All Rights Reserved or Creative Commons)
    """
    def setUp(self):  # pylint: disable=arguments-differ
        super(VideoLicenseTest, self).setUp()

        self.lms_courseware = CoursewarePage(
            self.browser,
            self.course_id,
        )
        self.studio_course_outline = CourseOutlinePage(
            self.browser, self.course_info['org'], self.course_info['number'],
            self.course_info['run'])

    # used by StudioCourseTest.setUp()
    def populate_course_fixture(self, course_fixture):
        """
        Create a course with a single chapter.
        That chapter has a single section.
        That section has a single vertical.
        That vertical has a single video element.
        """
        video_block = XBlockFixtureDesc('video', "Test Video")
        vertical = XBlockFixtureDesc('vertical', "Test Vertical")
        vertical.add_children(video_block)
        sequential = XBlockFixtureDesc('sequential', "Test Section")
        sequential.add_children(vertical)
        chapter = XBlockFixtureDesc('chapter', "Test Chapter")
        chapter.add_children(sequential)
        self.course_fixture.add_children(chapter)

    def test_empty_license(self):
        """
        When I visit the LMS courseware,
        I can see that the video is present
        but it has no license displayed by default.
        """
        self.lms_courseware.visit()
        video = self.lms_courseware.q(css=".vert .xblock .video")
        self.assertTrue(video.is_present())
        video_license = self.lms_courseware.q(
            css=".vert .xblock.xmodule_VideoModule .xblock-license")
        self.assertFalse(video_license.is_present())

    def test_arr_license(self):
        """
        When I edit a video element in Studio,
        I can set an "All Rights Reserved" license on that video element.
        When I visit the LMS courseware,
        I can see that the video is present
        and that it has "All Rights Reserved" displayed for the license.
        """
        self.studio_course_outline.visit()
        subsection = self.studio_course_outline.section_at(0).subsection_at(0)
        subsection.expand_subsection()
        unit = subsection.unit_at(0)
        container_page = unit.go_to()
        container_page.edit()
        video = [
            xb for xb in container_page.xblocks if xb.name == "Test Video"
        ][0]
        video.open_advanced_tab()
        video.set_license('all-rights-reserved')
        video.save_settings()
        container_page.publish_action.click()

        self.lms_courseware.visit()
        video = self.lms_courseware.q(css=".vert .xblock .video")
        self.assertTrue(video.is_present())
        video_license_css = ".vert .xblock.xmodule_VideoModule .xblock-license"
        self.lms_courseware.wait_for_element_presence(
            video_license_css, "Video module license block is present")
        video_license = self.lms_courseware.q(css=video_license_css)
        self.assertEqual(video_license.text[0], "© All Rights Reserved")

    def test_cc_license(self):
        """
        When I edit a video element in Studio,
        I can set a "Creative Commons" license on that video element.
        When I visit the LMS courseware,
        I can see that the video is present
        and that it has "Some Rights Reserved" displayed for the license.
        """
        self.studio_course_outline.visit()
        subsection = self.studio_course_outline.section_at(0).subsection_at(0)
        subsection.expand_subsection()
        unit = subsection.unit_at(0)
        container_page = unit.go_to()
        container_page.edit()
        video = [
            xb for xb in container_page.xblocks if xb.name == "Test Video"
        ][0]
        video.open_advanced_tab()
        video.set_license('creative-commons')
        video.save_settings()
        container_page.publish_action.click()

        self.lms_courseware.visit()
        video = self.lms_courseware.q(css=".vert .xblock .video")
        self.assertTrue(video.is_present())
        video_license_css = ".vert .xblock.xmodule_VideoModule .xblock-license"
        self.lms_courseware.wait_for_element_presence(
            video_license_css, "Video module license block is present")
        video_license = self.lms_courseware.q(css=video_license_css)
        self.assertIn("Some Rights Reserved", video_license.text[0])
Example #32
0
 def is_browser_on_page(self):
     if not CoursewarePage.is_browser_on_page(self):
         return False
     return StaffPreviewPage.is_browser_on_page(self)
Example #33
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))
class ContentLicenseTest(StudioCourseTest):
    """
    Tests for course-level licensing (that is, setting the license,
    for an entire course's content, to All Rights Reserved or Creative Commons)
    """
    def setUp(self):  # pylint: disable=arguments-differ
        super(ContentLicenseTest, self).setUp()
        self.outline_page = CourseOutlinePage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )
        self.settings_page = SettingsPage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )
        self.lms_courseware = CoursewarePage(
            self.browser,
            self.course_id,
        )
        self.settings_page.visit()

    def test_empty_license(self):
        """
        When I visit the Studio settings page,
        I see that the course license is "All Rights Reserved" by default.
        Then I visit the LMS courseware page,
        and I see that the default course license is displayed.
        """
        self.assertEqual(self.settings_page.course_license, "All Rights Reserved")
        self.lms_courseware.visit()
        self.assertEqual(self.lms_courseware.course_license, "© All Rights Reserved")

    def test_arr_license(self):
        """
        When I visit the Studio settings page,
        and I set the course license to "All Rights Reserved",
        and I refresh the page,
        I see that the course license is "All Rights Reserved".
        Then I visit the LMS courseware page,
        and I see that the course license is "All Rights Reserved".
        """
        self.settings_page.course_license = "All Rights Reserved"
        self.settings_page.save_changes()
        self.settings_page.refresh_and_wait_for_load()
        self.assertEqual(self.settings_page.course_license, "All Rights Reserved")

        self.lms_courseware.visit()
        self.assertEqual(self.lms_courseware.course_license, "© All Rights Reserved")

    def test_cc_license(self):
        """
        When I visit the Studio settings page,
        and I set the course license to "Creative Commons",
        and I refresh the page,
        I see that the course license is "Creative Commons".
        Then I visit the LMS courseware page,
        and I see that the course license is "Some Rights Reserved".
        """
        self.settings_page.course_license = "Creative Commons"
        self.settings_page.save_changes()
        self.settings_page.refresh_and_wait_for_load()
        self.assertEqual(self.settings_page.course_license, "Creative Commons")

        self.lms_courseware.visit()
        # The course_license text will include a bunch of screen reader text to explain
        # the selected options
        self.assertIn("Some Rights Reserved", self.lms_courseware.course_license)
Example #35
0
 def test_visit_coursware(self):
     """
     Produce a HAR for loading the Coursware page.
     """
     courseware_page = CoursewarePage(self.browser, self.course_id)
     self._make_har_file(courseware_page)
class AnnotatableProblemTest(UniqueCourseTest):
    """
    Tests for annotation components.
    """
    USERNAME = "******"
    EMAIL = "*****@*****.**"

    DATA_TEMPLATE = dedent("""\
        <annotatable>
            <instructions>Instruction text</instructions>
            <p>{}</p>
        </annotatable>
    """)

    ANNOTATION_TEMPLATE = dedent("""\
        Before {0}.
        <annotation title="region {0}" body="Comment {0}" highlight="yellow" problem="{0}">
            Region Contents {0}
        </annotation>
        After {0}.
    """)

    PROBLEM_TEMPLATE = dedent("""\
    <problem max_attempts="1" weight="">
      <annotationresponse>
        <annotationinput>
          <title>Question {number}</title>
          <text>Region Contents {number}</text>
          <comment>What number is this region?</comment>
          <comment_prompt>Type your response below:</comment_prompt>
          <tag_prompt>What number is this region?</tag_prompt>
          <options>
          {options}
          </options>
        </annotationinput>
      </annotationresponse>
      <solution>
        This problem is checking region {number}
      </solution>
    </problem>
    """)

    OPTION_TEMPLATE = """<option choice="{correctness}">{number}</option>"""

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

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

        # Install a course with two annotations and two annotations problems.
        course_fix = CourseFixture(
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name']
        )

        self.annotation_count = 2
        course_fix.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
                    XBlockFixtureDesc('vertical', 'Test Annotation Vertical').add_children(
                        XBlockFixtureDesc('annotatable', 'Test Annotation Module',
                                          data=self.DATA_TEMPLATE.format("\n".join(
                                              self.ANNOTATION_TEMPLATE.format(i) for i in xrange(self.annotation_count)
                                          ))),
                        XBlockFixtureDesc('problem', 'Test Annotation Problem 0',
                                          data=self.PROBLEM_TEMPLATE.format(number=0, options="\n".join(
                                              self.OPTION_TEMPLATE.format(
                                                  number=k,
                                                  correctness=_correctness(k, 0))
                                              for k in xrange(self.annotation_count)
                                          ))),
                        XBlockFixtureDesc('problem', 'Test Annotation Problem 1',
                                          data=self.PROBLEM_TEMPLATE.format(number=1, options="\n".join(
                                              self.OPTION_TEMPLATE.format(
                                                  number=k,
                                                  correctness=_correctness(k, 1))
                                              for k in xrange(self.annotation_count)
                                          )))
                    )
                )
            )
        ).install()

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

    def _goto_annotation_component_page(self):
        """
        Open annotation component page with assertion.
        """
        self.courseware_page.visit()
        annotation_component_page = AnnotationComponentPage(self.browser)
        self.assertEqual(
            annotation_component_page.component_name, 'Test Annotation Module'.format()
        )
        return annotation_component_page

    def test_annotation_component(self):
        """
        Test annotation components links to annotation problems.
        """

        annotation_component_page = self._goto_annotation_component_page()
        # This will avoid scrolling related problems on different browsers and instead directly jump on the problem
        disable_animations(annotation_component_page)

        for i in xrange(self.annotation_count):
            annotation_component_page.click_reply_annotation(i)
            self.assertTrue(annotation_component_page.check_scroll_to_problem())

            annotation_component_page.answer_problem()
            self.assertTrue(annotation_component_page.check_feedback())

            annotation_component_page.click_return_to_annotation()
            self.assertTrue(annotation_component_page.check_scroll_to_annotation())
Example #37
0
 def __init__(self, browser, course_id):
     CoursewarePage.__init__(self, browser, course_id)
     StaffPreviewPage.__init__(self, browser)
Example #38
0
 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)
class BookmarksTestMixin(EventsTestMixin, UniqueCourseTest):
    """
    Mixin with helper methods for testing Bookmarks.
    """
    USERNAME = "******"
    EMAIL = "*****@*****.**"

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

        self.studio_course_outline_page = StudioCourseOutlinePage(
            self.browser, self.course_info['org'], self.course_info['number'],
            self.course_info['run'])

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

        # 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 setup_test(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.
        AutoAuthPage(self.browser,
                     username=self.USERNAME,
                     email=self.EMAIL,
                     course_id=self.course_id).visit()

        self.courseware_page.visit()

    def create_course_fixture(self, num_chapters):
        """
        Create course fixture

        Arguments:
            num_chapters: number of chapters to create
        """
        self.course_fixture = CourseFixture(  # pylint: disable=attribute-defined-outside-init
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name'])

        xblocks = []
        for index in range(num_chapters):
            xblocks += [
                XBlockFixtureDesc(
                    'chapter', 'TestSection{}'.format(index)).add_children(
                        XBlockFixtureDesc(
                            'sequential',
                            'TestSubsection{}'.format(index)).add_children(
                                XBlockFixtureDesc(
                                    'vertical',
                                    'TestVertical{}'.format(index))))
            ]
        self.course_fixture.add_children(*xblocks).install()

    def verify_event_data(self, event_type, event_data):
        """
        Verify emitted event data.

        Arguments:
            event_type: expected event type
            event_data: expected event data
        """
        actual_events = self.wait_for_events(
            event_filter={'event_type': event_type}, number_of_matches=1)
        self.assert_events_match(event_data, actual_events)

    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)
Example #40
0
class VideoBaseTest(UniqueCourseTest):
    """
    Base class for tests of the Video Player
    Sets up the course and provides helper functions for the Video tests.
    """

    def setUp(self):
        """
        Initialization of pages and course fixture for video tests
        """
        super(VideoBaseTest, self).setUp()
        self.longMessage = True

        self.video = VideoPage(self.browser)
        self.tab_nav = TabNavPage(self.browser)
        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        self.course_info_page = CourseInfoPage(self.browser, self.course_id)
        self.auth_page = AutoAuthPage(self.browser, course_id=self.course_id)

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

        self.metadata = None
        self.assets = []
        self.contents_of_verticals = None
        self.youtube_configuration = {}
        self.user_info = {}

        # reset youtube stub server
        self.addCleanup(YouTubeStubConfig.reset)

    def navigate_to_video(self):
        """ Prepare the course and get to the video and render it """
        self._install_course_fixture()
        self._navigate_to_courseware_video_and_render()

    def navigate_to_video_no_render(self):
        """
        Prepare the course and get to the video unit
        however do not wait for it to render, because
        the has been an error.
        """
        self._install_course_fixture()
        self._navigate_to_courseware_video_no_render()

    def _install_course_fixture(self):
        """ Install the course fixture that has been defined """
        if self.assets:
            self.course_fixture.add_asset(self.assets)

        chapter_sequential = XBlockFixtureDesc('sequential', 'Test Section')
        chapter_sequential.add_children(*self._add_course_verticals())
        chapter = XBlockFixtureDesc('chapter', 'Test Chapter').add_children(chapter_sequential)
        self.course_fixture.add_children(chapter)
        self.course_fixture.install()

        if len(self.youtube_configuration) > 0:
            YouTubeStubConfig.configure(self.youtube_configuration)

    def _add_course_verticals(self):
        """
        Create XBlockFixtureDesc verticals
        :return: a list of XBlockFixtureDesc
        """
        xblock_verticals = []
        _contents_of_verticals = self.contents_of_verticals

        # Video tests require at least one vertical with a single video.
        if not _contents_of_verticals:
            _contents_of_verticals = [[{'display_name': 'Video', 'metadata': self.metadata}]]

        for vertical_index, vertical in enumerate(_contents_of_verticals):
            xblock_verticals.append(self._create_single_vertical(vertical, vertical_index))

        return xblock_verticals

    def _create_single_vertical(self, vertical_contents, vertical_index):
        """
        Create a single course vertical of type XBlockFixtureDesc with category `vertical`.
        A single course vertical can contain single or multiple video modules.
        :param vertical_contents: a list of items for the vertical to contain
        :param vertical_index: index for the vertical display name
        :return: XBlockFixtureDesc
        """
        xblock_course_vertical = XBlockFixtureDesc('vertical', u'Test Vertical-{0}'.format(vertical_index))

        for video in vertical_contents:
            xblock_course_vertical.add_children(
                XBlockFixtureDesc('video', video['display_name'], metadata=video.get('metadata')))

        return xblock_course_vertical

    def _navigate_to_courseware_video(self):
        """ Register for the course and navigate to the video unit """
        self.auth_page.visit()
        self.user_info = self.auth_page.user_info
        self.courseware_page.visit()

    def _navigate_to_courseware_video_and_render(self):
        """ Wait for the video player to render """
        self._navigate_to_courseware_video()
        self.video.wait_for_video_player_render()

    def _navigate_to_courseware_video_no_render(self):
        """ Wait for the video Xmodule but not for rendering """
        self._navigate_to_courseware_video()
        self.video.wait_for_video_class()

    def metadata_for_mode(self, player_mode, additional_data=None):
        """
        Create a dictionary for video player configuration according to `player_mode`
        :param player_mode (str): Video player mode
        :param additional_data (dict): Optional additional metadata.
        :return: dict
        """
        metadata = {}
        youtube_ids = {
            'youtube_id_1_0': '',
            'youtube_id_0_75': '',
            'youtube_id_1_25': '',
            'youtube_id_1_5': '',
        }

        if player_mode == 'html5':
            metadata.update(youtube_ids)
            metadata.update({
                'html5_sources': HTML5_SOURCES
            })

        if player_mode == 'youtube_html5':
            metadata.update({
                'html5_sources': HTML5_SOURCES,
            })

        if player_mode == 'youtube_html5_unsupported_video':
            metadata.update({
                'html5_sources': HTML5_SOURCES_INCORRECT
            })

        if player_mode == 'html5_unsupported_video':
            metadata.update(youtube_ids)
            metadata.update({
                'html5_sources': HTML5_SOURCES_INCORRECT
            })

        if player_mode == 'hls':
            metadata.update(youtube_ids)
            metadata.update({
                'html5_sources': HLS_SOURCES,
            })

        if player_mode == 'html5_and_hls':
            metadata.update(youtube_ids)
            metadata.update({
                'html5_sources': HTML5_SOURCES + HLS_SOURCES,
            })

        if additional_data:
            metadata.update(additional_data)

        return metadata

    def go_to_sequential_position(self, position):
        """
        Navigate to sequential specified by `video_display_name`
        """
        self.courseware_page.go_to_sequential_position(position)
        self.video.wait_for_video_player_render()
class DragAndDropXblockWithMixinsTest(UniqueCourseTest):
    """
    Test Suite to verify various behaviors of DragAndDrop Xblock on the LMS.
    """

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

        self.username = "******".format(uuid=self.unique_id[0:8])
        self.email = "{username}@example.com".format(username=self.username)
        self.password = "******"
        self.courseware_page = CoursewarePage(self.browser, self.course_id)

        # Install a course with a hierarchy and problems
        self.course_fixture = CourseFixture(
            self.course_info['org'], self.course_info['number'],
            self.course_info['run'], self.course_info['display_name'],
            start_date=datetime.now() + timedelta(days=10)
        )
        self.browser.set_window_size(1024, 1024)

    def setup_sequential(self, metadata):
        """
        Setup a sequential with DnD problem, alongwith the metadata provided.

        This method will allow to customize the sequential, such as changing the
        due date for individual tests.
        """
        problem = self.get_problem()
        sequential = self.get_sequential(metadata=metadata)
        self.course_fixture.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                sequential.add_children(problem)
            )
        ).install()

        # Auto-auth register for the course.
        AutoAuthPage(
            self.browser,
            username=self.username,
            email=self.email,
            password=self.password,
            course_id=self.course_id,
            staff=True
        ).visit()

    def format_date(self, date_value):
        """
        Get the date in isoformat as this is required format to add date data
        in the sequential.
        """
        return date_value.isoformat()

    def get_problem(self):
        """
        Creating a DnD problem with assessment mode
        """
        return XBlockFixtureDesc('drag-and-drop-v2', 'DnD', metadata={'mode': "assessment"})

    def get_sequential(self, metadata=None):
        return XBlockFixtureDesc('sequential', 'Test Subsection', metadata=metadata)

    @ddt.data(
        (datetime.now(), True),
        (datetime.now() - timedelta(days=1), True),
        (datetime.now() + timedelta(days=1), False)
    )
    @ddt.unpack
    def test_submit_button_status_with_due_date(self, due_date, is_button_disabled):
        """
        Scenario: Test that DnD submit button will be enabled if section is not past due.

        Given I have a sequential in instructor-paced course
        And a DnD problem with assessment mode is present in the sequential
        When I visit the problem
        Then the submit button should be present
        And button should be disabled as some item needs to be on a zone
        When I drag an item to a zone
        Then submit button will be enabled if due date has not passed, else disabled
        """
        problem_page = DragAndDropPage(self.browser)
        self.setup_sequential(metadata={'due': self.format_date(due_date)})
        self.courseware_page.visit()
        self.assertTrue(problem_page.is_submit_button_present())
        self.assertTrue(problem_page.is_submit_disabled())
        problem_page.drag_item_to_zone(0, 'middle')
        self.assertEqual(is_button_disabled, problem_page.is_submit_disabled())

    def test_submit_button_when_pacing_change_self_paced(self):
        """
        Scenario: For a self-paced course, the submit button of DnD problems will be
        be enabled, regardless of the subsection due date.

        Given a DnD problem in a subsection with past due date
        And the course is instructor-paced
        Then the submit button will remain disabled after initial drag
        When the pacing is changed to self-paced
        Then the submit button is not disabled anymore
        """
        problem_page = DragAndDropPage(self.browser)
        self.setup_sequential(metadata={'due': self.format_date(datetime.now())})
        self.courseware_page.visit()
        problem_page.drag_item_to_zone(0, 'middle')
        self.assertTrue(problem_page.is_submit_disabled())
        self.course_fixture.add_course_details({'self_paced': True})
        self.course_fixture.configure_course()
        self.courseware_page.visit()
        self.assertFalse(problem_page.is_submit_disabled())
Example #42
0
 def __init__(self, browser, course_id):
     CoursewarePage.__init__(self, browser, course_id)
     StaffPreviewPage.__init__(self, browser)
Example #43
0
    def setUp(self):
        super(ConditionalTest, self).setUp()

        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        AutoAuthPage(self.browser, course_id=self.course_id,
                     staff=False).visit()
class ContentLicenseTest(StudioCourseTest):
    """
    Tests for course-level licensing (that is, setting the license,
    for an entire course's content, to All Rights Reserved or Creative Commons)
    """
    def setUp(self):  # pylint: disable=arguments-differ
        super(ContentLicenseTest, self).setUp()
        self.outline_page = CourseOutlinePage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )
        self.settings_page = SettingsPage(
            self.browser,
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run']
        )
        self.lms_courseware = CoursewarePage(
            self.browser,
            self.course_id,
        )
        self.settings_page.visit()

    def test_empty_license(self):
        """
        When I visit the Studio settings page,
        I see that the course license is "All Rights Reserved" by default.
        Then I visit the LMS courseware page,
        and I see that the default course license is displayed.
        """
        self.assertEqual(self.settings_page.course_license, "All Rights Reserved")
        self.lms_courseware.visit()
        self.assertEqual(self.lms_courseware.course_license, "© All Rights Reserved")

    def test_arr_license(self):
        """
        When I visit the Studio settings page,
        and I set the course license to "All Rights Reserved",
        and I refresh the page,
        I see that the course license is "All Rights Reserved".
        Then I visit the LMS courseware page,
        and I see that the course license is "All Rights Reserved".
        """
        self.settings_page.course_license = "All Rights Reserved"
        self.settings_page.save_changes()
        self.settings_page.refresh_and_wait_for_load()
        self.assertEqual(self.settings_page.course_license, "All Rights Reserved")

        self.lms_courseware.visit()
        self.assertEqual(self.lms_courseware.course_license, "© All Rights Reserved")

    def test_cc_license(self):
        """
        When I visit the Studio settings page,
        and I set the course license to "Creative Commons",
        and I refresh the page,
        I see that the course license is "Creative Commons".
        Then I visit the LMS courseware page,
        and I see that the course license is "Some Rights Reserved".
        """
        self.settings_page.course_license = "Creative Commons"
        self.settings_page.save_changes()
        self.settings_page.refresh_and_wait_for_load()
        self.assertEqual(self.settings_page.course_license, "Creative Commons")

        self.lms_courseware.visit()
        # The course_license text will include a bunch of screen reader text to explain
        # the selected options
        self.assertIn("Some Rights Reserved", self.lms_courseware.course_license)
Example #45
0
class ConditionalTest(UniqueCourseTest):
    """
    Test the conditional module in the lms.
    """
    shard = 23

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

        self.courseware_page = CoursewarePage(self.browser, self.course_id)
        AutoAuthPage(self.browser, course_id=self.course_id,
                     staff=False).visit()

    def install_course_fixture(self, block_type='problem'):
        """
        Install a course fixture
        """
        course_fixture = CourseFixture(
            self.course_info['org'],
            self.course_info['number'],
            self.course_info['run'],
            self.course_info['display_name'],
        )
        vertical = XBlockFixtureDesc('vertical', 'Test Unit')
        # populate the course fixture with the right conditional modules
        course_fixture.add_children(
            XBlockFixtureDesc('chapter', 'Test Section').add_children(
                XBlockFixtureDesc('sequential',
                                  'Test Subsection').add_children(vertical)))
        course_fixture.install()

        # Construct conditional block
        source_block = None
        conditional_attr = None
        conditional_value = None
        if block_type == 'problem':
            problem_factory = StringResponseXMLFactory()
            problem_xml = problem_factory.build_xml(
                question_text='The answer is "correct string"',
                case_sensitive=False,
                answer='correct string',
            ),
            problem = XBlockFixtureDesc('problem',
                                        'Test Problem',
                                        data=problem_xml[0])
            source_block = problem
            conditional_attr = 'attempted'
            conditional_value = 'True'
        elif block_type == 'poll':
            poll = XBlockFixtureDesc(
                'poll_question',
                'Conditional Poll',
                question='Is this a good poll?',
                answers=[{
                    'id': 'yes',
                    'text': POLL_ANSWER
                }, {
                    'id': 'no',
                    'text': 'Of course not!'
                }],
            )
            conditional_attr = 'poll_answer'
            conditional_value = 'yes'
            source_block = poll
        else:
            raise NotImplementedError()

        course_fixture.create_xblock(vertical.locator, source_block)
        # create conditional
        conditional = XBlockFixtureDesc('conditional',
                                        'Test Conditional',
                                        sources_list=[source_block.locator],
                                        conditional_attr=conditional_attr,
                                        conditional_value=conditional_value)
        result_block = XBlockFixtureDesc(
            'html',
            'Conditional Contents',
            data='<html><div class="hidden-contents">Hidden Contents</p></html>'
        )
        course_fixture.create_xblock(vertical.locator, conditional)
        course_fixture.create_xblock(conditional.locator, result_block)

    def test_conditional_hides_content(self):
        self.install_course_fixture()
        self.courseware_page.visit()
        conditional_page = ConditionalPage(self.browser)
        self.assertFalse(conditional_page.is_content_visible())

    def test_conditional_displays_content(self):
        self.install_course_fixture()
        self.courseware_page.visit()
        # Answer the problem
        problem_page = ProblemPage(self.browser)
        problem_page.fill_answer('correct string')
        problem_page.click_submit()
        # The conditional does not update on its own, so we need to reload the page.
        self.courseware_page.visit()
        # Verify that we can see the content.
        conditional_page = ConditionalPage(self.browser)
        self.assertTrue(conditional_page.is_content_visible())

    def test_conditional_handles_polls(self):
        self.install_course_fixture(block_type='poll')
        self.courseware_page.visit()
        # Fill in the conditional page poll
        conditional_page = ConditionalPage(self.browser)
        conditional_page.fill_in_poll()
        # The conditional does not update on its own, so we need to reload the page.
        self.courseware_page.visit()
        self.assertTrue(conditional_page.is_content_visible())
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)"
        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, 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())

        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())
Example #47
0
 def setup_thread_page(self, thread_id):
     CoursewarePage(self.browser, self.course_id).visit()
     self.show_thread(thread_id)
Example #48
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())
Example #49
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)