Files
edx-platform/common/test/acceptance/tests/lms/test_library.py
Feanil Patel 9cf2f9f298 Run 2to3 -f future . -w
This will remove imports from __future__ that are no longer needed.

https://docs.python.org/3.5/library/2to3.html#2to3fixer-future
2019-12-30 10:35:30 -05:00

285 lines
11 KiB
Python

# -*- coding: utf-8 -*-
"""
End-to-end tests for LibraryContent block in LMS
"""
import textwrap
import ddt
import six
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
from common.test.acceptance.fixtures.library import LibraryFixture
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
from common.test.acceptance.pages.common.logout import LogoutPage
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.library import LibraryContentXBlockWrapper
from common.test.acceptance.pages.studio.library import StudioLibraryContainerXBlockWrapper, StudioLibraryContentEditor
from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from common.test.acceptance.tests.helpers import TestWithSearchIndexMixin, UniqueCourseTest
SECTION_NAME = 'Test Section'
SUBSECTION_NAME = 'Test Subsection'
UNIT_NAME = 'Test Unit'
class LibraryContentTestBase(UniqueCourseTest):
""" Base class for library content block tests """
USERNAME = "STUDENT_TESTER"
EMAIL = "student101@example.com"
STAFF_USERNAME = "STAFF_TESTER"
STAFF_EMAIL = "staff101@example.com"
shard = 10
def populate_library_fixture(self, library_fixture):
"""
To be overwritten by subclassed tests. Used to install a library to
run tests on.
"""
def setUp(self):
"""
Set up library, course and library content XBlock
"""
super(LibraryContentTestBase, self).setUp()
self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.studio_course_outline = StudioCourseOutlinePage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
self.library_fixture = LibraryFixture('test_org', self.unique_id, u'Test Library {}'.format(self.unique_id))
self.populate_library_fixture(self.library_fixture)
self.library_fixture.install()
self.library_info = self.library_fixture.library_info
self.library_key = self.library_fixture.library_key
# Install a course with library content xblock
self.course_fixture = CourseFixture(
self.course_info['org'], self.course_info['number'],
self.course_info['run'], self.course_info['display_name']
)
library_content_metadata = {
'source_library_id': six.text_type(self.library_key),
'mode': 'random',
'max_count': 1,
}
self.lib_block = XBlockFixtureDesc('library_content', "Library Content", metadata=library_content_metadata)
self.course_fixture.add_children(
XBlockFixtureDesc('chapter', SECTION_NAME).add_children(
XBlockFixtureDesc('sequential', SUBSECTION_NAME).add_children(
XBlockFixtureDesc('vertical', UNIT_NAME).add_children(
self.lib_block
)
)
)
)
self.course_fixture.install()
def _change_library_content_settings(self, count=1, capa_type=None):
"""
Performs library block refresh in Studio, configuring it to show {count} children
"""
unit_page = self._go_to_unit_page(True)
library_container_block = StudioLibraryContainerXBlockWrapper.from_xblock_wrapper(unit_page.xblocks[1])
library_container_block.edit()
editor = StudioLibraryContentEditor(self.browser, library_container_block.locator)
editor.count = count
if capa_type is not None:
editor.capa_type = capa_type
editor.save()
self._go_to_unit_page(change_login=False)
unit_page.wait_for_page()
unit_page.publish()
self.assertIn("Published and Live", unit_page.publish_title)
@property
def library_xblocks_texts(self):
"""
Gets texts of all xblocks in library
"""
return frozenset(child.data for child in self.library_fixture.children)
def _go_to_unit_page(self, change_login=True):
"""
Open unit page in Studio
"""
if change_login:
LogoutPage(self.browser).visit()
self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True)
self.studio_course_outline.visit()
subsection = self.studio_course_outline.section(SECTION_NAME).subsection(SUBSECTION_NAME)
return subsection.expand_subsection().unit(UNIT_NAME).go_to()
def _goto_library_block_page(self, block_id=None):
"""
Open library page in LMS
"""
self.courseware_page.visit()
paragraphs = self.courseware_page.q(css='.course-content p').results
if not paragraphs:
course_home_page = CourseHomePage(self.browser, self.course_id)
course_home_page.visit()
course_home_page.outline.go_to_section_by_index(0, 0)
block_id = block_id if block_id is not None else self.lib_block.locator
#pylint: disable=attribute-defined-outside-init
self.library_content_page = LibraryContentXBlockWrapper(self.browser, block_id)
self.library_content_page.wait_for_page()
def _auto_auth(self, username, email, staff):
"""
Logout and login with given credentials.
"""
AutoAuthPage(self.browser, username=username, email=email,
course_id=self.course_id, staff=staff).visit()
@ddt.ddt
class LibraryContentTest(LibraryContentTestBase):
"""
Test courseware.
"""
shard = 10
def populate_library_fixture(self, library_fixture):
"""
Populates library fixture with XBlock Fixtures
"""
library_fixture.add_children(
XBlockFixtureDesc("html", "Html1", data='html1'),
XBlockFixtureDesc("html", "Html2", data='html2'),
XBlockFixtureDesc("html", "Html3", data='html3'),
XBlockFixtureDesc("html", "Html4", data='html4'),
)
@ddt.data(2, 3, 4)
def test_shows_random_xblocks_from_configured(self, count):
"""
Scenario: Ensures that library content shows {count} random xblocks from library in LMS
Given I have a library, a course and a LibraryContent block in that course
When I go to studio unit page for library content xblock as staff
And I set library content xblock to display {count} random children
And I refresh library content xblock and pulbish unit
When I go to LMS courseware page for library content xblock as student
Then I can see {count} random xblocks from the library
"""
self._change_library_content_settings(count=count)
self._auto_auth(self.USERNAME, self.EMAIL, False)
self._goto_library_block_page()
children_contents = self.library_content_page.children_contents
self.assertEqual(len(children_contents), count)
self.assertLessEqual(children_contents, self.library_xblocks_texts)
def test_shows_all_if_max_set_to_greater_value(self):
"""
Scenario: Ensures that library content shows {count} random xblocks from library in LMS
Given I have a library, a course and a LibraryContent block in that course
When I go to studio unit page for library content xblock as staff
And I set library content xblock to display more children than library have
And I refresh library content xblock and pulbish unit
When I go to LMS courseware page for library content xblock as student
Then I can see all xblocks from the library
"""
self._change_library_content_settings(count=10)
self._auto_auth(self.USERNAME, self.EMAIL, False)
self._goto_library_block_page()
children_contents = self.library_content_page.children_contents
self.assertEqual(len(children_contents), 4)
self.assertEqual(children_contents, self.library_xblocks_texts)
@ddt.ddt
class StudioLibraryContainerCapaFilterTest(LibraryContentTestBase, TestWithSearchIndexMixin):
"""
Test Library Content block in LMS
"""
shard = 10
def setUp(self):
""" SetUp method """
self._create_search_index()
super(StudioLibraryContainerCapaFilterTest, self).setUp()
def tearDown(self):
self._cleanup_index_file()
super(StudioLibraryContainerCapaFilterTest, self).tearDown()
def _get_problem_choice_group_text(self, name, items):
""" Generates Choice Group CAPA problem XML """
items_text = "\n".join([
u"<choice correct='{correct}'>{item}</choice>".format(correct=correct, item=item)
for item, correct in items
])
return textwrap.dedent(u"""
<problem>
<p>{name}</p>
<multiplechoiceresponse>
<choicegroup label="{name}" type="MultipleChoice">{items}</choicegroup>
</multiplechoiceresponse>
</problem>""").format(name=name, items=items_text)
def _get_problem_select_text(self, name, items, correct):
""" Generates Select Option CAPA problem XML """
items_text = ",".join(["'{0}'".format(item) for item in items])
return textwrap.dedent(u"""
<problem>
<p>{name}</p>
<optionresponse>
<optioninput label="{name}" options="({options})" correct="{correct}"></optioninput>
</optionresponse>
</problem>""").format(name=name, options=items_text, correct=correct)
def populate_library_fixture(self, library_fixture):
"""
Populates library fixture with XBlock Fixtures
"""
items = (
XBlockFixtureDesc(
"problem", "Problem Choice Group 1",
data=self._get_problem_choice_group_text("Problem Choice Group 1 Text", [("1", False), ('2', True)])
),
XBlockFixtureDesc(
"problem", "Problem Choice Group 2",
data=self._get_problem_choice_group_text("Problem Choice Group 2 Text", [("Q", True), ('W', False)])
),
XBlockFixtureDesc(
"problem", "Problem Select 1",
data=self._get_problem_select_text("Problem Select 1 Text", ["Option 1", "Option 2"], "Option 1")
),
XBlockFixtureDesc(
"problem", "Problem Select 2",
data=self._get_problem_select_text("Problem Select 2 Text", ["Option 3", "Option 4"], "Option 4")
),
)
library_fixture.add_children(*items)
@property
def _problem_headers(self):
""" Expected XBLock headers according to populate_library_fixture """
return frozenset(child.display_name for child in self.library_fixture.children)
def _set_library_content_settings(self, count=1, capa_type="Any Type"):
"""
Sets library content XBlock parameters, saves, publishes unit, goes to LMS unit page and
gets children XBlock headers to assert against them
"""
self._change_library_content_settings(count=count, capa_type=capa_type)
self._auto_auth(self.USERNAME, self.EMAIL, False)
self._goto_library_block_page()
return self.library_content_page.children_headers