@@ -15,6 +15,7 @@ class PaginatedUIMixin(object):
|
||||
PREVIOUS_PAGE_BUTTON_CSS = 'button.previous-page-link'
|
||||
PAGINATION_HEADER_TEXT_CSS = 'div.search-tools'
|
||||
CURRENT_PAGE_NUMBER_CSS = 'span.current-page'
|
||||
TOTAL_PAGES_CSS = 'span.total-pages'
|
||||
|
||||
def get_pagination_header_text(self):
|
||||
"""Return the text showing which items the user is currently viewing."""
|
||||
@@ -31,6 +32,11 @@ class PaginatedUIMixin(object):
|
||||
"""Return the the current page number."""
|
||||
return int(self.q(css=self.CURRENT_PAGE_NUMBER_CSS).text[0])
|
||||
|
||||
@property
|
||||
def get_total_pages(self):
|
||||
"""Returns the total page value"""
|
||||
return int(self.q(css=self.TOTAL_PAGES_CSS).text[0])
|
||||
|
||||
def go_to_page(self, page_number):
|
||||
"""Go to the given page_number in the paginated list results."""
|
||||
self.q(css=self.PAGE_NUMBER_INPUT_CSS).results[0].send_keys(unicode(page_number), Keys.ENTER)
|
||||
|
||||
65
common/test/acceptance/pages/lms/bookmarks.py
Normal file
65
common/test/acceptance/pages/lms/bookmarks.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
Courseware Boomarks
|
||||
"""
|
||||
from bok_choy.promise import EmptyPromise
|
||||
from .course_page import CoursePage
|
||||
from ..common.paging import PaginatedUIMixin
|
||||
|
||||
|
||||
class BookmarksPage(CoursePage, PaginatedUIMixin):
|
||||
"""
|
||||
Courseware Bookmarks Page.
|
||||
"""
|
||||
url = None
|
||||
url_path = "courseware/"
|
||||
BOOKMARKS_BUTTON_SELECTOR = '.bookmarks-list-button'
|
||||
BOOKMARKED_ITEMS_SELECTOR = '.bookmarks-results-list .bookmarks-results-list-item'
|
||||
BOOKMARKED_BREADCRUMBS = BOOKMARKED_ITEMS_SELECTOR + ' .list-item-breadcrumbtrail'
|
||||
|
||||
def is_browser_on_page(self):
|
||||
""" Verify if we are on correct page """
|
||||
return self.q(css=self.BOOKMARKS_BUTTON_SELECTOR).visible
|
||||
|
||||
def bookmarks_button_visible(self):
|
||||
""" Check if bookmarks button is visible """
|
||||
return self.q(css=self.BOOKMARKS_BUTTON_SELECTOR).visible
|
||||
|
||||
def click_bookmarks_button(self, wait_for_results=True):
|
||||
""" Click on Bookmarks button """
|
||||
self.q(css=self.BOOKMARKS_BUTTON_SELECTOR).first.click()
|
||||
if wait_for_results:
|
||||
EmptyPromise(self.results_present, "Bookmarks results present").fulfill()
|
||||
|
||||
def results_present(self):
|
||||
""" Check if bookmarks results are present """
|
||||
return self.q(css='#my-bookmarks').present
|
||||
|
||||
def results_header_text(self):
|
||||
""" Returns the bookmarks results header text """
|
||||
return self.q(css='.bookmarks-results-header').text[0]
|
||||
|
||||
def empty_header_text(self):
|
||||
""" Returns the bookmarks empty header text """
|
||||
return self.q(css='.bookmarks-empty-header').text[0]
|
||||
|
||||
def empty_list_text(self):
|
||||
""" Returns the bookmarks empty list text """
|
||||
return self.q(css='.bookmarks-empty-detail-title').text[0]
|
||||
|
||||
def count(self):
|
||||
""" Returns the total number of bookmarks in the list """
|
||||
return len(self.q(css=self.BOOKMARKED_ITEMS_SELECTOR).results)
|
||||
|
||||
def breadcrumbs(self):
|
||||
""" Return list of breadcrumbs for all bookmarks """
|
||||
breadcrumbs = self.q(css=self.BOOKMARKED_BREADCRUMBS).text
|
||||
return [breadcrumb.replace('\n', '').split('-') for breadcrumb in breadcrumbs]
|
||||
|
||||
def click_bookmarked_block(self, index):
|
||||
"""
|
||||
Click on bookmarked block at index `index`
|
||||
|
||||
Arguments:
|
||||
index (int): bookmark index in the list
|
||||
"""
|
||||
self.q(css=self.BOOKMARKED_ITEMS_SELECTOR).nth(index).click()
|
||||
@@ -193,13 +193,13 @@ class CourseNavPage(PageObject):
|
||||
)
|
||||
|
||||
# Regular expression to remove HTML span tags from a string
|
||||
REMOVE_SPAN_TAG_RE = re.compile(r'<span.+/span>')
|
||||
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.sub('', element.get_attribute('innerHTML')).strip().split('\n')[0]
|
||||
return self.REMOVE_SPAN_TAG_RE.search(element.get_attribute('innerHTML')).groups()[0].strip()
|
||||
|
||||
def go_to_sequential_position(self, sequential_position):
|
||||
"""
|
||||
|
||||
@@ -3,6 +3,7 @@ Courseware page.
|
||||
"""
|
||||
|
||||
from .course_page import CoursePage
|
||||
from bok_choy.promise import EmptyPromise
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
|
||||
|
||||
@@ -171,6 +172,38 @@ class CoursewarePage(CoursePage):
|
||||
"""
|
||||
return self.q(css=".proctored_exam_status .exam-timer").is_present()
|
||||
|
||||
def active_usage_id(self):
|
||||
""" Returns the usage id of active sequence item """
|
||||
get_active = lambda el: 'active' in el.get_attribute('class')
|
||||
attribute_value = lambda el: el.get_attribute('data-id')
|
||||
return self.q(css='#sequence-list a').filter(get_active).map(attribute_value).results[0]
|
||||
|
||||
@property
|
||||
def breadcrumb(self):
|
||||
""" Return the course tree breadcrumb shown above the sequential bar """
|
||||
return [part.strip() for part in self.q(css='.path').text[0].split('>')]
|
||||
|
||||
def bookmark_button_visible(self):
|
||||
""" Check if bookmark button is visible """
|
||||
EmptyPromise(lambda: self.q(css='.bookmark-button').visible, "Bookmark button visible").fulfill()
|
||||
return True
|
||||
|
||||
@property
|
||||
def bookmark_button_state(self):
|
||||
""" Return `bookmarked` if button is in bookmarked state else '' """
|
||||
return 'bookmarked' if self.q(css='.bookmark-button.bookmarked').present else ''
|
||||
|
||||
@property
|
||||
def bookmark_icon_visible(self):
|
||||
""" Check if bookmark icon is visible on active sequence nav item """
|
||||
return self.q(css='.active .bookmark-icon').visible
|
||||
|
||||
def click_bookmark_unit_button(self):
|
||||
""" Bookmark a unit by clicking on Bookmark button """
|
||||
previous_state = self.bookmark_button_state
|
||||
self.q(css='.bookmark-button').first.click()
|
||||
EmptyPromise(lambda: self.bookmark_button_state != previous_state, "Bookmark button toggled").fulfill()
|
||||
|
||||
|
||||
class CoursewareSequentialTabPage(CoursePage):
|
||||
"""
|
||||
|
||||
@@ -12,11 +12,12 @@ class CoursewareSearchPage(CoursePage):
|
||||
|
||||
url_path = "courseware/"
|
||||
search_bar_selector = '#courseware-search-bar'
|
||||
search_results_selector = '.courseware-results'
|
||||
|
||||
@property
|
||||
def search_results(self):
|
||||
""" search results list showing """
|
||||
return self.q(css='#courseware-search-results')
|
||||
return self.q(css=self.search_results_selector)
|
||||
|
||||
def is_browser_on_page(self):
|
||||
""" did we find the search bar in the UI """
|
||||
@@ -30,6 +31,7 @@ class CoursewareSearchPage(CoursePage):
|
||||
""" execute the search """
|
||||
self.q(css=self.search_bar_selector + ' [type="submit"]').click()
|
||||
self.wait_for_ajax()
|
||||
self.wait_for_element_visibility(self.search_results_selector, 'Search results are visible')
|
||||
|
||||
def search_for_term(self, text):
|
||||
"""
|
||||
|
||||
@@ -564,7 +564,7 @@ class EdxNoteHighlight(NoteChild):
|
||||
"""
|
||||
Clicks cancel button.
|
||||
"""
|
||||
self.q(css=self._bounded_selector(".annotator-cancel")).first.click()
|
||||
self.q(css=self._bounded_selector(".annotator-close")).first.click()
|
||||
self.wait_for_notes_invisibility("Note is canceled.")
|
||||
return self
|
||||
|
||||
@@ -605,8 +605,7 @@ class EdxNoteHighlight(NoteChild):
|
||||
text = element.text[0].strip()
|
||||
else:
|
||||
text = None
|
||||
self.q(css=("body")).first.click()
|
||||
self.wait_for_notes_invisibility()
|
||||
self.cancel()
|
||||
return text
|
||||
|
||||
@text.setter
|
||||
@@ -629,8 +628,7 @@ class EdxNoteHighlight(NoteChild):
|
||||
if tags:
|
||||
for tag in tags:
|
||||
tag_text.append(tag.text)
|
||||
self.q(css="body").first.click()
|
||||
self.wait_for_notes_invisibility()
|
||||
self.cancel()
|
||||
return tag_text
|
||||
|
||||
@tags.setter
|
||||
|
||||
@@ -344,6 +344,11 @@ def get_element_padding(page, selector):
|
||||
return page.browser.execute_script(js_script)
|
||||
|
||||
|
||||
def is_404_page(browser):
|
||||
""" Check if page is 404 """
|
||||
return 'Page not found (404)' in browser.find_element_by_tag_name('h1').text
|
||||
|
||||
|
||||
class EventsTestMixin(TestCase):
|
||||
"""
|
||||
Helpers and setup for running tests that evaluate events emitted
|
||||
|
||||
640
common/test/acceptance/tests/lms/test_bookmarks.py
Normal file
640
common/test/acceptance/tests/lms/test_bookmarks.py
Normal file
@@ -0,0 +1,640 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
End-to-end tests for the courseware unit bookmarks.
|
||||
"""
|
||||
import json
|
||||
import requests
|
||||
from ...pages.studio.auto_auth import AutoAuthPage as StudioAutoAuthPage
|
||||
from ...pages.lms.auto_auth import AutoAuthPage as LmsAutoAuthPage
|
||||
from ...pages.lms.bookmarks import BookmarksPage
|
||||
from ...pages.lms.courseware import CoursewarePage
|
||||
from ...pages.lms.course_nav import CourseNavPage
|
||||
from ...pages.studio.overview import CourseOutlinePage
|
||||
from ...pages.common.logout import LogoutPage
|
||||
from ...pages.common import BASE_URL
|
||||
|
||||
from ...fixtures.course import CourseFixture, XBlockFixtureDesc
|
||||
from ..helpers import EventsTestMixin, UniqueCourseTest, is_404_page
|
||||
|
||||
|
||||
class BookmarksTestMixin(EventsTestMixin, UniqueCourseTest):
|
||||
"""
|
||||
Mixin with helper methods for testing Bookmarks.
|
||||
"""
|
||||
USERNAME = "STUDENT"
|
||||
EMAIL = "student@example.com"
|
||||
|
||||
def create_course_fixture(self, num_chapters):
|
||||
"""
|
||||
Create course fixture
|
||||
|
||||
Arguments:
|
||||
num_chapters: number of chapters to create
|
||||
"""
|
||||
self.course_fixture = CourseFixture( # pylint: disable=attribute-defined-outside-init
|
||||
self.course_info['org'], self.course_info['number'],
|
||||
self.course_info['run'], self.course_info['display_name']
|
||||
)
|
||||
|
||||
xblocks = []
|
||||
for index in range(num_chapters):
|
||||
xblocks += [
|
||||
XBlockFixtureDesc('chapter', 'TestSection{}'.format(index)).add_children(
|
||||
XBlockFixtureDesc('sequential', 'TestSubsection{}'.format(index)).add_children(
|
||||
XBlockFixtureDesc('vertical', 'TestVertical{}'.format(index))
|
||||
)
|
||||
)
|
||||
]
|
||||
self.course_fixture.add_children(*xblocks).install()
|
||||
|
||||
def verify_event_data(self, event_type, event_data):
|
||||
"""
|
||||
Verify emitted event data.
|
||||
|
||||
Arguments:
|
||||
event_type: expected event type
|
||||
event_data: expected event data
|
||||
"""
|
||||
actual_events = self.wait_for_events(event_filter={'event_type': event_type}, number_of_matches=1)
|
||||
self.assert_events_match(event_data, actual_events)
|
||||
|
||||
|
||||
class BookmarksTest(BookmarksTestMixin):
|
||||
"""
|
||||
Tests to verify bookmarks functionality.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Initialize test setup.
|
||||
"""
|
||||
super(BookmarksTest, self).setUp()
|
||||
|
||||
self.course_outline_page = CourseOutlinePage(
|
||||
self.browser,
|
||||
self.course_info['org'],
|
||||
self.course_info['number'],
|
||||
self.course_info['run']
|
||||
)
|
||||
|
||||
self.courseware_page = CoursewarePage(self.browser, self.course_id)
|
||||
self.bookmarks_page = BookmarksPage(self.browser, self.course_id)
|
||||
self.course_nav = CourseNavPage(self.browser)
|
||||
|
||||
# Get session to be used for bookmarking units
|
||||
self.session = requests.Session()
|
||||
params = {'username': self.USERNAME, 'email': self.EMAIL, 'course_id': self.course_id}
|
||||
response = self.session.get(BASE_URL + "/auto_auth", params=params)
|
||||
self.assertTrue(response.ok, "Failed to get session")
|
||||
|
||||
def _test_setup(self, num_chapters=2):
|
||||
"""
|
||||
Setup test settings.
|
||||
|
||||
Arguments:
|
||||
num_chapters: number of chapters to create in course
|
||||
"""
|
||||
self.create_course_fixture(num_chapters)
|
||||
|
||||
# Auto-auth register for the course.
|
||||
LmsAutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit()
|
||||
|
||||
self.courseware_page.visit()
|
||||
|
||||
def _bookmark_unit(self, location):
|
||||
"""
|
||||
Bookmark a unit
|
||||
|
||||
Arguments:
|
||||
location (str): unit location
|
||||
"""
|
||||
_headers = {
|
||||
'Content-type': 'application/json',
|
||||
'X-CSRFToken': self.session.cookies['csrftoken'],
|
||||
}
|
||||
params = {'course_id': self.course_id}
|
||||
data = json.dumps({'usage_id': location})
|
||||
response = self.session.post(
|
||||
BASE_URL + '/api/bookmarks/v1/bookmarks/',
|
||||
data=data,
|
||||
params=params,
|
||||
headers=_headers
|
||||
)
|
||||
self.assertTrue(response.ok, "Failed to bookmark unit")
|
||||
|
||||
def _bookmark_units(self, num_units):
|
||||
"""
|
||||
Bookmark first `num_units` units
|
||||
|
||||
Arguments:
|
||||
num_units(int): Number of units to bookmarks
|
||||
"""
|
||||
xblocks = self.course_fixture.get_nested_xblocks(category="vertical")
|
||||
for index in range(num_units):
|
||||
self._bookmark_unit(xblocks[index].locator)
|
||||
|
||||
def _breadcrumb(self, num_units, modified_name=None):
|
||||
"""
|
||||
Creates breadcrumbs for the first `num_units`
|
||||
|
||||
Arguments:
|
||||
num_units(int): Number of units for which we want to create breadcrumbs
|
||||
|
||||
Returns:
|
||||
list of breadcrumbs
|
||||
"""
|
||||
breadcrumbs = []
|
||||
for index in range(num_units):
|
||||
breadcrumbs.append(
|
||||
[
|
||||
'TestSection{}'.format(index),
|
||||
'TestSubsection{}'.format(index),
|
||||
modified_name if modified_name else 'TestVertical{}'.format(index)
|
||||
]
|
||||
)
|
||||
return breadcrumbs
|
||||
|
||||
def _delete_section(self, index):
|
||||
""" Delete a section at index `index` """
|
||||
|
||||
# Logout and login as staff
|
||||
LogoutPage(self.browser).visit()
|
||||
StudioAutoAuthPage(
|
||||
self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id, staff=True
|
||||
).visit()
|
||||
|
||||
# Visit course outline page in studio.
|
||||
self.course_outline_page.visit()
|
||||
self.course_outline_page.wait_for_page()
|
||||
|
||||
self.course_outline_page.section_at(index).delete()
|
||||
|
||||
# Logout and login as a student.
|
||||
LogoutPage(self.browser).visit()
|
||||
LmsAutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit()
|
||||
|
||||
# Visit courseware as a student.
|
||||
self.courseware_page.visit()
|
||||
self.courseware_page.wait_for_page()
|
||||
|
||||
def _toggle_bookmark_and_verify(self, bookmark_icon_state, bookmark_button_state, bookmarked_count):
|
||||
"""
|
||||
Bookmark/Un-Bookmark a unit and then verify
|
||||
"""
|
||||
self.assertTrue(self.courseware_page.bookmark_button_visible)
|
||||
self.courseware_page.click_bookmark_unit_button()
|
||||
self.assertEqual(self.courseware_page.bookmark_icon_visible, bookmark_icon_state)
|
||||
self.assertEqual(self.courseware_page.bookmark_button_state, bookmark_button_state)
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
self.assertEqual(self.bookmarks_page.count(), bookmarked_count)
|
||||
|
||||
def _verify_pagination_info(
|
||||
self,
|
||||
bookmark_count_on_current_page,
|
||||
header_text,
|
||||
previous_button_enabled,
|
||||
next_button_enabled,
|
||||
current_page_number,
|
||||
total_pages
|
||||
):
|
||||
"""
|
||||
Verify pagination info
|
||||
"""
|
||||
self.assertEqual(self.bookmarks_page.count(), bookmark_count_on_current_page)
|
||||
self.assertEqual(self.bookmarks_page.get_pagination_header_text(), header_text)
|
||||
self.assertEqual(self.bookmarks_page.is_previous_page_button_enabled(), previous_button_enabled)
|
||||
self.assertEqual(self.bookmarks_page.is_next_page_button_enabled(), next_button_enabled)
|
||||
self.assertEqual(self.bookmarks_page.get_current_page_number(), current_page_number)
|
||||
self.assertEqual(self.bookmarks_page.get_total_pages, total_pages)
|
||||
|
||||
def _navigate_to_bookmarks_list(self):
|
||||
"""
|
||||
Navigates and verifies the bookmarks list page.
|
||||
"""
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
self.assertTrue(self.bookmarks_page.results_present())
|
||||
self.assertEqual(self.bookmarks_page.results_header_text(), 'My Bookmarks')
|
||||
|
||||
def _verify_breadcrumbs(self, num_units, modified_name=None):
|
||||
"""
|
||||
Verifies the breadcrumb trail.
|
||||
"""
|
||||
bookmarked_breadcrumbs = self.bookmarks_page.breadcrumbs()
|
||||
|
||||
# Verify bookmarked breadcrumbs.
|
||||
breadcrumbs = self._breadcrumb(num_units=num_units, modified_name=modified_name)
|
||||
breadcrumbs.reverse()
|
||||
self.assertEqual(bookmarked_breadcrumbs, breadcrumbs)
|
||||
|
||||
def update_and_publish_block_display_name(self, modified_name):
|
||||
"""
|
||||
Update and publish the block/unit display name.
|
||||
"""
|
||||
self.course_outline_page.visit()
|
||||
self.course_outline_page.wait_for_page()
|
||||
|
||||
self.course_outline_page.expand_all_subsections()
|
||||
section = self.course_outline_page.section_at(0)
|
||||
container_page = section.subsection_at(0).unit_at(0).go_to()
|
||||
|
||||
self.course_fixture._update_xblock(container_page.locator, { # pylint: disable=protected-access
|
||||
"metadata": {
|
||||
"display_name": modified_name
|
||||
}
|
||||
})
|
||||
|
||||
container_page.visit()
|
||||
container_page.wait_for_page()
|
||||
|
||||
self.assertEqual(container_page.name, modified_name)
|
||||
container_page.publish_action.click()
|
||||
|
||||
def test_bookmark_button(self):
|
||||
"""
|
||||
Scenario: Bookmark unit button toggles correctly
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
For first 2 units
|
||||
I visit the unit
|
||||
And I can see the Bookmark button
|
||||
When I click on Bookmark button
|
||||
Then unit should be bookmarked
|
||||
Then I click again on the bookmark button
|
||||
And I should see a unit un-bookmarked
|
||||
"""
|
||||
self._test_setup()
|
||||
for index in range(2):
|
||||
self.course_nav.go_to_section('TestSection{}'.format(index), 'TestSubsection{}'.format(index))
|
||||
|
||||
self._toggle_bookmark_and_verify(True, 'bookmarked', 1)
|
||||
self.bookmarks_page.click_bookmarks_button(False)
|
||||
self._toggle_bookmark_and_verify(False, '', 0)
|
||||
|
||||
def test_empty_bookmarks_list(self):
|
||||
"""
|
||||
Scenario: An empty bookmarks list is shown if there are no bookmarked units.
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I can see the Bookmarks button
|
||||
When I click on Bookmarks button
|
||||
Then I should see an empty bookmarks list
|
||||
And empty bookmarks list content is correct
|
||||
"""
|
||||
self._test_setup()
|
||||
self.assertTrue(self.bookmarks_page.bookmarks_button_visible())
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
self.assertEqual(self.bookmarks_page.results_header_text(), 'My Bookmarks')
|
||||
self.assertEqual(self.bookmarks_page.empty_header_text(), 'You have not bookmarked any courseware pages yet.')
|
||||
|
||||
empty_list_text = ("Use bookmarks to help you easily return to courseware pages. To bookmark a page, "
|
||||
"select Bookmark in the upper right corner of that page. To see a list of all your "
|
||||
"bookmarks, select Bookmarks in the upper left corner of any courseware page.")
|
||||
self.assertEqual(self.bookmarks_page.empty_list_text(), empty_list_text)
|
||||
|
||||
def test_bookmarks_list(self):
|
||||
"""
|
||||
Scenario: A bookmarks list is shown if there are bookmarked units.
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I have bookmarked 2 units
|
||||
When I click on Bookmarks button
|
||||
Then I should see a bookmarked list with 2 bookmark links
|
||||
And breadcrumb trail is correct for a bookmark
|
||||
When I click on bookmarked link
|
||||
Then I can navigate to correct bookmarked unit
|
||||
"""
|
||||
self._test_setup()
|
||||
self._bookmark_units(2)
|
||||
|
||||
self._navigate_to_bookmarks_list()
|
||||
self._verify_breadcrumbs(num_units=2)
|
||||
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=2,
|
||||
header_text='Showing 1-2 out of 2 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=False,
|
||||
current_page_number=1,
|
||||
total_pages=1
|
||||
)
|
||||
|
||||
# get usage ids for units
|
||||
xblocks = self.course_fixture.get_nested_xblocks(category="vertical")
|
||||
xblock_usage_ids = [xblock.locator for xblock in xblocks]
|
||||
# Verify link navigation
|
||||
for index in range(2):
|
||||
self.bookmarks_page.click_bookmarked_block(index)
|
||||
self.courseware_page.wait_for_page()
|
||||
self.assertIn(self.courseware_page.active_usage_id(), xblock_usage_ids)
|
||||
self.courseware_page.visit().wait_for_page()
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
|
||||
def test_bookmark_shows_updated_breadcrumb_after_publish(self):
|
||||
"""
|
||||
Scenario: A bookmark breadcrumb trail is updated after publishing the changed display name.
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I can see bookmarked unit
|
||||
Then I visit unit page in studio
|
||||
Then I change unit display_name
|
||||
And I publish the changes
|
||||
Then I visit my courseware page
|
||||
And I visit bookmarks list page
|
||||
When I see the bookmark
|
||||
Then I can see the breadcrumb trail
|
||||
with updated display_name.
|
||||
"""
|
||||
self._test_setup(num_chapters=1)
|
||||
self._bookmark_units(num_units=1)
|
||||
|
||||
self._navigate_to_bookmarks_list()
|
||||
self._verify_breadcrumbs(num_units=1)
|
||||
|
||||
LogoutPage(self.browser).visit()
|
||||
LmsAutoAuthPage(
|
||||
self.browser,
|
||||
username=self.USERNAME,
|
||||
email=self.EMAIL,
|
||||
course_id=self.course_id,
|
||||
staff=True
|
||||
).visit()
|
||||
|
||||
modified_name = "Updated name"
|
||||
self.update_and_publish_block_display_name(modified_name)
|
||||
|
||||
LogoutPage(self.browser).visit()
|
||||
LmsAutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL, course_id=self.course_id).visit()
|
||||
self.courseware_page.visit()
|
||||
|
||||
self._navigate_to_bookmarks_list()
|
||||
self._verify_breadcrumbs(num_units=1, modified_name=modified_name)
|
||||
|
||||
def test_unreachable_bookmark(self):
|
||||
"""
|
||||
Scenario: We should get a HTTP 404 for an unreachable bookmark.
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I have bookmarked 2 units
|
||||
Then I delete a bookmarked unit
|
||||
Then I click on Bookmarks button
|
||||
And I should see a bookmarked list
|
||||
When I click on deleted bookmark
|
||||
Then I should navigated to 404 page
|
||||
"""
|
||||
self._test_setup(num_chapters=1)
|
||||
self._bookmark_units(1)
|
||||
self._delete_section(0)
|
||||
|
||||
self._navigate_to_bookmarks_list()
|
||||
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=1,
|
||||
header_text='Showing 1 out of 1 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=False,
|
||||
current_page_number=1,
|
||||
total_pages=1
|
||||
)
|
||||
|
||||
self.bookmarks_page.click_bookmarked_block(0)
|
||||
self.assertTrue(is_404_page(self.browser))
|
||||
|
||||
def test_page_size_limit(self):
|
||||
"""
|
||||
Scenario: We can't get bookmarks more than default page size.
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I have bookmarked all the 11 units available
|
||||
Then I click on Bookmarks button
|
||||
And I should see a bookmarked list
|
||||
And bookmark list contains 10 bookmarked items
|
||||
"""
|
||||
self._test_setup(11)
|
||||
self._bookmark_units(11)
|
||||
self._navigate_to_bookmarks_list()
|
||||
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=10,
|
||||
header_text='Showing 1-10 out of 11 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
def test_pagination_with_single_page(self):
|
||||
"""
|
||||
Scenario: Bookmarks list pagination is working as expected for single page
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I have bookmarked all the 2 units available
|
||||
Then I click on Bookmarks button
|
||||
And I should see a bookmarked list with 2 bookmarked items
|
||||
And I should see paging header and footer with correct data
|
||||
And previous and next buttons are disabled
|
||||
"""
|
||||
self._test_setup(num_chapters=2)
|
||||
self._bookmark_units(num_units=2)
|
||||
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
self.assertTrue(self.bookmarks_page.results_present())
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=2,
|
||||
header_text='Showing 1-2 out of 2 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=False,
|
||||
current_page_number=1,
|
||||
total_pages=1
|
||||
)
|
||||
|
||||
def test_next_page_button(self):
|
||||
"""
|
||||
Scenario: Next button is working as expected for bookmarks list pagination
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I have bookmarked all the 12 units available
|
||||
|
||||
Then I click on Bookmarks button
|
||||
And I should see a bookmarked list of 10 items
|
||||
And I should see paging header and footer with correct info
|
||||
|
||||
Then I click on next page button in footer
|
||||
And I should be navigated to second page
|
||||
And I should see a bookmarked list with 2 items
|
||||
And I should see paging header and footer with correct info
|
||||
"""
|
||||
self._test_setup(num_chapters=12)
|
||||
self._bookmark_units(num_units=12)
|
||||
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
self.assertTrue(self.bookmarks_page.results_present())
|
||||
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=10,
|
||||
header_text='Showing 1-10 out of 12 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
self.bookmarks_page.press_next_page_button()
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=2,
|
||||
header_text='Showing 11-12 out of 12 total',
|
||||
previous_button_enabled=True,
|
||||
next_button_enabled=False,
|
||||
current_page_number=2,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
def test_previous_page_button(self):
|
||||
"""
|
||||
Scenario: Previous button is working as expected for bookmarks list pagination
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I have bookmarked all the 12 units available
|
||||
And I click on Bookmarks button
|
||||
|
||||
Then I click on next page button in footer
|
||||
And I should be navigated to second page
|
||||
And I should see a bookmarked list with 2 items
|
||||
And I should see paging header and footer with correct info
|
||||
|
||||
Then I click on previous page button
|
||||
And I should be navigated to first page
|
||||
And I should see paging header and footer with correct info
|
||||
"""
|
||||
self._test_setup(num_chapters=12)
|
||||
self._bookmark_units(num_units=12)
|
||||
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
self.assertTrue(self.bookmarks_page.results_present())
|
||||
|
||||
self.bookmarks_page.press_next_page_button()
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=2,
|
||||
header_text='Showing 11-12 out of 12 total',
|
||||
previous_button_enabled=True,
|
||||
next_button_enabled=False,
|
||||
current_page_number=2,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
self.bookmarks_page.press_previous_page_button()
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=10,
|
||||
header_text='Showing 1-10 out of 12 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
def test_pagination_with_valid_page_number(self):
|
||||
"""
|
||||
Scenario: Bookmarks list pagination works as expected for valid page number
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I have bookmarked all the 12 units available
|
||||
|
||||
Then I click on Bookmarks button
|
||||
And I should see a bookmarked list
|
||||
And I should see total page value is 2
|
||||
Then I enter 2 in the page number input
|
||||
And I should be navigated to page 2
|
||||
"""
|
||||
self._test_setup(num_chapters=11)
|
||||
self._bookmark_units(num_units=11)
|
||||
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
self.assertTrue(self.bookmarks_page.results_present())
|
||||
self.assertEqual(self.bookmarks_page.get_total_pages, 2)
|
||||
|
||||
self.bookmarks_page.go_to_page(2)
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=1,
|
||||
header_text='Showing 11-11 out of 11 total',
|
||||
previous_button_enabled=True,
|
||||
next_button_enabled=False,
|
||||
current_page_number=2,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
def test_pagination_with_invalid_page_number(self):
|
||||
"""
|
||||
Scenario: Bookmarks list pagination works as expected for invalid page number
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I have bookmarked all the 11 units available
|
||||
Then I click on Bookmarks button
|
||||
And I should see a bookmarked list
|
||||
And I should see total page value is 2
|
||||
Then I enter 3 in the page number input
|
||||
And I should stay at page 1
|
||||
"""
|
||||
self._test_setup(num_chapters=11)
|
||||
self._bookmark_units(num_units=11)
|
||||
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
self.assertTrue(self.bookmarks_page.results_present())
|
||||
self.assertEqual(self.bookmarks_page.get_total_pages, 2)
|
||||
|
||||
self.bookmarks_page.go_to_page(3)
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=10,
|
||||
header_text='Showing 1-10 out of 11 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
def test_bookmarked_unit_accessed_event(self):
|
||||
"""
|
||||
Scenario: Bookmark events are emitted with correct data when we access/visit a bookmarked unit.
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
And I have bookmarked a unit
|
||||
When I click on bookmarked unit
|
||||
Then `edx.course.bookmark.accessed` event is emitted
|
||||
"""
|
||||
self._test_setup(num_chapters=1)
|
||||
self.reset_event_tracking()
|
||||
|
||||
# create expected event data
|
||||
xblocks = self.course_fixture.get_nested_xblocks(category="vertical")
|
||||
event_data = [
|
||||
{
|
||||
'event': {
|
||||
'bookmark_id': '{},{}'.format(self.USERNAME, xblocks[0].locator),
|
||||
'component_type': xblocks[0].category,
|
||||
'component_usage_id': xblocks[0].locator,
|
||||
}
|
||||
}
|
||||
]
|
||||
self._bookmark_units(num_units=1)
|
||||
self.bookmarks_page.click_bookmarks_button()
|
||||
|
||||
self._verify_pagination_info(
|
||||
bookmark_count_on_current_page=1,
|
||||
header_text='Showing 1 out of 1 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=False,
|
||||
current_page_number=1,
|
||||
total_pages=1
|
||||
)
|
||||
|
||||
self.bookmarks_page.click_bookmarked_block(0)
|
||||
self.verify_event_data('edx.bookmark.accessed', event_data)
|
||||
@@ -29,6 +29,7 @@ class CoursewareTest(UniqueCourseTest):
|
||||
super(CoursewareTest, self).setUp()
|
||||
|
||||
self.courseware_page = CoursewarePage(self.browser, self.course_id)
|
||||
self.course_nav = CourseNavPage(self.browser)
|
||||
|
||||
self.course_outline = CourseOutlinePage(
|
||||
self.browser,
|
||||
@@ -38,12 +39,12 @@ class CoursewareTest(UniqueCourseTest):
|
||||
)
|
||||
|
||||
# Install a course with sections/problems, tabs, updates, and handouts
|
||||
course_fix = CourseFixture(
|
||||
self.course_fix = CourseFixture(
|
||||
self.course_info['org'], self.course_info['number'],
|
||||
self.course_info['run'], self.course_info['display_name']
|
||||
)
|
||||
|
||||
course_fix.add_children(
|
||||
self.course_fix.add_children(
|
||||
XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
|
||||
XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children(
|
||||
XBlockFixtureDesc('problem', 'Test Problem 1')
|
||||
@@ -67,6 +68,10 @@ class CoursewareTest(UniqueCourseTest):
|
||||
self.problem_page = ProblemPage(self.browser)
|
||||
self.assertEqual(self.problem_page.problem_name, 'TEST PROBLEM 1')
|
||||
|
||||
def _create_breadcrumb(self, index):
|
||||
""" Create breadcrumb """
|
||||
return ['Test Section {}'.format(index), 'Test Subsection {}'.format(index), 'Test Problem {}'.format(index)]
|
||||
|
||||
def _auto_auth(self, username, email, staff):
|
||||
"""
|
||||
Logout and login with given credentials.
|
||||
@@ -101,6 +106,23 @@ class CoursewareTest(UniqueCourseTest):
|
||||
# Problem name should be "TEST PROBLEM 2".
|
||||
self.assertEqual(self.problem_page.problem_name, 'TEST PROBLEM 2')
|
||||
|
||||
def test_course_tree_breadcrumb(self):
|
||||
"""
|
||||
Scenario: Correct course tree breadcrumb is shown.
|
||||
|
||||
Given that I am a registered user
|
||||
And I visit my courseware page
|
||||
Then I should see correct course tree breadcrumb
|
||||
"""
|
||||
self.courseware_page.visit()
|
||||
|
||||
xblocks = self.course_fix.get_nested_xblocks(category="problem")
|
||||
for index in range(1, len(xblocks) + 1):
|
||||
self.course_nav.go_to_section('Test Section {}'.format(index), 'Test Subsection {}'.format(index))
|
||||
courseware_page_breadcrumb = self.courseware_page.breadcrumb
|
||||
expected_breadcrumb = self._create_breadcrumb(index) # pylint: disable=no-member
|
||||
self.assertEqual(courseware_page_breadcrumb, expected_breadcrumb)
|
||||
|
||||
|
||||
class ProctoredExamTest(UniqueCourseTest):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user