From 6362d2259c843e0bc6f1c8a1901f2bd2afdd9cdc Mon Sep 17 00:00:00 2001 From: Robert Raposa Date: Wed, 29 Mar 2017 13:41:08 -0400 Subject: [PATCH] Refactor tests for new course outline. --- .../test/acceptance/pages/lms/course_home.py | 53 +++++++++++++++---- .../test/acceptance/pages/lms/courseware.py | 2 + .../test/acceptance/pages/lms/staff_view.py | 41 ++++++++++++-- common/test/acceptance/tests/lms/test_lms.py | 34 +++++++----- .../test_lms_cohorted_courseware_search.py | 4 +- .../tests/lms/test_lms_courseware.py | 4 +- .../acceptance/tests/lms/test_lms_gating.py | 44 ++++++++------- .../tests/lms/test_lms_user_preview.py | 4 +- .../tests/studio/test_import_export.py | 4 +- .../tests/studio/test_studio_container.py | 6 +-- .../tests/studio/test_studio_outline.py | 6 +-- 11 files changed, 140 insertions(+), 62 deletions(-) diff --git a/common/test/acceptance/pages/lms/course_home.py b/common/test/acceptance/pages/lms/course_home.py index 4007b675b7..94701cc85a 100644 --- a/common/test/acceptance/pages/lms/course_home.py +++ b/common/test/acceptance/pages/lms/course_home.py @@ -4,9 +4,10 @@ LMS Course Home page object from bok_choy.page_object import PageObject -from common.test.acceptance.pages.lms.bookmarks import BookmarksPage -from common.test.acceptance.pages.lms.course_page import CoursePage -from common.test.acceptance.pages.lms.courseware import CoursewarePage +from .bookmarks import BookmarksPage +from .course_page import CoursePage +from .courseware import CoursewarePage +from .staff_view import StaffPreviewPage class CourseHomePage(CoursePage): @@ -25,6 +26,7 @@ class CourseHomePage(CoursePage): super(CourseHomePage, self).__init__(browser, course_id) self.course_id = course_id self.outline = CourseOutlinePage(browser, self) + self.preview = StaffPreviewPage(browser, self) # TODO: TNL-6546: Remove the following self.unified_course_view = False @@ -94,6 +96,31 @@ class CourseOutlinePage(PageObject): return outline_dict + @property + def num_sections(self): + """ + Return the number of sections + """ + return len(self.q(css=self.SECTION_TITLES_SELECTOR)) + + @property + def num_subsections(self, section_title=None): + """ + Return the number of subsections. + + Arguments: + section_title: The section for which to return the number of + subsections. If None, default to the first section. + """ + if section_title: + section_index = self._section_title_to_index(section_title) + if not section_index: + return + else: + section_index = 1 + + return len(self.q(css=self.SUBSECTION_TITLES_SELECTOR.format(section_index))) + def go_to_section(self, section_title, subsection_title): """ Go to the section in the courseware. @@ -103,15 +130,10 @@ class CourseOutlinePage(PageObject): 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)) + section_index = self._section_title_to_index(section_title) + if section_index is None: return - # Get the subsection by index try: subsection_index = self._subsection_titles(section_index + 1).index(subsection_title) except ValueError: @@ -127,6 +149,17 @@ class CourseOutlinePage(PageObject): self._wait_for_course_section(section_title, subsection_title) + def _section_title_to_index(self, section_title): + """ + Get the section title index given the section title. + """ + try: + section_index = self._section_titles().index(section_title) + except ValueError: + self.warning("Could not find section '{0}'".format(section_title)) + + return section_index + def resume_course_from_outline(self): """ Navigate to courseware using Resume Course button in the header. diff --git a/common/test/acceptance/pages/lms/courseware.py b/common/test/acceptance/pages/lms/courseware.py index bec5c14c5c..a8f43f9017 100644 --- a/common/test/acceptance/pages/lms/courseware.py +++ b/common/test/acceptance/pages/lms/courseware.py @@ -18,6 +18,8 @@ class CoursewarePage(CoursePage): url_path = "courseware/" xblock_component_selector = '.vert .xblock' + + # TODO: TNL-6546: Remove sidebar selectors section_selector = '.chapter' subsection_selector = '.chapter-content-container a' diff --git a/common/test/acceptance/pages/lms/staff_view.py b/common/test/acceptance/pages/lms/staff_view.py index 507b3893d9..331d11808e 100644 --- a/common/test/acceptance/pages/lms/staff_view.py +++ b/common/test/acceptance/pages/lms/staff_view.py @@ -1,21 +1,35 @@ """ -Staff view of courseware +Staff views of various tabs (e.g. courseware, course home) """ from bok_choy.page_object import PageObject from common.test.acceptance.pages.lms.courseware import CoursewarePage -class StaffPage(CoursewarePage): +class StaffPreviewPage(PageObject): """ - View of courseware pages while logged in as course staff + Handles Staff Preview for any course tab that provides that functionality. """ - url = None + PREVIEW_MENU_CSS = '.preview-menu' VIEW_MODE_OPTIONS_CSS = '.preview-menu .action-preview-select option' + def __init__(self, browser, parent_page=None): + """ + Initialize the staff preview page. + + This page can either be used as a subclass, or a child of a parent page. + + Arguments: + browser: The selenium browser. + parent_page: None if this is being used as a subclass. Otherwise, + the parent_page the contains this staff preview page fragment. + """ + super(StaffPreviewPage, self).__init__(browser) + self.parent_page = parent_page + def is_browser_on_page(self): - if not super(StaffPage, self).is_browser_on_page(): + if self.parent_page and not self.parent_page.is_browser_on_page: return False return self.q(css=self.PREVIEW_MENU_CSS).present @@ -46,6 +60,23 @@ class StaffPage(CoursewarePage): ) self.wait_for_ajax() + +class StaffCoursewarePage(CoursewarePage, StaffPreviewPage): + """ + View of courseware pages while logged in as course staff + """ + + url = None + + def __init__(self, browser, course_id): + CoursewarePage.__init__(self, browser, course_id) + StaffPreviewPage.__init__(self, browser) + + def is_browser_on_page(self): + if not CoursewarePage.is_browser_on_page(self): + return False + return StaffPreviewPage.is_browser_on_page(self) + def open_staff_debug_info(self): """ Open the staff debug window diff --git a/common/test/acceptance/tests/lms/test_lms.py b/common/test/acceptance/tests/lms/test_lms.py index 45a7af9715..abe8cdb294 100644 --- a/common/test/acceptance/tests/lms/test_lms.py +++ b/common/test/acceptance/tests/lms/test_lms.py @@ -957,6 +957,7 @@ class VisibleToStaffOnlyTest(UniqueCourseTest): ) ).install() + self.course_home_page = CourseHomePage(self.browser, self.course_id) self.courseware_page = CoursewarePage(self.browser, self.course_id) def test_visible_to_staff(self): @@ -969,16 +970,21 @@ class VisibleToStaffOnlyTest(UniqueCourseTest): AutoAuthPage(self.browser, username="STAFF_TESTER", email="johndoe_staff@example.com", course_id=self.course_id, staff=True).visit() - self.courseware_page.visit() - self.assertEqual(3, len(self.courseware_page.nav.sections['Test Section'])) + self.course_home_page.visit() + self.assertEqual(3, len(self.course_home_page.outline.sections['Test Section'])) - self.courseware_page.nav.go_to_section("Test Section", "Subsection With Locked Unit") + self.course_home_page.outline.go_to_section("Test Section", "Subsection With Locked Unit") + self.courseware_page.wait_for_page() self.assertEqual([u'Locked Unit', u'Unlocked Unit'], self.courseware_page.nav.sequence_items) - self.courseware_page.nav.go_to_section("Test Section", "Unlocked Subsection") + self.course_home_page.visit() + self.course_home_page.outline.go_to_section("Test Section", "Unlocked Subsection") + self.courseware_page.wait_for_page() self.assertEqual([u'Test Unit'], self.courseware_page.nav.sequence_items) - self.courseware_page.nav.go_to_section("Test Section", "Locked Subsection") + self.course_home_page.visit() + self.course_home_page.outline.go_to_section("Test Section", "Locked Subsection") + self.courseware_page.wait_for_page() self.assertEqual([u'Test Unit'], self.courseware_page.nav.sequence_items) def test_visible_to_student(self): @@ -991,13 +997,16 @@ class VisibleToStaffOnlyTest(UniqueCourseTest): AutoAuthPage(self.browser, username="STUDENT_TESTER", email="johndoe_student@example.com", course_id=self.course_id, staff=False).visit() - self.courseware_page.visit() - self.assertEqual(2, len(self.courseware_page.nav.sections['Test Section'])) + self.course_home_page.visit() + self.assertEqual(2, len(self.course_home_page.outline.sections['Test Section'])) - self.courseware_page.nav.go_to_section("Test Section", "Subsection With Locked Unit") + 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.courseware_page.nav.go_to_section("Test Section", "Unlocked Subsection") + 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) @@ -1142,8 +1151,7 @@ class ProblemExecutionTest(UniqueCourseTest): """ super(ProblemExecutionTest, self).setUp() - self.course_info_page = CourseInfoPage(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) # Install a course with sections and problems. @@ -1188,8 +1196,8 @@ class ProblemExecutionTest(UniqueCourseTest): def test_python_execution_in_problem(self): # Navigate to the problem page - self.courseware_page.visit() - self.courseware_page.nav.go_to_section('Test Section', 'Test Subsection') + self.course_home_page.visit() + self.course_home_page.outline.go_to_section('Test Section', 'Test Subsection') problem_page = ProblemPage(self.browser) self.assertEqual(problem_page.problem_name.upper(), 'PYTHON PROBLEM') diff --git a/common/test/acceptance/tests/lms/test_lms_cohorted_courseware_search.py b/common/test/acceptance/tests/lms/test_lms_cohorted_courseware_search.py index 59443fdae2..2558e38660 100644 --- a/common/test/acceptance/tests/lms/test_lms_cohorted_courseware_search.py +++ b/common/test/acceptance/tests/lms/test_lms_cohorted_courseware_search.py @@ -9,7 +9,7 @@ from common.test.acceptance.tests.helpers import remove_file from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage -from common.test.acceptance.pages.lms.staff_view import StaffPage +from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage from common.test.acceptance.fixtures.course import XBlockFixtureDesc from nose.plugins.attrib import attr @@ -110,7 +110,7 @@ class CoursewareSearchCohortTest(ContainerBase): Open staff page with assertion """ self.courseware_search_page.visit() - staff_page = StaffPage(self.browser, self.course_id) + staff_page = StaffCoursewarePage(self.browser, self.course_id) self.assertEqual(staff_page.staff_view_mode, 'Staff') return staff_page diff --git a/common/test/acceptance/tests/lms/test_lms_courseware.py b/common/test/acceptance/tests/lms/test_lms_courseware.py index e5b2e4b52b..244f40f0c9 100644 --- a/common/test/acceptance/tests/lms/test_lms_courseware.py +++ b/common/test/acceptance/tests/lms/test_lms_courseware.py @@ -20,7 +20,7 @@ from ...pages.lms.dashboard import DashboardPage from ...pages.lms.pay_and_verify import PaymentAndVerificationFlow, FakePaymentPage, FakeSoftwareSecureVerificationPage from ...pages.lms.problem import ProblemPage from ...pages.lms.progress import ProgressPage -from ...pages.lms.staff_view import StaffPage +from ...pages.lms.staff_view import StaffCoursewarePage from ...pages.lms.track_selection import TrackSelectionPage from ...pages.studio.auto_auth import AutoAuthPage from ...pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage @@ -333,7 +333,7 @@ class ProctoredExamTest(UniqueCourseTest): LogoutPage(self.browser).visit() auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id) self.courseware_page.visit() - staff_page = StaffPage(self.browser, self.course_id) + staff_page = StaffCoursewarePage(self.browser, self.course_id) self.assertEqual(staff_page.staff_view_mode, 'Staff') staff_page.set_staff_view_mode_specific_student(self.USERNAME) diff --git a/common/test/acceptance/tests/lms/test_lms_gating.py b/common/test/acceptance/tests/lms/test_lms_gating.py index 7ace5bff91..a3cccb1cf5 100644 --- a/common/test/acceptance/tests/lms/test_lms_gating.py +++ b/common/test/acceptance/tests/lms/test_lms_gating.py @@ -7,9 +7,9 @@ from textwrap import dedent from common.test.acceptance.tests.helpers import UniqueCourseTest from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage +from common.test.acceptance.pages.lms.course_home import CourseHomePage from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.problem import ProblemPage -from common.test.acceptance.pages.lms.staff_view import StaffPage from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc @@ -28,6 +28,7 @@ class GatingTest(UniqueCourseTest): 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, @@ -158,13 +159,14 @@ class GatingTest(UniqueCourseTest): self._auto_auth(self.STUDENT_USERNAME, self.STUDENT_EMAIL, False) - self.courseware_page.visit() - self.assertEqual(self.courseware_page.num_subsections, 1) + 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._fulfill_prerequisite() self.courseware_page.visit() - self.assertEqual(self.courseware_page.num_subsections, 2) + 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): """ @@ -187,27 +189,29 @@ class GatingTest(UniqueCourseTest): 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) + 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.courseware_page.q(css='.chapter-content-container a').nth(1).click() + 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.courseware_page.q(css='.chapter-content-container a').nth(0).click() + 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() - 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.course_home_page.visit() + self.course_home_page.preview.set_staff_view_mode('Student') + 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()) diff --git a/common/test/acceptance/tests/lms/test_lms_user_preview.py b/common/test/acceptance/tests/lms/test_lms_user_preview.py index 601ed82cfe..b9f4fe3e61 100644 --- a/common/test/acceptance/tests/lms/test_lms_user_preview.py +++ b/common/test/acceptance/tests/lms/test_lms_user_preview.py @@ -10,7 +10,7 @@ from common.test.acceptance.tests.helpers import UniqueCourseTest, create_user_p from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage -from common.test.acceptance.pages.lms.staff_view import StaffPage +from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from bok_choy.promise import EmptyPromise from xmodule.partitions.partitions import Group @@ -50,7 +50,7 @@ class StaffViewTest(UniqueCourseTest): Open staff page with assertion """ self.courseware_page.visit() - staff_page = StaffPage(self.browser, self.course_id) + staff_page = StaffCoursewarePage(self.browser, self.course_id) self.assertEqual(staff_page.staff_view_mode, 'Staff') return staff_page diff --git a/common/test/acceptance/tests/studio/test_import_export.py b/common/test/acceptance/tests/studio/test_import_export.py index ef63356fa5..179c90bdda 100644 --- a/common/test/acceptance/tests/studio/test_import_export.py +++ b/common/test/acceptance/tests/studio/test_import_export.py @@ -15,7 +15,7 @@ from common.test.acceptance.pages.studio.import_export import ( from common.test.acceptance.pages.studio.library import LibraryEditPage from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.lms.courseware import CoursewarePage -from common.test.acceptance.pages.lms.staff_view import StaffPage +from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage class ExportTestMixin(object): @@ -302,7 +302,7 @@ class TestEntranceExamCourseImport(ImportTestMixin, StudioCourseTest): 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') + StaffCoursewarePage(self.browser, self.course_id).set_staff_view_mode('Student') self.assertEqual(courseware.num_sections, 1) self.assertIn( "To access course materials, you must score", courseware.entrance_exam_message_selector.text[0] diff --git a/common/test/acceptance/tests/studio/test_studio_container.py b/common/test/acceptance/tests/studio/test_studio_container.py index eb74e9854e..26423e2b1a 100644 --- a/common/test/acceptance/tests/studio/test_studio_container.py +++ b/common/test/acceptance/tests/studio/test_studio_container.py @@ -13,7 +13,7 @@ from common.test.acceptance.pages.studio.html_component_editor import HtmlCompon from common.test.acceptance.pages.studio.move_xblock import MoveModalView from common.test.acceptance.pages.studio.utils import add_discussion, drag from common.test.acceptance.pages.lms.courseware import CoursewarePage -from common.test.acceptance.pages.lms.staff_view import StaffPage +from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage from common.test.acceptance.tests.helpers import create_user_partition_json import datetime @@ -972,9 +972,9 @@ class UnitPublishingTest(ContainerBase): def _verify_and_return_staff_page(self): """ - Verifies that the browser is on the staff page and returns a StaffPage. + Verifies that the browser is on the staff page and returns a StaffCoursewarePage. """ - page = StaffPage(self.browser, self.course_id) + page = StaffCoursewarePage(self.browser, self.course_id) page.wait_for_page() return page diff --git a/common/test/acceptance/tests/studio/test_studio_outline.py b/common/test/acceptance/tests/studio/test_studio_outline.py index 79cf8449f0..4e49bb0053 100644 --- a/common/test/acceptance/tests/studio/test_studio_outline.py +++ b/common/test/acceptance/tests/studio/test_studio_outline.py @@ -14,7 +14,7 @@ from common.test.acceptance.pages.studio.overview import CourseOutlinePage, Cont from common.test.acceptance.pages.studio.utils import add_discussion, drag, verify_ordering from common.test.acceptance.pages.lms.course_home import CourseHomePage from common.test.acceptance.pages.lms.courseware import CoursewarePage -from common.test.acceptance.pages.lms.staff_view import StaffPage +from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage from common.test.acceptance.fixtures.config import ConfigModelFixture from common.test.acceptance.fixtures.course import XBlockFixtureDesc @@ -741,7 +741,7 @@ class StaffLockTest(CourseOutlineTest): courseware = CoursewarePage(self.browser, self.course_id) courseware.wait_for_page() self.assertEqual(courseware.num_sections, 2) - StaffPage(self.browser, self.course_id).set_staff_view_mode('Student') + StaffCoursewarePage(self.browser, self.course_id).set_staff_view_mode('Student') self.assertEqual(courseware.num_sections, 1) def test_locked_subsections_do_not_appear_in_lms(self): @@ -760,7 +760,7 @@ class StaffLockTest(CourseOutlineTest): courseware = CoursewarePage(self.browser, self.course_id) courseware.wait_for_page() self.assertEqual(courseware.num_subsections, 2) - StaffPage(self.browser, self.course_id).set_staff_view_mode('Student') + StaffCoursewarePage(self.browser, self.course_id).set_staff_view_mode('Student') self.assertEqual(courseware.num_subsections, 1) def test_toggling_staff_lock_on_section_does_not_publish_draft_units(self):