class LibraryContentTestBase(UniqueCourseTest): """ Base class for library content block tests """ USERNAME = "******" EMAIL = "*****@*****.**" STAFF_USERNAME = "******" STAFF_EMAIL = "*****@*****.**" shard = 10 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, u'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': six.text_type(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() 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()
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.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'] ) 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.course_outline.visit() self.course_outline.open_subsection_settings_dialog(0) self.course_outline.select_advanced_tab(desired_item='gated_content') self.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.course_outline.visit() self.course_outline.open_subsection_settings_dialog(1) self.course_outline.select_advanced_tab(desired_item='gated_content') self.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_check() 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.course_outline.visit() self.course_outline.open_subsection_settings_dialog(0) self.course_outline.select_advanced_tab(desired_item='gated_content') self.assertTrue(self.course_outline.gating_prerequisite_checkbox_is_visible()) self.assertTrue(self.course_outline.gating_prerequisite_checkbox_is_checked()) self.assertFalse(self.course_outline.gating_prerequisites_dropdown_is_visible()) self.assertFalse(self.course_outline.gating_prerequisite_min_score_is_visible()) self._setup_gated_subsection() # Assert settings are displayed correctly for a gated subsection self.course_outline.visit() self.course_outline.open_subsection_settings_dialog(1) self.course_outline.select_advanced_tab(desired_item='gated_content') self.assertTrue(self.course_outline.gating_prerequisite_checkbox_is_visible()) self.assertTrue(self.course_outline.gating_prerequisites_dropdown_is_visible()) self.assertTrue(self.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.courseware_page.visit() self.assertEqual(self.courseware_page.num_subsections, 1) # Fulfill prerequisite and verify that gated subsection is shown self._fulfill_prerequisite() self.courseware_page.visit() self.assertEqual(self.courseware_page.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.courseware_page.visit() staff_page = StaffPage(self.browser, self.course_id) self.assertEqual(staff_page.staff_view_mode, 'Staff') self.assertEqual(self.courseware_page.num_subsections, 2) # Click on gated section and check for banner self.courseware_page.q(css='.chapter-content-container a').nth(1).click() self.courseware_page.wait_for_page() self.assertTrue(self.courseware_page.has_banner()) self.courseware_page.q(css='.chapter-content-container a').nth(0).click() self.courseware_page.wait_for_page() staff_page.set_staff_view_mode('Student') self.assertEqual(self.courseware_page.num_subsections, 1) self.assertFalse(self.courseware_page.has_banner()) staff_page.set_staff_view_mode_specific_student(self.STUDENT_USERNAME) self.assertEqual(self.courseware_page.num_subsections, 2) self.courseware_page.q(css='.chapter-content-container a').nth(1).click() self.courseware_page.wait_for_page() self.assertFalse(self.courseware_page.has_banner())
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])
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()
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])
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" }, "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.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 there 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_home_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_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()
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.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']) 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.course_outline.visit() self.course_outline.open_subsection_settings_dialog(0) self.course_outline.select_advanced_tab(desired_item='gated_content') self.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.course_outline.visit() self.course_outline.open_subsection_settings_dialog(1) self.course_outline.select_advanced_tab(desired_item='gated_content') self.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.course_outline.visit() self.course_outline.open_subsection_settings_dialog(0) self.course_outline.select_advanced_tab(desired_item='gated_content') self.assertTrue( self.course_outline.gating_prerequisite_checkbox_is_visible()) self.assertTrue( self.course_outline.gating_prerequisite_checkbox_is_checked()) self.assertFalse( self.course_outline.gating_prerequisites_dropdown_is_visible()) self.assertFalse( self.course_outline.gating_prerequisite_min_score_is_visible()) self._setup_gated_subsection() # Assert settings are displayed correctly for a gated subsection self.course_outline.visit() self.course_outline.open_subsection_settings_dialog(1) self.course_outline.select_advanced_tab(desired_item='gated_content') self.assertTrue( self.course_outline.gating_prerequisite_checkbox_is_visible()) self.assertTrue( self.course_outline.gating_prerequisites_dropdown_is_visible()) self.assertTrue( self.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.courseware_page.visit() self.assertEqual(self.courseware_page.num_subsections, 1) # Fulfill prerequisite and verify that gated subsection is shown self._fulfill_prerequisite() self.courseware_page.visit() self.assertEqual(self.courseware_page.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.courseware_page.visit() staff_page = StaffPage(self.browser, self.course_id) self.assertEqual(staff_page.staff_view_mode, 'Staff') self.assertEqual(self.courseware_page.num_subsections, 2) # Click on gated section and check for banner self.courseware_page.q( css='.chapter-content-container a').nth(1).click() self.courseware_page.wait_for_page() self.assertTrue(self.courseware_page.has_banner()) self.courseware_page.q( css='.chapter-content-container a').nth(0).click() self.courseware_page.wait_for_page() staff_page.set_staff_view_mode('Student') self.assertEqual(self.courseware_page.num_subsections, 1) self.assertFalse(self.courseware_page.has_banner()) staff_page.set_staff_view_mode_specific_student(self.STUDENT_USERNAME) self.assertEqual(self.courseware_page.num_subsections, 2) self.courseware_page.q( css='.chapter-content-container a').nth(1).click() self.courseware_page.wait_for_page() self.assertFalse(self.courseware_page.has_banner())
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"}, "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.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 there 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_home_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_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()