Commit 652ad7ae by Robert Raposa Committed by Diana Huang

Add course outline bokchoy tests.

- Rename CourseOutlinePage to StudioCourseOutlinePage in lms tests.
- Introduce CourseHomePage with outline child.
- Add a11y, breadcrumbs, and waffle.
parent 574d0703
...@@ -227,9 +227,9 @@ class CourseFixture(XBlockContainerFixture): ...@@ -227,9 +227,9 @@ class CourseFixture(XBlockContainerFixture):
self._configure_course() self._configure_course()
@property @property
def course_outline(self): def studio_course_outline_as_json(self):
""" """
Retrieves course outline in JSON format. Retrieves Studio course outline in JSON format.
""" """
url = STUDIO_BASE_URL + '/course/' + self._course_key + "?format=json" url = STUDIO_BASE_URL + '/course/' + self._course_key + "?format=json"
response = self.session.get(url, headers=self.headers) response = self.session.get(url, headers=self.headers)
......
"""
LMS Course Home page object
"""
from bok_choy.page_object import PageObject
from common.test.acceptance.pages.lms.course_page import CoursePage
from common.test.acceptance.pages.lms.courseware import CoursewarePage
class CourseHomePage(CoursePage):
"""
Course home page, including course outline.
"""
url_path = "course/"
def is_browser_on_page(self):
return self.q(css='.course-outline').present
def __init__(self, browser, course_id):
super(CourseHomePage, self).__init__(browser, course_id)
self.course_id = course_id
self.outline = CourseOutlinePage(browser, self)
# TODO: TNL-6546: Remove the following
self.unified_course_view = False
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)
)
"""
Course navigation page object
"""
import re
from bok_choy.page_object import PageObject, unguarded
from bok_choy.promise import EmptyPromise
class CourseNavPage(PageObject):
"""
Navigate sections and sequences in the courseware.
"""
url = None
def is_browser_on_page(self):
return self.q(css='div.course-index').present
@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
nav_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)
nav_dict[sec_title] = self._subsection_titles(sec_index + 1)
return nav_dict
@property
def sequence_items(self):
"""
Return a list of sequence items on the page.
Sequence items are one level below subsections in the course nav.
Example return value:
['Chemical Bonds Video', 'Practice Problems', 'Homework']
"""
seq_css = 'ol#sequence-list>li>.nav-item>.sequence-tooltip'
return self.q(css=seq_css).map(self._clean_seq_titles).results
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")
"""
# For test stability, disable JQuery animations (opening / closing menus)
self.browser.execute_script("jQuery.fx.off = true;")
# Get the section by index
try:
sec_index = self._section_titles().index(section_title)
except ValueError:
self.warning("Could not find section '{0}'".format(section_title))
return
# Click the section to ensure it's open (no harm in clicking twice if it's already open)
# Add one to convert from list index to CSS index
section_css = '.course-navigation .chapter:nth-of-type({0})'.format(sec_index + 1)
self.q(css=section_css).first.click()
# Get the subsection by index
try:
subsec_index = self._subsection_titles(sec_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 = (
".course-navigation .chapter-content-container:nth-of-type({0}) "
".menu-item:nth-of-type({1})"
).format(sec_index + 1, subsec_index + 1)
# Click the subsection and ensure that the page finishes reloading
self.q(css=subsection_css).first.click()
self._on_section_promise(section_title, subsection_title).fulfill()
def go_to_vertical(self, vertical_title):
"""
Within a section/subsection, navigate to the vertical with `vertical_title`.
"""
# Get the index of the item in the sequence
all_items = self.sequence_items
try:
seq_index = all_items.index(vertical_title)
except ValueError:
msg = "Could not find sequential '{0}'. Available sequentials: [{1}]".format(
vertical_title, ", ".join(all_items)
)
self.warning(msg)
else:
# Click on the sequence item at the correct index
# Convert the list index (starts at 0) to a CSS index (starts at 1)
seq_css = "ol#sequence-list>li:nth-of-type({0})>.nav-item".format(seq_index + 1)
self.q(css=seq_css).first.click()
# Click triggers an ajax event
self.wait_for_ajax()
def _section_titles(self):
"""
Return a list of all section titles on the page.
"""
chapter_css = '.course-navigation .chapter .group-heading'
return self.q(css=chapter_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 = (
".course-navigation .chapter-content-container:nth-of-type({0}) "
".menu-item a p:nth-of-type(1)"
).format(section_index)
# If the element is visible, we can get its text directly
# Otherwise, we need to get the HTML
# It *would* make sense to always get the HTML, but unfortunately
# the open tab has some child <span> tags that we don't want.
return self.q(
css=subsection_css
).map(
lambda el: el.text.strip().split('\n')[0] if el.is_displayed() else el.get_attribute('innerHTML').strip()
).results
def _on_section_promise(self, section_title, subsection_title):
"""
Return a `Promise` that is fulfilled when the user is on
the correct section and subsection.
"""
desc = "currently at section '{0}' and subsection '{1}'".format(section_title, subsection_title)
return EmptyPromise(
lambda: self.is_on_section(section_title, subsection_title), desc
)
@unguarded
def is_on_section(self, section_title, subsection_title):
"""
Return a boolean indicating whether the user is on the section and subsection
with the specified titles.
This assumes that the currently expanded section is the one we're on
That's true right after we click the section/subsection, but not true in general
(the user could go to a section, then expand another tab).
"""
current_section_list = self.q(css='.course-navigation .chapter.is-open .group-heading').text
current_subsection_list = self.q(css='.course-navigation .chapter-content-container .menu-item.active a p').text
if len(current_section_list) == 0:
self.warning("Could not find the current section")
return False
elif len(current_subsection_list) == 0:
self.warning("Could not find current subsection")
return False
else:
return (
current_section_list[0].strip() == section_title and
current_subsection_list[0].strip().split('\n')[0] == subsection_title
)
# Regular expression to remove HTML span tags from a string
REMOVE_SPAN_TAG_RE = re.compile(r'</span>(.+)<span')
def _clean_seq_titles(self, element):
"""
Clean HTML of sequence titles, stripping out span tags and returning the first line.
"""
return self.REMOVE_SPAN_TAG_RE.search(element.get_attribute('innerHTML')).groups()[0].strip()
@property
def active_subsection_url(self):
"""
return the url of the active subsection in the left nav
"""
return self.q(css='.chapter-content-container .menu-item.active a').attrs('href')[0]
...@@ -8,9 +8,9 @@ import requests ...@@ -8,9 +8,9 @@ import requests
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage as StudioAutoAuthPage from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage as StudioAutoAuthPage
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage as LmsAutoAuthPage from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage as LmsAutoAuthPage
from common.test.acceptance.pages.lms.bookmarks import BookmarksPage from common.test.acceptance.pages.lms.bookmarks import BookmarksPage
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.courseware import CoursewarePage
from common.test.acceptance.pages.lms.course_nav import CourseNavPage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.common import BASE_URL from common.test.acceptance.pages.common import BASE_URL
...@@ -72,7 +72,7 @@ class BookmarksTest(BookmarksTestMixin): ...@@ -72,7 +72,7 @@ class BookmarksTest(BookmarksTestMixin):
""" """
super(BookmarksTest, self).setUp() super(BookmarksTest, self).setUp()
self.course_outline_page = CourseOutlinePage( self.studio_course_outline_page = StudioCourseOutlinePage(
self.browser, self.browser,
self.course_info['org'], self.course_info['org'],
self.course_info['number'], self.course_info['number'],
...@@ -80,8 +80,8 @@ class BookmarksTest(BookmarksTestMixin): ...@@ -80,8 +80,8 @@ class BookmarksTest(BookmarksTestMixin):
) )
self.courseware_page = CoursewarePage(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.bookmarks_page = BookmarksPage(self.browser, self.course_id) self.bookmarks_page = BookmarksPage(self.browser, self.course_id)
self.course_nav = CourseNavPage(self.browser)
# Get session to be used for bookmarking units # Get session to be used for bookmarking units
self.session = requests.Session() self.session = requests.Session()
...@@ -166,10 +166,10 @@ class BookmarksTest(BookmarksTestMixin): ...@@ -166,10 +166,10 @@ class BookmarksTest(BookmarksTestMixin):
).visit() ).visit()
# Visit course outline page in studio. # Visit course outline page in studio.
self.course_outline_page.visit() self.studio_course_outline_page.visit()
self.course_outline_page.wait_for_page() self.studio_course_outline_page.wait_for_page()
self.course_outline_page.section_at(index).delete() self.studio_course_outline_page.section_at(index).delete()
# Logout and login as a student. # Logout and login as a student.
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
...@@ -232,11 +232,11 @@ class BookmarksTest(BookmarksTestMixin): ...@@ -232,11 +232,11 @@ class BookmarksTest(BookmarksTestMixin):
""" """
Update and publish the block/unit display name. Update and publish the block/unit display name.
""" """
self.course_outline_page.visit() self.studio_course_outline_page.visit()
self.course_outline_page.wait_for_page() self.studio_course_outline_page.wait_for_page()
self.course_outline_page.expand_all_subsections() self.studio_course_outline_page.expand_all_subsections()
section = self.course_outline_page.section_at(0) section = self.studio_course_outline_page.section_at(0)
container_page = section.subsection_at(0).unit_at(0).go_to() container_page = section.subsection_at(0).unit_at(0).go_to()
self.course_fixture._update_xblock(container_page.locator, { # pylint: disable=protected-access self.course_fixture._update_xblock(container_page.locator, { # pylint: disable=protected-access
...@@ -267,7 +267,8 @@ class BookmarksTest(BookmarksTestMixin): ...@@ -267,7 +267,8 @@ class BookmarksTest(BookmarksTestMixin):
""" """
self._test_setup() self._test_setup()
for index in range(2): for index in range(2):
self.course_nav.go_to_section('TestSection{}'.format(index), 'TestSubsection{}'.format(index)) self.course_home_page.visit()
self.course_home_page.outline.go_to_section('TestSection{}'.format(index), 'TestSubsection{}'.format(index))
self._toggle_bookmark_and_verify(True, 'bookmarked', 1) self._toggle_bookmark_and_verify(True, 'bookmarked', 1)
self.bookmarks_page.click_bookmarks_button(False) self.bookmarks_page.click_bookmarks_button(False)
......
...@@ -7,10 +7,11 @@ from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureD ...@@ -7,10 +7,11 @@ from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureD
from common.test.acceptance.fixtures.certificates import CertificateConfigFixture from common.test.acceptance.fixtures.certificates import CertificateConfigFixture
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.certificate_page import CertificatePage from common.test.acceptance.pages.lms.certificate_page import CertificatePage
from common.test.acceptance.pages.lms.course_home import CourseHomePage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage from common.test.acceptance.pages.lms.course_info import CourseInfoPage
from common.test.acceptance.pages.lms.tab_nav import TabNavPage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.course_nav import CourseNavPage
from common.test.acceptance.pages.lms.progress import ProgressPage from common.test.acceptance.pages.lms.progress import ProgressPage
from common.test.acceptance.pages.lms.tab_nav import TabNavPage
@attr(shard=5) @attr(shard=5)
...@@ -154,7 +155,8 @@ class CertificateProgressPageTest(UniqueCourseTest): ...@@ -154,7 +155,8 @@ class CertificateProgressPageTest(UniqueCourseTest):
self.course_info_page = CourseInfoPage(self.browser, self.course_id) self.course_info_page = CourseInfoPage(self.browser, self.course_id)
self.progress_page = ProgressPage(self.browser, self.course_id) self.progress_page = ProgressPage(self.browser, self.course_id)
self.course_nav = CourseNavPage(self.browser) 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) self.tab_nav = TabNavPage(self.browser)
def log_in_as_unique_user(self): def log_in_as_unique_user(self):
...@@ -205,38 +207,42 @@ class CertificateProgressPageTest(UniqueCourseTest): ...@@ -205,38 +207,42 @@ class CertificateProgressPageTest(UniqueCourseTest):
Problems were added in the setUp Problems were added in the setUp
""" """
self.course_info_page.visit() # self.course_info_page.visit()
self.tab_nav.go_to_tab('Course') # 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 # Navigate to Test Subsection in Test Section Section
self.course_nav.go_to_section('Test Section', 'Test Subsection') self.course_home_page.outline.go_to_section('Test Section', 'Test Subsection')
# Navigate to Test Problem 1 # Navigate to Test Problem 1
self.course_nav.go_to_vertical('Test Problem 1') self.courseware_page.nav.go_to_vertical('Test Problem 1')
# Select correct value for from select menu # Select correct value for from select menu
self.course_nav.q(css='select option[value="{}"]'.format('blue')).first.click() self.courseware_page.q(css='select option[value="{}"]'.format('blue')).first.click()
# Select correct radio button for the answer # Select correct radio button for the answer
self.course_nav.q(css='fieldset div.field:nth-child(4) input').nth(0).click() self.courseware_page.q(css='fieldset div.field:nth-child(4) input').nth(0).click()
# Select correct radio buttons for the answer # Select correct radio buttons for the answer
self.course_nav.q(css='fieldset div.field:nth-child(2) input').nth(1).click() self.courseware_page.q(css='fieldset div.field:nth-child(2) input').nth(1).click()
self.course_nav.q(css='fieldset div.field:nth-child(4) input').nth(1).click() self.courseware_page.q(css='fieldset div.field:nth-child(4) input').nth(1).click()
# Submit the answer # Submit the answer
self.course_nav.q(css='button.submit').click() self.courseware_page.q(css='button.submit').click()
self.course_nav.wait_for_ajax() self.courseware_page.wait_for_ajax()
# Navigate to the 'Test Subsection 2' of 'Test Section 2' # Navigate to the 'Test Subsection 2' of 'Test Section 2'
self.course_nav.go_to_section('Test Section 2', 'Test Subsection 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 # Navigate to Test Problem 2
self.course_nav.go_to_vertical('Test Problem 2') self.courseware_page.nav.go_to_vertical('Test Problem 2')
# Fill in the answer of the problem # Fill in the answer of the problem
self.course_nav.q(css='input[id^=input_][id$=_2_1]').fill('A*x^2 + sqrt(y)') self.courseware_page.q(css='input[id^=input_][id$=_2_1]').fill('A*x^2 + sqrt(y)')
# Submit the answer # Submit the answer
self.course_nav.q(css='button.submit').click() self.courseware_page.q(css='button.submit').click()
self.course_nav.wait_for_ajax() self.courseware_page.wait_for_ajax()
...@@ -8,7 +8,7 @@ import textwrap ...@@ -8,7 +8,7 @@ import textwrap
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from common.test.acceptance.tests.helpers import UniqueCourseTest, TestWithSearchIndexMixin from common.test.acceptance.tests.helpers import UniqueCourseTest, TestWithSearchIndexMixin
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.studio.library import StudioLibraryContentEditor, StudioLibraryContainerXBlockWrapper from common.test.acceptance.pages.studio.library import StudioLibraryContentEditor, StudioLibraryContainerXBlockWrapper
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.library import LibraryContentXBlockWrapper from common.test.acceptance.pages.lms.library import LibraryContentXBlockWrapper
...@@ -44,7 +44,7 @@ class LibraryContentTestBase(UniqueCourseTest): ...@@ -44,7 +44,7 @@ class LibraryContentTestBase(UniqueCourseTest):
self.courseware_page = CoursewarePage(self.browser, self.course_id) self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.course_outline = CourseOutlinePage( self.studio_course_outline = StudioCourseOutlinePage(
self.browser, self.browser,
self.course_info['org'], self.course_info['org'],
self.course_info['number'], self.course_info['number'],
...@@ -116,9 +116,9 @@ class LibraryContentTestBase(UniqueCourseTest): ...@@ -116,9 +116,9 @@ class LibraryContentTestBase(UniqueCourseTest):
if change_login: if change_login:
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
self.course_outline.visit() self.studio_course_outline.visit()
subsection = self.course_outline.section(SECTION_NAME).subsection(SUBSECTION_NAME) subsection = self.studio_course_outline.section(SECTION_NAME).subsection(SUBSECTION_NAME)
return subsection.expand_subsection().unit(UNIT_NAME).go_to() return subsection.expand_subsection().unit(UNIT_NAME).go_to()
def _goto_library_block_page(self, block_id=None): def _goto_library_block_page(self, block_id=None):
......
...@@ -7,7 +7,7 @@ import uuid ...@@ -7,7 +7,7 @@ import uuid
from common.test.acceptance.tests.helpers import remove_file from common.test.acceptance.tests.helpers import remove_file
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage 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.courseware_search import CoursewareSearchPage
from common.test.acceptance.pages.lms.staff_view import StaffPage from common.test.acceptance.pages.lms.staff_view import StaffPage
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
...@@ -45,7 +45,7 @@ class CoursewareSearchCohortTest(ContainerBase): ...@@ -45,7 +45,7 @@ class CoursewareSearchCohortTest(ContainerBase):
super(CoursewareSearchCohortTest, self).setUp(is_staff=is_staff) super(CoursewareSearchCohortTest, self).setUp(is_staff=is_staff)
self.staff_user = self.user self.staff_user = self.user
self.course_outline = CourseOutlinePage( self.studio_course_outline = StudioCourseOutlinePage(
self.browser, self.browser,
self.course_info['org'], self.course_info['org'],
self.course_info['number'], self.course_info['number'],
...@@ -101,9 +101,9 @@ class CoursewareSearchCohortTest(ContainerBase): ...@@ -101,9 +101,9 @@ class CoursewareSearchCohortTest(ContainerBase):
Reindex course content on studio course page Reindex course content on studio course page
""" """
self._auto_auth(self.staff_user["username"], self.staff_user["email"], True) self._auto_auth(self.staff_user["username"], self.staff_user["email"], True)
self.course_outline.visit() self.studio_course_outline.visit()
self.course_outline.start_reindex() self.studio_course_outline.start_reindex()
self.course_outline.wait_for_ajax() self.studio_course_outline.wait_for_ajax()
def _goto_staff_page(self): def _goto_staff_page(self):
""" """
......
...@@ -11,7 +11,7 @@ from common.test.acceptance.pages.common.logout import LogoutPage ...@@ -11,7 +11,7 @@ from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.common.utils import click_css from common.test.acceptance.pages.common.utils import click_css
from common.test.acceptance.pages.studio.utils import add_html_component, type_in_codemirror from common.test.acceptance.pages.studio.utils import add_html_component, type_in_codemirror
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.studio.container import ContainerPage from common.test.acceptance.pages.studio.container import ContainerPage
from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
...@@ -54,7 +54,7 @@ class CoursewareSearchTest(UniqueCourseTest): ...@@ -54,7 +54,7 @@ class CoursewareSearchTest(UniqueCourseTest):
super(CoursewareSearchTest, self).setUp() super(CoursewareSearchTest, self).setUp()
self.courseware_search_page = CoursewareSearchPage(self.browser, self.course_id) self.courseware_search_page = CoursewareSearchPage(self.browser, self.course_id)
self.course_outline = CourseOutlinePage( self.studio_course_outline = StudioCourseOutlinePage(
self.browser, self.browser,
self.course_info['org'], self.course_info['org'],
self.course_info['number'], self.course_info['number'],
...@@ -91,8 +91,8 @@ class CoursewareSearchTest(UniqueCourseTest): ...@@ -91,8 +91,8 @@ class CoursewareSearchTest(UniqueCourseTest):
Publish content on studio course page under specified section Publish content on studio course page under specified section
""" """
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
self.course_outline.visit() self.studio_course_outline.visit()
subsection = self.course_outline.section_at(section_index).subsection_at(0) subsection = self.studio_course_outline.section_at(section_index).subsection_at(0)
subsection.expand_subsection() subsection.expand_subsection()
unit = subsection.unit_at(0) unit = subsection.unit_at(0)
unit.publish() unit.publish()
...@@ -102,8 +102,8 @@ class CoursewareSearchTest(UniqueCourseTest): ...@@ -102,8 +102,8 @@ class CoursewareSearchTest(UniqueCourseTest):
Edit chapter name on studio course page under specified section Edit chapter name on studio course page under specified section
""" """
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
self.course_outline.visit() self.studio_course_outline.visit()
section = self.course_outline.section_at(section_index) section = self.studio_course_outline.section_at(section_index)
section.change_name(self.EDITED_CHAPTER_NAME) section.change_name(self.EDITED_CHAPTER_NAME)
def _studio_add_content(self, section_index): def _studio_add_content(self, section_index):
...@@ -113,8 +113,8 @@ class CoursewareSearchTest(UniqueCourseTest): ...@@ -113,8 +113,8 @@ class CoursewareSearchTest(UniqueCourseTest):
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
# create a unit in course outline # create a unit in course outline
self.course_outline.visit() self.studio_course_outline.visit()
subsection = self.course_outline.section_at(section_index).subsection_at(0) subsection = self.studio_course_outline.section_at(section_index).subsection_at(0)
subsection.expand_subsection() subsection.expand_subsection()
subsection.add_unit() subsection.add_unit()
...@@ -134,9 +134,9 @@ class CoursewareSearchTest(UniqueCourseTest): ...@@ -134,9 +134,9 @@ class CoursewareSearchTest(UniqueCourseTest):
""" """
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
self.course_outline.visit() self.studio_course_outline.visit()
self.course_outline.start_reindex() self.studio_course_outline.start_reindex()
self.course_outline.wait_for_ajax() self.studio_course_outline.wait_for_ajax()
def _search_for_content(self, search_term): def _search_for_content(self, search_term):
""" """
......
...@@ -9,7 +9,7 @@ from common.test.acceptance.pages.common.logout import LogoutPage ...@@ -9,7 +9,7 @@ from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.common.utils import click_css from common.test.acceptance.pages.common.utils import click_css
from common.test.acceptance.pages.studio.utils import add_html_component, type_in_codemirror from common.test.acceptance.pages.studio.utils import add_html_component, type_in_codemirror
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.studio.container import ContainerPage from common.test.acceptance.pages.studio.container import ContainerPage
from common.test.acceptance.pages.lms.dashboard_search import DashboardSearchPage from common.test.acceptance.pages.lms.dashboard_search import DashboardSearchPage
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
...@@ -60,10 +60,10 @@ class DashboardSearchTest(AcceptanceTest): ...@@ -60,10 +60,10 @@ class DashboardSearchTest(AcceptanceTest):
} }
# generate course fixtures and outline pages # generate course fixtures and outline pages
self.course_outlines = {} self.studio_course_outlines = {}
self.course_fixtures = {} self.course_fixtures = {}
for key, course_info in self.courses.iteritems(): for key, course_info in self.courses.iteritems():
course_outline = CourseOutlinePage( studio_course_outline = StudioCourseOutlinePage(
self.browser, self.browser,
course_info['org'], course_info['org'],
course_info['number'], course_info['number'],
...@@ -89,7 +89,7 @@ class DashboardSearchTest(AcceptanceTest): ...@@ -89,7 +89,7 @@ class DashboardSearchTest(AcceptanceTest):
) )
).install() ).install()
self.course_outlines[key] = course_outline self.studio_course_outlines[key] = studio_course_outline
self.course_fixtures[key] = course_fix self.course_fixtures[key] = course_fix
def tearDown(self): def tearDown(self):
...@@ -106,13 +106,13 @@ class DashboardSearchTest(AcceptanceTest): ...@@ -106,13 +106,13 @@ class DashboardSearchTest(AcceptanceTest):
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
AutoAuthPage(self.browser, username=username, email=email, staff=staff).visit() AutoAuthPage(self.browser, username=username, email=email, staff=staff).visit()
def _studio_add_content(self, course_outline, html_content): def _studio_add_content(self, studio_course_outline, html_content):
""" """
Add content to first section on studio course page. Add content to first section on studio course page.
""" """
# create a unit in course outline # create a unit in course outline
course_outline.visit() studio_course_outline.visit()
subsection = course_outline.section_at(0).subsection_at(0) subsection = studio_course_outline.section_at(0).subsection_at(0)
subsection.expand_subsection() subsection.expand_subsection()
subsection.add_unit() subsection.add_unit()
...@@ -126,12 +126,12 @@ class DashboardSearchTest(AcceptanceTest): ...@@ -126,12 +126,12 @@ class DashboardSearchTest(AcceptanceTest):
type_in_codemirror(unit_page, 0, html_content) type_in_codemirror(unit_page, 0, html_content)
click_css(unit_page, '.action-save', 0) click_css(unit_page, '.action-save', 0)
def _studio_publish_content(self, course_outline): def _studio_publish_content(self, studio_course_outline):
""" """
Publish content in first section on studio course page. Publish content in first section on studio course page.
""" """
course_outline.visit() studio_course_outline.visit()
subsection = course_outline.section_at(0).subsection_at(0) subsection = studio_course_outline.section_at(0).subsection_at(0)
subsection.expand_subsection() subsection.expand_subsection()
unit = subsection.unit_at(0) unit = subsection.unit_at(0)
unit.publish() unit.publish()
...@@ -167,9 +167,9 @@ class DashboardSearchTest(AcceptanceTest): ...@@ -167,9 +167,9 @@ class DashboardSearchTest(AcceptanceTest):
# Create content in studio without publishing. # Create content in studio without publishing.
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
self._studio_add_content(self.course_outlines['A'], html_content) self._studio_add_content(self.studio_course_outlines['A'], html_content)
self._studio_add_content(self.course_outlines['B'], html_content) self._studio_add_content(self.studio_course_outlines['B'], html_content)
self._studio_add_content(self.course_outlines['C'], html_content) self._studio_add_content(self.studio_course_outlines['C'], html_content)
# Do a search, there should be no results shown. # Do a search, there should be no results shown.
self._auto_auth(self.USERNAME, self.EMAIL, False) self._auto_auth(self.USERNAME, self.EMAIL, False)
...@@ -179,9 +179,9 @@ class DashboardSearchTest(AcceptanceTest): ...@@ -179,9 +179,9 @@ class DashboardSearchTest(AcceptanceTest):
# Publish in studio to trigger indexing. # Publish in studio to trigger indexing.
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
self._studio_publish_content(self.course_outlines['A']) self._studio_publish_content(self.studio_course_outlines['A'])
self._studio_publish_content(self.course_outlines['B']) self._studio_publish_content(self.studio_course_outlines['B'])
self._studio_publish_content(self.course_outlines['C']) self._studio_publish_content(self.studio_course_outlines['C'])
# Do the search again, this time we expect results from courses A & B, but not C # Do the search again, this time we expect results from courses A & B, but not C
self._auto_auth(self.USERNAME, self.EMAIL, False) self._auto_auth(self.USERNAME, self.EMAIL, False)
......
...@@ -9,7 +9,7 @@ from nose.plugins.attrib import attr ...@@ -9,7 +9,7 @@ from nose.plugins.attrib import attr
from common.test.acceptance.tests.helpers import UniqueCourseTest, EventsTestMixin from common.test.acceptance.tests.helpers import UniqueCourseTest, EventsTestMixin
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.course_nav import CourseNavPage 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.courseware import CoursewarePage
from common.test.acceptance.pages.lms.edxnotes import EdxNotesUnitPage, EdxNotesPage, EdxNotesPageNoContent from common.test.acceptance.pages.lms.edxnotes import EdxNotesUnitPage, EdxNotesPage, EdxNotesPageNoContent
from common.test.acceptance.fixtures.edxnotes import EdxNotesFixture, Note, Range from common.test.acceptance.fixtures.edxnotes import EdxNotesFixture, Note, Range
...@@ -26,7 +26,7 @@ class EdxNotesTestMixin(UniqueCourseTest): ...@@ -26,7 +26,7 @@ class EdxNotesTestMixin(UniqueCourseTest):
""" """
super(EdxNotesTestMixin, self).setUp() super(EdxNotesTestMixin, self).setUp()
self.courseware_page = CoursewarePage(self.browser, self.course_id) self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.course_nav = CourseNavPage(self.browser) self.course_home_page = CourseHomePage(self.browser, self.course_id)
self.note_unit_page = EdxNotesUnitPage(self.browser, self.course_id) self.note_unit_page = EdxNotesUnitPage(self.browser, self.course_id)
self.notes_page = EdxNotesPage(self.browser, self.course_id) self.notes_page = EdxNotesPage(self.browser, self.course_id)
...@@ -1504,7 +1504,8 @@ class EdxNotesToggleNotesTest(EdxNotesTestMixin): ...@@ -1504,7 +1504,8 @@ class EdxNotesToggleNotesTest(EdxNotesTestMixin):
self.assertEqual(len(self.note_unit_page.notes), 0) self.assertEqual(len(self.note_unit_page.notes), 0)
self.courseware_page.go_to_sequential_position(2) self.courseware_page.go_to_sequential_position(2)
self.assertEqual(len(self.note_unit_page.notes), 0) self.assertEqual(len(self.note_unit_page.notes), 0)
self.course_nav.go_to_section(u"Test Section 1", u"Test Subsection 2") self.course_home_page.visit()
self.course_home_page.outline.go_to_section(u"Test Section 1", u"Test Subsection 2")
self.assertEqual(len(self.note_unit_page.notes), 0) self.assertEqual(len(self.note_unit_page.notes), 0)
def test_can_reenable_all_notes(self): def test_can_reenable_all_notes(self):
...@@ -1530,5 +1531,6 @@ class EdxNotesToggleNotesTest(EdxNotesTestMixin): ...@@ -1530,5 +1531,6 @@ class EdxNotesToggleNotesTest(EdxNotesTestMixin):
self.assertGreater(len(self.note_unit_page.notes), 0) self.assertGreater(len(self.note_unit_page.notes), 0)
self.courseware_page.go_to_sequential_position(2) self.courseware_page.go_to_sequential_position(2)
self.assertGreater(len(self.note_unit_page.notes), 0) self.assertGreater(len(self.note_unit_page.notes), 0)
self.course_nav.go_to_section(u"Test Section 1", u"Test Subsection 2") self.course_home_page.visit()
self.course_home_page.outline.go_to_section(u"Test Section 1", u"Test Subsection 2")
self.assertGreater(len(self.note_unit_page.notes), 0) self.assertGreater(len(self.note_unit_page.notes), 0)
...@@ -43,7 +43,7 @@ class EntranceExamTest(UniqueCourseTest): ...@@ -43,7 +43,7 @@ class EntranceExamTest(UniqueCourseTest):
).install() ).install()
entrance_exam_subsection = None entrance_exam_subsection = None
outline = course_fixture.course_outline outline = course_fixture.studio_course_outline_as_json
for child in outline['child_info']['children']: for child in outline['child_info']['children']:
if child.get('display_name') == "Entrance Exam": if child.get('display_name') == "Entrance Exam":
entrance_exam_subsection = child['child_info']['children'][0] entrance_exam_subsection = child['child_info']['children'][0]
......
...@@ -6,7 +6,7 @@ from textwrap import dedent ...@@ -6,7 +6,7 @@ from textwrap import dedent
from common.test.acceptance.tests.helpers import UniqueCourseTest from common.test.acceptance.tests.helpers import UniqueCourseTest
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.problem import ProblemPage from common.test.acceptance.pages.lms.problem import ProblemPage
from common.test.acceptance.pages.lms.staff_view import StaffPage from common.test.acceptance.pages.lms.staff_view import StaffPage
...@@ -29,7 +29,7 @@ class GatingTest(UniqueCourseTest): ...@@ -29,7 +29,7 @@ class GatingTest(UniqueCourseTest):
self.logout_page = LogoutPage(self.browser) self.logout_page = LogoutPage(self.browser)
self.courseware_page = CoursewarePage(self.browser, self.course_id) self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.course_outline = CourseOutlinePage( self.studio_course_outline = StudioCourseOutlinePage(
self.browser, self.browser,
self.course_info['org'], self.course_info['org'],
self.course_info['number'], self.course_info['number'],
...@@ -89,10 +89,10 @@ class GatingTest(UniqueCourseTest): ...@@ -89,10 +89,10 @@ class GatingTest(UniqueCourseTest):
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
# Make the first subsection a prerequisite # Make the first subsection a prerequisite
self.course_outline.visit() self.studio_course_outline.visit()
self.course_outline.open_subsection_settings_dialog(0) self.studio_course_outline.open_subsection_settings_dialog(0)
self.course_outline.select_advanced_tab(desired_item='gated_content') self.studio_course_outline.select_advanced_tab(desired_item='gated_content')
self.course_outline.make_gating_prerequisite() self.studio_course_outline.make_gating_prerequisite()
def _setup_gated_subsection(self): def _setup_gated_subsection(self):
""" """
...@@ -102,10 +102,10 @@ class GatingTest(UniqueCourseTest): ...@@ -102,10 +102,10 @@ class GatingTest(UniqueCourseTest):
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
# Gate the second subsection based on the score achieved in the first subsection # Gate the second subsection based on the score achieved in the first subsection
self.course_outline.visit() self.studio_course_outline.visit()
self.course_outline.open_subsection_settings_dialog(1) self.studio_course_outline.open_subsection_settings_dialog(1)
self.course_outline.select_advanced_tab(desired_item='gated_content') self.studio_course_outline.select_advanced_tab(desired_item='gated_content')
self.course_outline.add_prerequisite_to_subsection("80") self.studio_course_outline.add_prerequisite_to_subsection("80")
def _fulfill_prerequisite(self): def _fulfill_prerequisite(self):
""" """
...@@ -127,23 +127,23 @@ class GatingTest(UniqueCourseTest): ...@@ -127,23 +127,23 @@ class GatingTest(UniqueCourseTest):
self._setup_prereq() self._setup_prereq()
# Assert settings are displayed correctly for a prerequisite subsection # Assert settings are displayed correctly for a prerequisite subsection
self.course_outline.visit() self.studio_course_outline.visit()
self.course_outline.open_subsection_settings_dialog(0) self.studio_course_outline.open_subsection_settings_dialog(0)
self.course_outline.select_advanced_tab(desired_item='gated_content') self.studio_course_outline.select_advanced_tab(desired_item='gated_content')
self.assertTrue(self.course_outline.gating_prerequisite_checkbox_is_visible()) self.assertTrue(self.studio_course_outline.gating_prerequisite_checkbox_is_visible())
self.assertTrue(self.course_outline.gating_prerequisite_checkbox_is_checked()) self.assertTrue(self.studio_course_outline.gating_prerequisite_checkbox_is_checked())
self.assertFalse(self.course_outline.gating_prerequisites_dropdown_is_visible()) self.assertFalse(self.studio_course_outline.gating_prerequisites_dropdown_is_visible())
self.assertFalse(self.course_outline.gating_prerequisite_min_score_is_visible()) self.assertFalse(self.studio_course_outline.gating_prerequisite_min_score_is_visible())
self._setup_gated_subsection() self._setup_gated_subsection()
# Assert settings are displayed correctly for a gated subsection # Assert settings are displayed correctly for a gated subsection
self.course_outline.visit() self.studio_course_outline.visit()
self.course_outline.open_subsection_settings_dialog(1) self.studio_course_outline.open_subsection_settings_dialog(1)
self.course_outline.select_advanced_tab(desired_item='gated_content') self.studio_course_outline.select_advanced_tab(desired_item='gated_content')
self.assertTrue(self.course_outline.gating_prerequisite_checkbox_is_visible()) self.assertTrue(self.studio_course_outline.gating_prerequisite_checkbox_is_visible())
self.assertTrue(self.course_outline.gating_prerequisites_dropdown_is_visible()) self.assertTrue(self.studio_course_outline.gating_prerequisites_dropdown_is_visible())
self.assertTrue(self.course_outline.gating_prerequisite_min_score_is_visible()) self.assertTrue(self.studio_course_outline.gating_prerequisite_min_score_is_visible())
def test_gated_subsection_in_lms_for_student(self): def test_gated_subsection_in_lms_for_student(self):
""" """
......
...@@ -12,7 +12,7 @@ from flaky import flaky ...@@ -12,7 +12,7 @@ from flaky import flaky
from common.test.acceptance.tests.helpers import UniqueCourseTest, get_modal_alert, EventsTestMixin from common.test.acceptance.tests.helpers import UniqueCourseTest, get_modal_alert, EventsTestMixin
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.pages.lms.create_mode import ModeCreationPage from common.test.acceptance.pages.lms.create_mode import ModeCreationPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage, EntranceExamAdmin from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage, EntranceExamAdmin
...@@ -227,7 +227,7 @@ class ProctoredExamsTest(BaseInstructorDashboardTest): ...@@ -227,7 +227,7 @@ class ProctoredExamsTest(BaseInstructorDashboardTest):
self.courseware_page = CoursewarePage(self.browser, self.course_id) self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.course_outline = CourseOutlinePage( self.studio_course_outline = StudioCourseOutlinePage(
self.browser, self.browser,
self.course_info['org'], self.course_info['org'],
self.course_info['number'], self.course_info['number'],
...@@ -301,15 +301,15 @@ class ProctoredExamsTest(BaseInstructorDashboardTest): ...@@ -301,15 +301,15 @@ class ProctoredExamsTest(BaseInstructorDashboardTest):
# Visit the course outline page in studio # Visit the course outline page in studio
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
self._auto_auth("STAFF_TESTER", "staff101@example.com", True) self._auto_auth("STAFF_TESTER", "staff101@example.com", True)
self.course_outline.visit() self.studio_course_outline.visit()
# open the exam settings to make it a proctored exam. # open the exam settings to make it a proctored exam.
self.course_outline.open_subsection_settings_dialog() self.studio_course_outline.open_subsection_settings_dialog()
# select advanced settings tab # select advanced settings tab
self.course_outline.select_advanced_tab() self.studio_course_outline.select_advanced_tab()
self.course_outline.make_exam_proctored() self.studio_course_outline.make_exam_proctored()
# login as a verified student and visit the courseware. # login as a verified student and visit the courseware.
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
...@@ -327,15 +327,15 @@ class ProctoredExamsTest(BaseInstructorDashboardTest): ...@@ -327,15 +327,15 @@ class ProctoredExamsTest(BaseInstructorDashboardTest):
# Visit the course outline page in studio # Visit the course outline page in studio
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
self._auto_auth("STAFF_TESTER", "staff101@example.com", True) self._auto_auth("STAFF_TESTER", "staff101@example.com", True)
self.course_outline.visit() self.studio_course_outline.visit()
# open the exam settings to make it a proctored exam. # open the exam settings to make it a proctored exam.
self.course_outline.open_subsection_settings_dialog() self.studio_course_outline.open_subsection_settings_dialog()
# select advanced settings tab # select advanced settings tab
self.course_outline.select_advanced_tab() self.studio_course_outline.select_advanced_tab()
self.course_outline.make_exam_timed() self.studio_course_outline.make_exam_timed()
# login as a verified student and visit the courseware. # login as a verified student and visit the courseware.
LogoutPage(self.browser).visit() LogoutPage(self.browser).visit()
......
...@@ -6,9 +6,8 @@ import json ...@@ -6,9 +6,8 @@ import json
from common.test.acceptance.tests.helpers import remove_file from common.test.acceptance.tests.helpers import remove_file
from common.test.acceptance.pages.common.logout import LogoutPage from common.test.acceptance.pages.common.logout import LogoutPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage 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.courseware_search import CoursewareSearchPage
from common.test.acceptance.pages.lms.course_nav import CourseNavPage
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
from common.test.acceptance.tests.helpers import create_user_partition_json from common.test.acceptance.tests.helpers import create_user_partition_json
...@@ -44,8 +43,7 @@ class SplitTestCoursewareSearchTest(ContainerBase): ...@@ -44,8 +43,7 @@ class SplitTestCoursewareSearchTest(ContainerBase):
self.staff_user = self.user self.staff_user = self.user
self.courseware_search_page = CoursewareSearchPage(self.browser, self.course_id) self.courseware_search_page = CoursewareSearchPage(self.browser, self.course_id)
self.course_navigation_page = CourseNavPage(self.browser) self.studio_course_outline = StudioCourseOutlinePage(
self.course_outline = CourseOutlinePage(
self.browser, self.browser,
self.course_info['org'], self.course_info['org'],
self.course_info['number'], self.course_info['number'],
...@@ -68,9 +66,9 @@ class SplitTestCoursewareSearchTest(ContainerBase): ...@@ -68,9 +66,9 @@ class SplitTestCoursewareSearchTest(ContainerBase):
Reindex course content on studio course page Reindex course content on studio course page
""" """
self._auto_auth(self.staff_user["username"], self.staff_user["email"], True) self._auto_auth(self.staff_user["username"], self.staff_user["email"], True)
self.course_outline.visit() self.studio_course_outline.visit()
self.course_outline.start_reindex() self.studio_course_outline.start_reindex()
self.course_outline.wait_for_ajax() self.studio_course_outline.wait_for_ajax()
def _create_group_configuration(self): def _create_group_configuration(self):
""" """
......
...@@ -20,7 +20,7 @@ from ...pages.lms.problem import ProblemPage ...@@ -20,7 +20,7 @@ from ...pages.lms.problem import ProblemPage
from ...pages.lms.progress import ProgressPage from ...pages.lms.progress import ProgressPage
from ...pages.studio.component_editor import ComponentEditorView from ...pages.studio.component_editor import ComponentEditorView
from ...pages.studio.utils import type_in_codemirror from ...pages.studio.utils import type_in_codemirror
from ...pages.studio.overview import CourseOutlinePage from ...pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
class ProgressPageBaseTest(UniqueCourseTest): class ProgressPageBaseTest(UniqueCourseTest):
...@@ -43,7 +43,7 @@ class ProgressPageBaseTest(UniqueCourseTest): ...@@ -43,7 +43,7 @@ class ProgressPageBaseTest(UniqueCourseTest):
self.progress_page = ProgressPage(self.browser, self.course_id) self.progress_page = ProgressPage(self.browser, self.course_id)
self.logout_page = LogoutPage(self.browser) self.logout_page = LogoutPage(self.browser)
self.course_outline = CourseOutlinePage( self.studio_course_outline = StudioCourseOutlinePage(
self.browser, self.browser,
self.course_info['org'], self.course_info['org'],
self.course_info['number'], self.course_info['number'],
...@@ -140,11 +140,11 @@ class PersistentGradesTest(ProgressPageBaseTest): ...@@ -140,11 +140,11 @@ class PersistentGradesTest(ProgressPageBaseTest):
Adds a unit to the subsection, which Adds a unit to the subsection, which
should not affect a persisted subsection grade. should not affect a persisted subsection grade.
""" """
self.course_outline.visit() self.studio_course_outline.visit()
subsection = self.course_outline.section(self.SECTION_NAME).subsection(self.SUBSECTION_NAME) subsection = self.studio_course_outline.section(self.SECTION_NAME).subsection(self.SUBSECTION_NAME)
subsection.expand_subsection() subsection.expand_subsection()
subsection.add_unit() subsection.add_unit()
self.course_outline.wait_for_ajax() self.studio_course_outline.wait_for_ajax()
subsection.publish() subsection.publish()
def _set_staff_lock_on_subsection(self, locked): def _set_staff_lock_on_subsection(self, locked):
...@@ -152,8 +152,8 @@ class PersistentGradesTest(ProgressPageBaseTest): ...@@ -152,8 +152,8 @@ class PersistentGradesTest(ProgressPageBaseTest):
Sets staff lock for a subsection, which should hide the Sets staff lock for a subsection, which should hide the
subsection score from students on the progress page. subsection score from students on the progress page.
""" """
self.course_outline.visit() self.studio_course_outline.visit()
subsection = self.course_outline.section_at(0).subsection_at(0) subsection = self.studio_course_outline.section_at(0).subsection_at(0)
subsection.set_staff_lock(locked) subsection.set_staff_lock(locked)
self.assertEqual(subsection.has_staff_lock_warning, locked) self.assertEqual(subsection.has_staff_lock_warning, locked)
...@@ -163,9 +163,9 @@ class PersistentGradesTest(ProgressPageBaseTest): ...@@ -163,9 +163,9 @@ class PersistentGradesTest(ProgressPageBaseTest):
along with its container unit, so any changes can along with its container unit, so any changes can
be published. be published.
""" """
self.course_outline.visit() self.studio_course_outline.visit()
self.course_outline.section_at(0).subsection_at(0).expand_subsection() self.studio_course_outline.section_at(0).subsection_at(0).expand_subsection()
unit = self.course_outline.section_at(0).subsection_at(0).unit(self.UNIT_NAME).go_to() unit = self.studio_course_outline.section_at(0).subsection_at(0).unit(self.UNIT_NAME).go_to()
component = unit.xblocks[1] component = unit.xblocks[1]
return unit, component return unit, component
...@@ -289,8 +289,8 @@ class SubsectionGradingPolicyTest(ProgressPageBaseTest): ...@@ -289,8 +289,8 @@ class SubsectionGradingPolicyTest(ProgressPageBaseTest):
If a section index is not provided, 0 is assumed. If a section index is not provided, 0 is assumed.
""" """
with self._logged_in_session(staff=True): with self._logged_in_session(staff=True):
self.course_outline.visit() self.studio_course_outline.visit()
modal = self.course_outline.section_at(section).subsection_at(0).edit() modal = self.studio_course_outline.section_at(section).subsection_at(0).edit()
modal.policy = policy modal.policy = policy
modal.save() modal.save()
......
...@@ -12,8 +12,8 @@ from nose.plugins.attrib import attr ...@@ -12,8 +12,8 @@ from nose.plugins.attrib import attr
from common.test.acceptance.pages.studio.settings_advanced import AdvancedSettingsPage from common.test.acceptance.pages.studio.settings_advanced import AdvancedSettingsPage
from common.test.acceptance.pages.studio.overview import CourseOutlinePage, ContainerPage, ExpandCollapseLinkState from common.test.acceptance.pages.studio.overview import CourseOutlinePage, ContainerPage, ExpandCollapseLinkState
from common.test.acceptance.pages.studio.utils import add_discussion, drag, verify_ordering 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.courseware import CoursewarePage
from common.test.acceptance.pages.lms.course_nav import CourseNavPage
from common.test.acceptance.pages.lms.staff_view import StaffPage from common.test.acceptance.pages.lms.staff_view import StaffPage
from common.test.acceptance.fixtures.config import ConfigModelFixture from common.test.acceptance.fixtures.config import ConfigModelFixture
from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.fixtures.course import XBlockFixtureDesc
...@@ -1490,7 +1490,7 @@ class PublishSectionTest(CourseOutlineTest): ...@@ -1490,7 +1490,7 @@ class PublishSectionTest(CourseOutlineTest):
The first subsection has 2 units, and the second subsection has one unit. The first subsection has 2 units, and the second subsection has one unit.
""" """
self.courseware = CoursewarePage(self.browser, self.course_id) self.courseware = CoursewarePage(self.browser, self.course_id)
self.course_nav = CourseNavPage(self.browser) self.course_home_page = CourseHomePage(self.browser, self.course_id)
course_fixture.add_children( course_fixture.add_children(
XBlockFixtureDesc('chapter', SECTION_NAME).add_children( XBlockFixtureDesc('chapter', SECTION_NAME).add_children(
XBlockFixtureDesc('sequential', SUBSECTION_NAME).add_children( XBlockFixtureDesc('sequential', SUBSECTION_NAME).add_children(
...@@ -1578,7 +1578,8 @@ class PublishSectionTest(CourseOutlineTest): ...@@ -1578,7 +1578,8 @@ class PublishSectionTest(CourseOutlineTest):
self.assertEqual(1, self.courseware.num_xblock_components) self.assertEqual(1, self.courseware.num_xblock_components)
self.courseware.go_to_sequential_position(2) self.courseware.go_to_sequential_position(2)
self.assertEqual(1, self.courseware.num_xblock_components) self.assertEqual(1, self.courseware.num_xblock_components)
self.course_nav.go_to_section(SECTION_NAME, 'Test Subsection 2') self.course_home_page.visit()
self.course_home_page.outline.go_to_section(SECTION_NAME, 'Test Subsection 2')
self.assertEqual(1, self.courseware.num_xblock_components) self.assertEqual(1, self.courseware.num_xblock_components)
def _add_unpublished_content(self): def _add_unpublished_content(self):
......
...@@ -15,7 +15,6 @@ from common.test.acceptance.tests.helpers import UniqueCourseTest, is_youtube_av ...@@ -15,7 +15,6 @@ from common.test.acceptance.tests.helpers import UniqueCourseTest, is_youtube_av
from common.test.acceptance.pages.lms.video.video import VideoPage from common.test.acceptance.pages.lms.video.video import VideoPage
from common.test.acceptance.pages.lms.tab_nav import TabNavPage from common.test.acceptance.pages.lms.tab_nav import TabNavPage
from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.courseware import CoursewarePage
from common.test.acceptance.pages.lms.course_nav import CourseNavPage
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage from common.test.acceptance.pages.lms.course_info import CourseInfoPage
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
...@@ -53,7 +52,6 @@ class VideoBaseTest(UniqueCourseTest): ...@@ -53,7 +52,6 @@ class VideoBaseTest(UniqueCourseTest):
self.video = VideoPage(self.browser) self.video = VideoPage(self.browser)
self.tab_nav = TabNavPage(self.browser) self.tab_nav = TabNavPage(self.browser)
self.course_nav = CourseNavPage(self.browser)
self.courseware = CoursewarePage(self.browser, self.course_id) self.courseware = CoursewarePage(self.browser, self.course_id)
self.course_info_page = CourseInfoPage(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.auth_page = AutoAuthPage(self.browser, course_id=self.course_id)
...@@ -531,7 +529,7 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -531,7 +529,7 @@ class YouTubeVideoTest(VideoBaseTest):
self.assertTrue(self.video.downloaded_transcript_contains_text(file_type, search_text)) self.assertTrue(self.video.downloaded_transcript_contains_text(file_type, search_text))
# open vertical containing video "C" # open vertical containing video "C"
self.course_nav.go_to_vertical('Test Vertical-2') self.courseware.nav.go_to_vertical('Test Vertical-2')
# menu "download_transcript" doesn't exist # menu "download_transcript" doesn't exist
self.assertFalse(self.video.is_menu_present('download_transcript')) self.assertFalse(self.video.is_menu_present('download_transcript'))
...@@ -678,17 +676,17 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -678,17 +676,17 @@ class YouTubeVideoTest(VideoBaseTest):
self.navigate_to_video() self.navigate_to_video()
# select the "2.0" speed on video "A" # select the "2.0" speed on video "A"
self.course_nav.go_to_vertical('Test Vertical-0') self.courseware.nav.go_to_vertical('Test Vertical-0')
self.video.wait_for_video_player_render() self.video.wait_for_video_player_render()
self.video.speed = '2.0' self.video.speed = '2.0'
# select the "0.50" speed on video "B" # select the "0.50" speed on video "B"
self.course_nav.go_to_vertical('Test Vertical-1') self.courseware.nav.go_to_vertical('Test Vertical-1')
self.video.wait_for_video_player_render() self.video.wait_for_video_player_render()
self.video.speed = '0.50' self.video.speed = '0.50'
# open video "C" # open video "C"
self.course_nav.go_to_vertical('Test Vertical-2') self.courseware.nav.go_to_vertical('Test Vertical-2')
self.video.wait_for_video_player_render() self.video.wait_for_video_player_render()
# Since the playback speed was set to .5 in "B", this video will also be impacted # Since the playback speed was set to .5 in "B", this video will also be impacted
...@@ -697,7 +695,7 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -697,7 +695,7 @@ class YouTubeVideoTest(VideoBaseTest):
self.video.verify_speed_changed('0.75x') self.video.verify_speed_changed('0.75x')
# go to the vertical containing video "A" # go to the vertical containing video "A"
self.course_nav.go_to_vertical('Test Vertical-0') self.courseware.nav.go_to_vertical('Test Vertical-0')
# Video "A" should still play at speed 2.0 because it was explicitly set to that. # Video "A" should still play at speed 2.0 because it was explicitly set to that.
self.assertEqual(self.video.speed, '2.0x') self.assertEqual(self.video.speed, '2.0x')
...@@ -706,7 +704,7 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -706,7 +704,7 @@ class YouTubeVideoTest(VideoBaseTest):
self.video.reload_page() self.video.reload_page()
# go to the vertical containing video "A" # go to the vertical containing video "A"
self.course_nav.go_to_vertical('Test Vertical-0') self.courseware.nav.go_to_vertical('Test Vertical-0')
# check if video "A" should start playing at speed "2.0" # check if video "A" should start playing at speed "2.0"
self.assertEqual(self.video.speed, '2.0x') self.assertEqual(self.video.speed, '2.0x')
...@@ -715,13 +713,13 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -715,13 +713,13 @@ class YouTubeVideoTest(VideoBaseTest):
self.video.speed = '1.0' self.video.speed = '1.0'
# go to the vertical containing "B" # go to the vertical containing "B"
self.course_nav.go_to_vertical('Test Vertical-1') self.courseware.nav.go_to_vertical('Test Vertical-1')
# Video "B" should still play at speed .5 because it was explicitly set to that. # Video "B" should still play at speed .5 because it was explicitly set to that.
self.assertEqual(self.video.speed, '0.50x') self.assertEqual(self.video.speed, '0.50x')
# go to the vertical containing video "C" # go to the vertical containing video "C"
self.course_nav.go_to_vertical('Test Vertical-2') self.courseware.nav.go_to_vertical('Test Vertical-2')
# The change of speed for Video "A" should impact Video "C" because it still has # The change of speed for Video "A" should impact Video "C" because it still has
# not been explicitly set to a speed. # not been explicitly set to a speed.
......
...@@ -25,7 +25,6 @@ from django.http import ( ...@@ -25,7 +25,6 @@ from django.http import (
QueryDict, QueryDict,
) )
from django.shortcuts import redirect from django.shortcuts import redirect
from django.template.loader import render_to_string
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.utils.timezone import UTC from django.utils.timezone import UTC
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
......
...@@ -223,6 +223,18 @@ ECOMMERCE_API_URL = 'http://localhost:8043/api/v2/' ...@@ -223,6 +223,18 @@ ECOMMERCE_API_URL = 'http://localhost:8043/api/v2/'
LMS_ROOT_URL = "http://localhost:8000" LMS_ROOT_URL = "http://localhost:8000"
DOC_LINK_BASE_URL = 'http://edx.readthedocs.io/projects/edx-guide-for-students' DOC_LINK_BASE_URL = 'http://edx.readthedocs.io/projects/edx-guide-for-students'
# TODO: TNL-6546: Remove this waffle and flag code.
from django.db.utils import ProgrammingError
from waffle.models import Flag
try:
flag, created = Flag.objects.get_or_create(name='unified_course_view')
flag.everyone = True
flag.save
WAFFLE_OVERRIDE = True
except ProgrammingError:
# during initial reset_db, the table for the flag doesn't yet exist.
pass
##################################################################### #####################################################################
# Lastly, see if the developer has any local overrides. # Lastly, see if the developer has any local overrides.
try: try:
......
...@@ -36,14 +36,8 @@ ${HTML(outline_fragment.foot_html())} ...@@ -36,14 +36,8 @@ ${HTML(outline_fragment.foot_html())}
</%block> </%block>
<%block name="content"> <%block name="content">
<section class="course-view container" id="course-container"> <div class="course-view container" id="course-container">
<header class="page-header has-secondary"> <header class="page-header has-secondary">
## Breadcrumb navigation
<div class="page-header-main">
<nav aria-label="${_('Discussions')}" class="sr-is-focusable" tabindex="-1">
<div class="has-breadcrumbs"></div>
</nav>
</div>
<div class="page-header-secondary"> <div class="page-header-secondary">
<div class="form-actions"> <div class="form-actions">
<a class="btn" href="${reverse('courseware', kwargs={'course_id': unicode(course.id.to_deprecated_string())})}"> <a class="btn" href="${reverse('courseware', kwargs={'course_id': unicode(course.id.to_deprecated_string())})}">
...@@ -52,15 +46,15 @@ ${HTML(outline_fragment.foot_html())} ...@@ -52,15 +46,15 @@ ${HTML(outline_fragment.foot_html())}
</div> </div>
<div class="page-header-search"> <div class="page-header-search">
<form class="search-form" role="search"> <form class="search-form" role="search">
<label class="field-label sr-only" for="search" id="search-hint">Search the course</label> <label class="field-label sr-only" for="search" id="search-hint">${_('Search the course')}</label>
<input <input
class="field-input input-text search-input" class="field-input input-text search-input"
type="search" type="search"
name="search" name="search"
id="search" id="search"
placeholder="Search the course" placeholder="${_('Search the course')}'"
/> />
<button class="btn btn-small search-btn" type="button">Search</button> <button class="btn btn-small search-btn" type="button">${_('Search')}</button>
</form> </form>
</div> </div>
</div> </div>
...@@ -68,5 +62,5 @@ ${HTML(outline_fragment.foot_html())} ...@@ -68,5 +62,5 @@ ${HTML(outline_fragment.foot_html())}
<div class="page-content"> <div class="page-content">
${HTML(outline_fragment.body_html())} ${HTML(outline_fragment.body_html())}
</div> </div>
</section> </div>
</%block> </%block>
...@@ -10,7 +10,7 @@ from django.utils.translation import ugettext as _ ...@@ -10,7 +10,7 @@ from django.utils.translation import ugettext as _
CourseOutlineFactory('.block-tree'); CourseOutlineFactory('.block-tree');
</%static:require_module_async> </%static:require_module_async>
<section class="course-outline" id="main"> <div class="course-outline" id="main" tabindex="-1">
<ol class="block-tree" role="tree"> <ol class="block-tree" role="tree">
% for section in blocks.get('children') or []: % for section in blocks.get('children') or []:
<li <li
...@@ -39,4 +39,4 @@ from django.utils.translation import ugettext as _ ...@@ -39,4 +39,4 @@ from django.utils.translation import ugettext as _
</li> </li>
% endfor % endfor
</ol> </ol>
</section> </div>
...@@ -46,7 +46,7 @@ class CourseOutlineFragmentView(FragmentView): ...@@ -46,7 +46,7 @@ class CourseOutlineFragmentView(FragmentView):
user=request.user, user=request.user,
nav_depth=3, nav_depth=3,
requested_fields=['children', 'display_name', 'type'], requested_fields=['children', 'display_name', 'type'],
block_types_filter=['course', 'chapter', 'vertical', 'sequential'] block_types_filter=['course', 'chapter', 'sequential']
) )
course_block_tree = all_blocks['blocks'][all_blocks['root']] # Get the root of the block tree course_block_tree = all_blocks['blocks'][all_blocks['root']] # Get the root of the block tree
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment