Bok choy acceptance tests
This commit is contained in:
@@ -35,8 +35,10 @@ def enum(**enums):
|
||||
|
||||
|
||||
def _get_capa_types():
|
||||
"""
|
||||
Gets capa types tags and labels
|
||||
"""
|
||||
capa_types = {
|
||||
ANY_CAPA_TYPE_VALUE: _('Any Type'),
|
||||
'annotationinput': _('Annotation'),
|
||||
'checkboxgroup': _('Checkbox Group'),
|
||||
'checkboxtextgroup': _('Checkbox Text Group'),
|
||||
@@ -54,7 +56,7 @@ def _get_capa_types():
|
||||
'javascriptinput': _('Javascript Input'),
|
||||
'jsinput': _('JS Input'),
|
||||
'matlabinput': _('Matlab'),
|
||||
'optioninput': _('Select option'),
|
||||
'optioninput': _('Select Option'),
|
||||
'radiogroup': _('Radio Group'),
|
||||
'radiotextgroup': _('Radio Text Group'),
|
||||
'schematic': _('Schematic'),
|
||||
@@ -63,7 +65,7 @@ def _get_capa_types():
|
||||
'vsepr_input': _('VSEPR'),
|
||||
}
|
||||
|
||||
return sorted([
|
||||
return [{'value': ANY_CAPA_TYPE_VALUE, 'display_name': _('Any Type')}] + sorted([
|
||||
{'value': capa_type, 'display_name': caption}
|
||||
for capa_type, caption in capa_types.items()
|
||||
], key=lambda item: item.get('display_name'))
|
||||
@@ -221,6 +223,9 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
|
||||
any particular student.
|
||||
"""
|
||||
def _filter_children(self, child_locator):
|
||||
"""
|
||||
Filters children by CAPA problem type, if configured
|
||||
"""
|
||||
if self.capa_type == ANY_CAPA_TYPE_VALUE:
|
||||
return True
|
||||
|
||||
@@ -234,7 +239,6 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
|
||||
|
||||
return any(self.capa_type in capa_input.tags for capa_input in block.lcp.inputs.values())
|
||||
|
||||
|
||||
def selected_children(self):
|
||||
"""
|
||||
Returns a set() of block_ids indicating which of the possible children
|
||||
@@ -427,8 +431,8 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe
|
||||
If source_libraries has been edited, refresh_children automatically.
|
||||
"""
|
||||
old_source_libraries = LibraryList().from_json(old_metadata.get('source_libraries', []))
|
||||
if (set(old_source_libraries) != set(self.source_libraries) or
|
||||
old_metadata.get('capa_type', ANY_CAPA_TYPE_VALUE) != self.capa_type):
|
||||
if set(old_source_libraries) != set(self.source_libraries) or \
|
||||
old_metadata.get('capa_type', ANY_CAPA_TYPE_VALUE) != self.capa_type:
|
||||
try:
|
||||
self.refresh_children(None, None, update_db=False) # update_db=False since update_item() is about to be called anyways
|
||||
except ValueError:
|
||||
|
||||
@@ -16,6 +16,9 @@ class LibraryContentXBlockWrapper(PageObject):
|
||||
self.locator = locator
|
||||
|
||||
def is_browser_on_page(self):
|
||||
"""
|
||||
Checks if page is opened
|
||||
"""
|
||||
return self.q(css='{}[data-id="{}"]'.format(self.BODY_SELECTOR, self.locator)).present
|
||||
|
||||
def _bounded_selector(self, selector):
|
||||
@@ -35,3 +38,11 @@ class LibraryContentXBlockWrapper(PageObject):
|
||||
"""
|
||||
child_blocks = self.q(css=self._bounded_selector("div[data-id]"))
|
||||
return frozenset(child.text for child in child_blocks)
|
||||
|
||||
@property
|
||||
def children_headers(self):
|
||||
"""
|
||||
Gets headers if all child XBlocks as list of strings
|
||||
"""
|
||||
child_blocks_headers = self.q(css=self._bounded_selector("div[data-id] h2.problem-header"))
|
||||
return frozenset(child.text for child in child_blocks_headers)
|
||||
|
||||
@@ -122,6 +122,7 @@ class StudioLibraryContentXBlockEditModal(CourseOutlineModal, PageObject):
|
||||
LIBRARY_LABEL = "Libraries"
|
||||
COUNT_LABEL = "Count"
|
||||
SCORED_LABEL = "Scored"
|
||||
PROBLEM_TYPE_LABEL = "Problem Type"
|
||||
|
||||
def is_browser_on_page(self):
|
||||
"""
|
||||
@@ -196,6 +197,24 @@ class StudioLibraryContentXBlockEditModal(CourseOutlineModal, PageObject):
|
||||
scored_select.select_by_value(str(scored))
|
||||
EmptyPromise(lambda: self.scored == scored, "scored is updated in modal.").fulfill()
|
||||
|
||||
@property
|
||||
def capa_type(self):
|
||||
"""
|
||||
Gets value of CAPA type select
|
||||
"""
|
||||
return self.get_metadata_input(self.PROBLEM_TYPE_LABEL).get_attribute('value')
|
||||
|
||||
@capa_type.setter
|
||||
def capa_type(self, value):
|
||||
"""
|
||||
Sets value of CAPA type select
|
||||
"""
|
||||
select_element = self.get_metadata_input(self.PROBLEM_TYPE_LABEL)
|
||||
select_element.click()
|
||||
problem_type_select = Select(select_element)
|
||||
problem_type_select.select_by_value(value)
|
||||
EmptyPromise(lambda: self.capa_type == value, "problem type is updated in modal.").fulfill()
|
||||
|
||||
def _add_library_key(self):
|
||||
"""
|
||||
Adds library key input
|
||||
|
||||
@@ -19,22 +19,22 @@ SUBSECTION_NAME = 'Test Subsection'
|
||||
UNIT_NAME = 'Test Unit'
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class LibraryContentTest(UniqueCourseTest):
|
||||
"""
|
||||
Test courseware.
|
||||
"""
|
||||
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"
|
||||
|
||||
def populate_library_fixture(self, library_fixture):
|
||||
pass
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up library, course and library content XBlock
|
||||
"""
|
||||
super(LibraryContentTest, self).setUp()
|
||||
super(LibraryContentTestBase, self).setUp()
|
||||
|
||||
self.courseware_page = CoursewarePage(self.browser, self.course_id)
|
||||
|
||||
@@ -46,11 +46,7 @@ class LibraryContentTest(UniqueCourseTest):
|
||||
)
|
||||
|
||||
self.library_fixture = LibraryFixture('test_org', self.unique_id, 'Test Library {}'.format(self.unique_id))
|
||||
self.library_fixture.add_children(
|
||||
XBlockFixtureDesc("html", "Html1", data='html1'),
|
||||
XBlockFixtureDesc("html", "Html2", data='html2'),
|
||||
XBlockFixtureDesc("html", "Html3", data='html3'),
|
||||
)
|
||||
self.populate_library_fixture(self.library_fixture)
|
||||
|
||||
self.library_fixture.install()
|
||||
self.library_info = self.library_fixture.library_info
|
||||
@@ -83,7 +79,7 @@ class LibraryContentTest(UniqueCourseTest):
|
||||
|
||||
self.course_fixture.install()
|
||||
|
||||
def _refresh_library_content_children(self, count=1):
|
||||
def _change_library_content_settings(self, count=1, capa_type=None):
|
||||
"""
|
||||
Performs library block refresh in Studio, configuring it to show {count} children
|
||||
"""
|
||||
@@ -91,6 +87,8 @@ class LibraryContentTest(UniqueCourseTest):
|
||||
library_container_block = StudioLibraryContainerXBlockWrapper.from_xblock_wrapper(unit_page.xblocks[0])
|
||||
modal = StudioLibraryContentXBlockEditModal(library_container_block.edit())
|
||||
modal.count = count
|
||||
if capa_type is not None:
|
||||
modal.capa_type = capa_type
|
||||
library_container_block.save_settings()
|
||||
self._go_to_unit_page(change_login=False)
|
||||
unit_page.wait_for_page()
|
||||
@@ -124,6 +122,7 @@ class LibraryContentTest(UniqueCourseTest):
|
||||
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):
|
||||
"""
|
||||
@@ -132,6 +131,22 @@ class LibraryContentTest(UniqueCourseTest):
|
||||
AutoAuthPage(self.browser, username=username, email=email,
|
||||
course_id=self.course_id, staff=staff).visit()
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class LibraryContentTest(LibraryContentTestBase):
|
||||
"""
|
||||
Test courseware.
|
||||
"""
|
||||
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'),
|
||||
)
|
||||
|
||||
@ddt.data(1, 2, 3)
|
||||
def test_shows_random_xblocks_from_configured(self, count):
|
||||
"""
|
||||
@@ -143,7 +158,7 @@ class LibraryContentTest(UniqueCourseTest):
|
||||
When I go to LMS courseware page for library content xblock as student
|
||||
Then I can see {count} random xblocks from the library
|
||||
"""
|
||||
self._refresh_library_content_children(count=count)
|
||||
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
|
||||
@@ -160,9 +175,128 @@ class LibraryContentTest(UniqueCourseTest):
|
||||
When I go to LMS courseware page for library content xblock as student
|
||||
Then I can see all xblocks from the library
|
||||
"""
|
||||
self._refresh_library_content_children(count=10)
|
||||
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), 3)
|
||||
self.assertEqual(children_contents, self.library_xblocks_texts)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class StudioLibraryContainerCapaFilterTest(LibraryContentTestBase):
|
||||
"""
|
||||
Test Library Content block in LMS
|
||||
"""
|
||||
def _get_problem_choice_group_text(self, name, items):
|
||||
""" Generates Choice Group CAPA problem XML """
|
||||
items_text = "\n".join([
|
||||
"<choice correct='{correct}'>{item}</choice>".format(correct=correct, item=item)
|
||||
for item, correct in items
|
||||
])
|
||||
|
||||
return """<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(map(lambda item: "'{0}'".format(item), items))
|
||||
|
||||
return """<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
|
||||
"""
|
||||
library_fixture.add_children(
|
||||
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")
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def _problem_headers(self):
|
||||
""" Expected XBLock headers according to populate_library_fixture """
|
||||
return frozenset(child.display_name.upper() for child in self.library_fixture.children)
|
||||
|
||||
@ddt.data(1, 3)
|
||||
def test_any_capa_type_shows_all(self, count):
|
||||
"""
|
||||
Scenario: Ensure setting "Any Type" for Problem Type does not filter out Problems
|
||||
Given I have a library with two "Select Option" and two "Choice Group" problems, and a course containing
|
||||
LibraryContent XBlock configured to draw XBlocks from that library
|
||||
When I go to studio unit page for library content xblock as staff
|
||||
And I set library content xblock Problem Type to "Any Type" and Count to {count}
|
||||
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} xblocks from the library of any type
|
||||
"""
|
||||
self._change_library_content_settings(count=count, capa_type="Any Type")
|
||||
self._auto_auth(self.USERNAME, self.EMAIL, False)
|
||||
self._goto_library_block_page()
|
||||
children_headers = self.library_content_page.children_headers
|
||||
self.assertEqual(len(children_headers), count)
|
||||
self.assertLessEqual(children_headers, self._problem_headers)
|
||||
|
||||
@ddt.data(
|
||||
('Choice Group', 1, ["Problem Choice Group 1", "Problem Choice Group 2"]),
|
||||
('Select Option', 2, ["Problem Select 1", "Problem Select 2"]),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_capa_type_shows_only_chosen_type(self, capa_type, count, expected_headers):
|
||||
"""
|
||||
Scenario: Ensure setting "{capa_type}" for Problem Type draws aonly problem of {capa_type} from library
|
||||
Given I have a library with two "Select Option" and two "Choice Group" problems, and a course containing
|
||||
LibraryContent XBlock configured to draw XBlocks from that library
|
||||
When I go to studio unit page for library content xblock as staff
|
||||
And I set library content xblock Problem Type to "{capa_type}" and Count to {count}
|
||||
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} xblocks from the library of {capa_type}
|
||||
"""
|
||||
self._change_library_content_settings(count=count, capa_type=capa_type)
|
||||
self._auto_auth(self.USERNAME, self.EMAIL, False)
|
||||
self._goto_library_block_page()
|
||||
children_headers = self.library_content_page.children_headers
|
||||
self.assertEqual(len(children_headers), count)
|
||||
self.assertLessEqual(children_headers, self._problem_headers)
|
||||
self.assertLessEqual(children_headers, set(map(lambda header: header.upper(), expected_headers)))
|
||||
|
||||
def test_missing_capa_type_shows_none(self):
|
||||
"""
|
||||
Scenario: Ensure setting "{capa_type}" for Problem Type that is not present in library results in empty XBlock
|
||||
Given I have a library with two "Select Option" and two "Choice Group" problems, and a course containing
|
||||
LibraryContent XBlock configured to draw XBlocks from that library
|
||||
When I go to studio unit page for library content xblock as staff
|
||||
And I set library content xblock Problem Type to type not present in library
|
||||
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 no xblocks
|
||||
"""
|
||||
self._change_library_content_settings(count=1, capa_type="Matlab")
|
||||
self._auto_auth(self.USERNAME, self.EMAIL, False)
|
||||
self._goto_library_block_page()
|
||||
children_headers = self.library_content_page.children_headers
|
||||
self.assertEqual(len(children_headers), 0)
|
||||
|
||||
Reference in New Issue
Block a user