Commit 7338cc12 by Xavier Antoviaque

Merge pull request #7148 from open-craft/library-selector

Show a select box when editing a library content block (SOL-123)
parents 41f08055 2e0beac3
......@@ -13,7 +13,6 @@ from student.roles import (
OrgStaffRole, OrgInstructorRole, OrgLibraryUserRole,
)
from xblock.reference.user_service import XBlockUser
from xmodule.library_content_module import LibraryVersionReference
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
......@@ -64,7 +63,7 @@ class LibraryTestCase(ModuleStoreTestCase):
parent_location=course.location,
user_id=self.user.id,
publish_item=False,
source_libraries=[LibraryVersionReference(library_key)],
source_library_id=unicode(library_key),
**(other_settings or {})
)
......@@ -333,7 +332,7 @@ class TestLibraries(LibraryTestCase):
# Now, change the block settings to have an invalid library key:
resp = self._update_item(
lc_block.location,
{"source_libraries": [["library-v1:NOT+FOUND", None]]},
{"source_library_id": "library-v1:NOT+FOUND"},
)
self.assertEqual(resp.status_code, 200)
lc_block = modulestore().get_item(lc_block.location)
......@@ -376,7 +375,7 @@ class TestLibraries(LibraryTestCase):
# Now, change the block settings to have an invalid library key:
resp = self._update_item(
lc_block.location,
{"source_libraries": [[str(library2key)]]},
{"source_library_id": str(library2key)},
)
self.assertEqual(resp.status_code, 200)
lc_block = modulestore().get_item(lc_block.location)
......@@ -450,7 +449,7 @@ class TestLibraries(LibraryTestCase):
# Now, change the block settings to have an invalid library key:
resp = self._update_item(
lc_block.location,
{"source_libraries": [["library-v1:NOT+FOUND", None]]},
{"source_library_id": "library-v1:NOT+FOUND"},
)
self.assertEqual(resp.status_code, 200)
with self.assertRaises(ValueError):
......
......@@ -72,23 +72,13 @@ from django.utils.translation import ugettext as _
</div>
</article>
<aside class="content-supplementary" role="complementary">
<div class="library-location">
<h4 class="bar-mod-title">${_("Library ID")}</h4>
<div class="wrapper-library-id bar-mod-content">
<h5 class="title">${_("Library ID")}</h5>
<p class="library-id">
<span class="library-id-value">${context_library.location.library_key | h}</span>
<span class="tip"><span class="sr">${_("Tip:")}</span> ${_("To add content from this library to a course that uses a Randomized Content Block, copy this ID and enter it in the Libraries field in the Randomized Content Block settings.")}</span>
</p>
</div>
</div>
% if can_edit:
<div class="bit">
<h3 class="title-3">${_("Adding content to your library")}</h3>
<p>${_("Add components to your library for use in courses, using Add New Component at the bottom of this page.")}</p>
<p>${_("Components are listed in the order in which they are added, with the most recently added at the bottom. Use the pagination arrows to navigate from page to page if you have more than one page of components in your library.")}</p>
<h3 class="title-3">${_("Using library content in courses")}</h3>
<p>${_("Use library content in courses by adding the {em_start}library_content{em_end} policy key to Advanced Settings, then adding a Randomized Content Block to your courseware. In the settings for each Randomized Content Block, enter the Library ID for each library from which you want to draw content, and specify the number of problems to be randomly selected and displayed to each student.").format(em_start='<strong>', em_end="</strong>")}</p>
<p>${_("Use library content in courses by adding the {em_start}library_content{em_end} policy key to the Advanced Module List in the course's Advanced Settings, then adding a Randomized Content Block to your courseware. In the settings for each Randomized Content Block, select this library as the source library, and specify the number of problems to be randomly selected and displayed to each student.").format(em_start='<strong>', em_end="</strong>")}</p>
</div>
% endif
<div class="bit external-help">
......
......@@ -3,7 +3,7 @@ XBlock runtime services for LibraryContentModule
"""
from django.core.exceptions import PermissionDenied
from opaque_keys.edx.locator import LibraryLocator
from xmodule.library_content_module import LibraryVersionReference, ANY_CAPA_TYPE_VALUE
from xmodule.library_content_module import ANY_CAPA_TYPE_VALUE
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.capa_module import CapaDescriptor
......@@ -104,38 +104,50 @@ class LibraryToolsService(object):
def update_children(self, dest_block, user_id, user_perms=None):
"""
This method is to be used when any of the libraries that a LibraryContentModule
references have been updated. It will re-fetch all matching blocks from
This method is to be used when the library that a LibraryContentModule
references has been updated. It will re-fetch all matching blocks from
the libraries, and copy them as children of dest_block. The children
will be given new block_ids, but the definition ID used should be the
exact same definition ID used in the library.
This method will update dest_block's 'source_libraries' field to store
the version number of the libraries used, so we easily determine if
dest_block is up to date or not.
This method will update dest_block's 'source_library_version' field to
store the version number of the libraries used, so we easily determine
if dest_block is up to date or not.
"""
if user_perms and not user_perms.can_write(dest_block.location.course_key):
raise PermissionDenied()
new_libraries = []
if not dest_block.source_library_id:
dest_block.source_library_version = ""
return
source_blocks = []
for library_key, __ in dest_block.source_libraries:
library = self._get_library(library_key)
if library is None:
raise ValueError("Required library not found.")
if user_perms and not user_perms.can_read(library_key):
raise PermissionDenied()
filter_children = (dest_block.capa_type != ANY_CAPA_TYPE_VALUE)
if filter_children:
# Apply simple filtering based on CAPA problem types:
source_blocks.extend([key for key in library.children if self._filter_child(key, dest_block.capa_type)])
else:
source_blocks.extend(library.children)
new_libraries.append(LibraryVersionReference(library_key, library.location.library_key.version_guid))
library_key = dest_block.source_library_key
library = self._get_library(library_key)
if library is None:
raise ValueError("Requested library not found.")
if user_perms and not user_perms.can_read(library_key):
raise PermissionDenied()
filter_children = (dest_block.capa_type != ANY_CAPA_TYPE_VALUE)
if filter_children:
# Apply simple filtering based on CAPA problem types:
source_blocks.extend([key for key in library.children if self._filter_child(key, dest_block.capa_type)])
else:
source_blocks.extend(library.children)
with self.store.bulk_operations(dest_block.location.course_key):
dest_block.source_libraries = new_libraries
dest_block.source_library_version = unicode(library.location.library_key.version_guid)
self.store.update_item(dest_block, user_id)
dest_block.children = self.store.copy_from_template(source_blocks, dest_block.location, user_id)
# ^-- copy_from_template updates the children in the DB
# but we must also set .children here to avoid overwriting the DB again
def list_available_libraries(self):
"""
List all known libraries.
Returns tuples of (LibraryLocator, display_name)
"""
return [
(lib.location.library_key.replace(version_guid=None, branch=None), lib.display_name)
for lib in self.store.get_libraries()
]
......@@ -6,15 +6,11 @@ Higher-level tests are in `cms/djangoapps/contentstore/tests/test_libraries.py`.
"""
from bson.objectid import ObjectId
from mock import Mock, patch
from opaque_keys.edx.locator import LibraryLocator
from unittest import TestCase
from xblock.fragment import Fragment
from xblock.runtime import Runtime as VanillaRuntime
from xmodule.library_content_module import (
LibraryVersionReference, LibraryList, ANY_CAPA_TYPE_VALUE, LibraryContentDescriptor
)
from xmodule.library_content_module import ANY_CAPA_TYPE_VALUE, LibraryContentDescriptor
from xmodule.library_tools import LibraryToolsService
from xmodule.modulestore.tests.factories import LibraryFactory, CourseFactory
from xmodule.modulestore.tests.utils import MixedSplitTestCase
......@@ -46,7 +42,7 @@ class LibraryContentTest(MixedSplitTestCase):
"library_content",
self.vertical,
max_count=1,
source_libraries=[LibraryVersionReference(self.library.location.library_key)]
source_library_id=unicode(self.library.location.library_key)
)
def _bind_course_module(self, module):
......@@ -128,25 +124,25 @@ class TestLibraryContentModule(LibraryContentTest):
def test_validation_of_course_libraries(self):
"""
Test that the validation method of LibraryContent blocks can validate
the source_libraries setting.
the source_library setting.
"""
# When source_libraries is blank, the validation summary should say this block needs to be configured:
self.lc_block.source_libraries = []
# When source_library_id is blank, the validation summary should say this block needs to be configured:
self.lc_block.source_library_id = ""
result = self.lc_block.validate()
self.assertFalse(result) # Validation fails due to at least one warning/message
self.assertTrue(result.summary)
self.assertEqual(StudioValidationMessage.NOT_CONFIGURED, result.summary.type)
# When source_libraries references a non-existent library, we should get an error:
self.lc_block.source_libraries = [LibraryVersionReference("library-v1:BAD+WOLF")]
# When source_library_id references a non-existent library, we should get an error:
self.lc_block.source_library_id = "library-v1:BAD+WOLF"
result = self.lc_block.validate()
self.assertFalse(result) # Validation fails due to at least one warning/message
self.assertTrue(result.summary)
self.assertEqual(StudioValidationMessage.ERROR, result.summary.type)
self.assertIn("invalid", result.summary.text)
# When source_libraries is set but the block needs to be updated, the summary should say so:
self.lc_block.source_libraries = [LibraryVersionReference(self.library.location.library_key)]
# When source_library_id is set but the block needs to be updated, the summary should say so:
self.lc_block.source_library_id = unicode(self.library.location.library_key)
result = self.lc_block.validate()
self.assertFalse(result) # Validation fails due to at least one warning/message
self.assertTrue(result.summary)
......@@ -268,47 +264,6 @@ class TestLibraryContentRender(LibraryContentTest):
self.assertEqual("LibraryContentAuthorView", rendered.js_init_fn) # but some js initialization should happen
class TestLibraryList(TestCase):
""" Tests for LibraryList XBlock Field """
def test_from_json_runtime_style(self):
"""
Test that LibraryList can parse raw libraries list as passed by runtime
"""
lib_list = LibraryList()
lib1_key, lib1_version = u'library-v1:Org1+Lib1', '5436ffec56c02c13806a4c1b'
lib2_key, lib2_version = u'library-v1:Org2+Lib2', '112dbaf312c0daa019ce9992'
raw = [[lib1_key, lib1_version], [lib2_key, lib2_version]]
parsed = lib_list.from_json(raw)
self.assertEqual(len(parsed), 2)
self.assertEquals(parsed[0].library_id, LibraryLocator.from_string(lib1_key))
self.assertEquals(parsed[0].version, ObjectId(lib1_version))
self.assertEquals(parsed[1].library_id, LibraryLocator.from_string(lib2_key))
self.assertEquals(parsed[1].version, ObjectId(lib2_version))
def test_from_json_studio_editor_style(self):
"""
Test that LibraryList can parse raw libraries list as passed by studio editor
"""
lib_list = LibraryList()
lib1_key, lib1_version = u'library-v1:Org1+Lib1', '5436ffec56c02c13806a4c1b'
lib2_key, lib2_version = u'library-v1:Org2+Lib2', '112dbaf312c0daa019ce9992'
raw = [lib1_key + ',' + lib1_version, lib2_key + ',' + lib2_version]
parsed = lib_list.from_json(raw)
self.assertEqual(len(parsed), 2)
self.assertEquals(parsed[0].library_id, LibraryLocator.from_string(lib1_key))
self.assertEquals(parsed[0].version, ObjectId(lib1_version))
self.assertEquals(parsed[1].library_id, LibraryLocator.from_string(lib2_key))
self.assertEquals(parsed[1].version, ObjectId(lib2_version))
def test_from_json_invalid_value(self):
"""
Test that LibraryList raises Value error if invalid library key is given
"""
lib_list = LibraryList()
with self.assertRaises(ValueError):
lib_list.from_json(["Not-a-library-key,whatever"])
class TestLibraryContentAnalytics(LibraryContentTest):
"""
Test analytics features of LibraryContentModule
......
......@@ -1003,6 +1003,8 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
# 3. A generic string editor for anything else (editing JSON representation of the value).
editor_type = "Generic"
values = field.values
if "values_provider" in field.runtime_options:
values = field.runtime_options['values_provider'](self)
if isinstance(values, (tuple, list)) and len(values) > 0:
editor_type = "Select"
values = [jsonify_value(field, json_choice) for json_choice in values]
......
......@@ -4,9 +4,8 @@ Library edit page in Studio
from bok_choy.javascript import js_defined, wait_for_js
from bok_choy.page_object import PageObject
from bok_choy.promise import EmptyPromise
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.select import Select
from .overview import CourseOutlineModal
from .component_editor import ComponentEditorView
from .container import XBlockWrapper
from ...pages.studio.pagination import PaginatedMixin
from ...tests.helpers import disable_animations
......@@ -111,65 +110,41 @@ class LibraryPage(PageObject, PaginatedMixin):
)
class StudioLibraryContentXBlockEditModal(CourseOutlineModal, PageObject):
class StudioLibraryContentEditor(ComponentEditorView):
"""
Library Content XBlock Modal edit window
"""
url = None
MODAL_SELECTOR = ".wrapper-modal-window-edit-xblock"
# Labels used to identify the fields on the edit modal:
LIBRARY_LABEL = "Libraries"
LIBRARY_LABEL = "Library"
COUNT_LABEL = "Count"
SCORED_LABEL = "Scored"
PROBLEM_TYPE_LABEL = "Problem Type"
def is_browser_on_page(self):
"""
Check that we are on the right page in the browser.
"""
return self.is_shown()
@property
def library_key(self):
"""
Gets value of first library key input
"""
library_key_input = self.get_metadata_input(self.LIBRARY_LABEL)
if library_key_input is not None:
return library_key_input.get_attribute('value').strip(',')
return None
def library_name(self):
return self.get_selected_option_text(self.LIBRARY_LABEL)
@library_key.setter
def library_key(self, library_key):
@library_name.setter
def library_name(self, library_name):
"""
Sets value of first library key input, creating it if necessary
Select a library from the library select box
"""
library_key_input = self.get_metadata_input(self.LIBRARY_LABEL)
if library_key_input is None:
library_key_input = self._add_library_key()
if library_key is not None:
# can't use lib_text.clear() here as input get deleted by client side script
library_key_input.send_keys(Keys.HOME)
library_key_input.send_keys(Keys.SHIFT, Keys.END)
library_key_input.send_keys(library_key)
else:
library_key_input.clear()
EmptyPromise(lambda: self.library_key == library_key, "library_key is updated in modal.").fulfill()
self.set_select_value(self.LIBRARY_LABEL, library_name)
EmptyPromise(lambda: self.library_name == library_name, "library_name is updated in modal.").fulfill()
@property
def count(self):
"""
Gets value of children count input
"""
return int(self.get_metadata_input(self.COUNT_LABEL).get_attribute('value'))
return int(self.get_setting_element(self.COUNT_LABEL).get_attribute('value'))
@count.setter
def count(self, count):
"""
Sets value of children count input
"""
count_text = self.get_metadata_input(self.COUNT_LABEL)
count_text = self.get_setting_element(self.COUNT_LABEL)
count_text.clear()
count_text.send_keys(count)
EmptyPromise(lambda: self.count == count, "count is updated in modal.").fulfill()
......@@ -179,7 +154,7 @@ class StudioLibraryContentXBlockEditModal(CourseOutlineModal, PageObject):
"""
Gets value of scored select
"""
value = self.get_metadata_input(self.SCORED_LABEL).get_attribute('value')
value = self.get_selected_option_text(self.SCORED_LABEL)
if value == 'True':
return True
elif value == 'False':
......@@ -191,10 +166,7 @@ class StudioLibraryContentXBlockEditModal(CourseOutlineModal, PageObject):
"""
Sets value of scored select
"""
select_element = self.get_metadata_input(self.SCORED_LABEL)
select_element.click()
scored_select = Select(select_element)
scored_select.select_by_value(str(scored))
self.set_select_value(self.SCORED_LABEL, str(scored))
EmptyPromise(lambda: self.scored == scored, "scored is updated in modal.").fulfill()
@property
......@@ -202,54 +174,23 @@ class StudioLibraryContentXBlockEditModal(CourseOutlineModal, PageObject):
"""
Gets value of CAPA type select
"""
return self.get_metadata_input(self.PROBLEM_TYPE_LABEL).get_attribute('value')
return self.get_setting_element(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)
self.set_select_value(self.PROBLEM_TYPE_LABEL, value)
EmptyPromise(lambda: self.capa_type == value, "problem type is updated in modal.").fulfill()
def _add_library_key(self):
"""
Adds library key input
"""
wrapper = self._get_metadata_element(self.LIBRARY_LABEL)
add_button = wrapper.find_element_by_xpath(".//a[contains(@class, 'create-action')]")
add_button.click()
return self._get_list_inputs(wrapper)[0]
def _get_list_inputs(self, list_wrapper):
"""
Finds nested input elements (useful for List and Dict fields)
"""
return list_wrapper.find_elements_by_xpath(".//input[@type='text']")
def _get_metadata_element(self, metadata_key):
"""
Gets metadata input element (a wrapper div for List and Dict fields)
"""
metadata_inputs = self.find_css(".metadata_entry .wrapper-comp-setting label.setting-label")
target_label = [elem for elem in metadata_inputs if elem.text == metadata_key][0]
label_for = target_label.get_attribute('for')
return self.find_css("#" + label_for)[0]
def get_metadata_input(self, metadata_key):
def set_select_value(self, label, value):
"""
Gets input/select element for given field
Sets the select with given label (display name) to the specified value
"""
element = self._get_metadata_element(metadata_key)
if element.tag_name == 'div':
# List or Dict field - return first input
# TODO support multiple values
inputs = self._get_list_inputs(element)
element = inputs[0] if inputs else None
return element
elem = self.get_setting_element(label)
select = Select(elem)
select.select_by_value(value)
@js_defined('window.LibraryContentAuthorView')
......
......@@ -9,7 +9,7 @@ from nose.plugins.attrib import attr
from ..helpers import UniqueCourseTest
from ...pages.studio.auto_auth import AutoAuthPage
from ...pages.studio.overview import CourseOutlinePage
from ...pages.studio.library import StudioLibraryContentXBlockEditModal, StudioLibraryContainerXBlockWrapper
from ...pages.studio.library import StudioLibraryContentEditor, StudioLibraryContainerXBlockWrapper
from ...pages.lms.courseware import CoursewarePage
from ...pages.lms.library import LibraryContentXBlockWrapper
from ...pages.common.logout import LogoutPage
......@@ -65,7 +65,7 @@ class LibraryContentTestBase(UniqueCourseTest):
)
library_content_metadata = {
'source_libraries': [self.library_key],
'source_library_id': unicode(self.library_key),
'mode': 'random',
'max_count': 1,
'has_score': False
......@@ -90,12 +90,13 @@ class LibraryContentTestBase(UniqueCourseTest):
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[0])
modal = StudioLibraryContentXBlockEditModal(library_container_block.edit())
modal.count = count
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:
modal.capa_type = capa_type
library_container_block.save_settings()
editor.capa_type = capa_type
editor.save()
self._go_to_unit_page(change_login=False)
unit_page.wait_for_page()
unit_page.publish_action.click()
......
......@@ -4,12 +4,11 @@ Acceptance tests for Library Content in LMS
import ddt
from flaky import flaky
import textwrap
from unittest import skip
from .base_studio_test import StudioLibraryTest
from ...fixtures.course import CourseFixture
from ..helpers import UniqueCourseTest
from ...pages.studio.library import StudioLibraryContentXBlockEditModal, StudioLibraryContainerXBlockWrapper
from ...pages.studio.library import StudioLibraryContentEditor, StudioLibraryContainerXBlockWrapper
from ...pages.studio.overview import CourseOutlinePage
from ...fixtures.course import XBlockFixtureDesc
......@@ -56,7 +55,7 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
def populate_course_fixture(self, course_fixture):
""" Install a course with sections/problems, tabs, updates, and handouts """
library_content_metadata = {
'source_libraries': [self.library_key],
'source_library_id': unicode(self.library_key),
'mode': 'random',
'max_count': 1,
'has_score': False
......@@ -79,29 +78,32 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
return StudioLibraryContainerXBlockWrapper.from_xblock_wrapper(xblock)
@ddt.data(
('library-v1:111+111', 1, True),
('library-v1:edX+L104', 2, False),
('library-v1:OtherX+IDDQD', 3, True),
(1, True),
(2, False),
(3, True),
)
@ddt.unpack
def test_can_edit_metadata(self, library_key, max_count, scored):
def test_can_edit_metadata(self, max_count, scored):
"""
Scenario: Given I have a library, a course and library content xblock in a course
When I go to studio unit page for library content block
And I edit library content metadata and save it
Then I can ensure that data is persisted
"""
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[0])
edit_modal = StudioLibraryContentXBlockEditModal(library_container.edit())
edit_modal.library_key = library_key
library_name = self.library_info['display_name']
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[1])
library_container.edit()
edit_modal = StudioLibraryContentEditor(self.browser, library_container.locator)
edit_modal.library_name = library_name
edit_modal.count = max_count
edit_modal.scored = scored
library_container.save_settings() # saving settings
# open edit window again to verify changes are persistent
edit_modal = StudioLibraryContentXBlockEditModal(library_container.edit())
self.assertEqual(edit_modal.library_key, library_key)
library_container.edit()
edit_modal = StudioLibraryContentEditor(self.browser, library_container.locator)
self.assertEqual(edit_modal.library_name, library_name)
self.assertEqual(edit_modal.count, max_count)
self.assertEqual(edit_modal.scored, scored)
......@@ -109,47 +111,25 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
"""
Scenario: Given I have a library, a course and library content xblock in a course
When I go to studio unit page for library content block
And I edit set library key to none
And I edit to select "No Library"
Then I can see that library content block is misconfigured
"""
expected_text = 'A library has not yet been selected.'
expected_action = 'Select a Library'
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[0])
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[1])
# precondition check - the library block should be configured before we remove the library setting
self.assertFalse(library_container.has_validation_not_configured_warning)
edit_modal = StudioLibraryContentXBlockEditModal(library_container.edit())
edit_modal.library_key = None
library_container.edit()
edit_modal = StudioLibraryContentEditor(self.browser, library_container.locator)
edit_modal.library_name = "No Library Selected"
library_container.save_settings()
self.assertTrue(library_container.has_validation_not_configured_warning)
self.assertIn(expected_text, library_container.validation_not_configured_warning_text)
self.assertIn(expected_action, library_container.validation_not_configured_warning_text)
def test_set_missing_library_shows_correct_label(self):
"""
Scenario: Given I have a library, a course and library content xblock in a course
When I go to studio unit page for library content block
And I edit set library key to non-existent library
Then I can see that library content block is misconfigured
"""
nonexistent_lib_key = 'library-v1:111+111'
expected_text = "Library is invalid, corrupt, or has been deleted."
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[0])
# precondition check - assert library is configured before we remove it
self.assertFalse(library_container.has_validation_error)
edit_modal = StudioLibraryContentXBlockEditModal(library_container.edit())
edit_modal.library_key = nonexistent_lib_key
library_container.save_settings()
self.assertTrue(library_container.has_validation_error)
self.assertIn(expected_text, library_container.validation_error_text)
@flaky # TODO fix this, see TE-745
def test_out_of_date_message(self):
"""
......@@ -162,7 +142,7 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
Then I can see that the content no longer needs to be updated
"""
expected_text = "This component is out of date. The library has new content."
library_block = self._get_library_xblock_wrapper(self.unit_page.xblocks[0])
library_block = self._get_library_xblock_wrapper(self.unit_page.xblocks[1])
self.assertFalse(library_block.has_validation_warning)
# Removed this assert until a summary message is added back to the author view (SOL-192)
......@@ -178,7 +158,7 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
library_block.refresh_children()
self.unit_page.wait_for_page() # Wait for the page to reload
library_block = self._get_library_xblock_wrapper(self.unit_page.xblocks[0])
library_block = self._get_library_xblock_wrapper(self.unit_page.xblocks[1])
self.assertFalse(library_block.has_validation_message)
# Removed this assert until a summary message is added back to the author view (SOL-192)
......@@ -206,13 +186,14 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
expected_text = 'There are no matching problem types in the specified libraries. Select another problem type'
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[0])
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[1])
# precondition check - assert library has children matching filter criteria
self.assertFalse(library_container.has_validation_error)
self.assertFalse(library_container.has_validation_warning)
edit_modal = StudioLibraryContentXBlockEditModal(library_container.edit())
library_container.edit()
edit_modal = StudioLibraryContentEditor(self.browser, library_container.locator)
self.assertEqual(edit_modal.capa_type, "Any Type") # precondition check
edit_modal.capa_type = "Custom Evaluated Script"
......@@ -221,7 +202,8 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
self.assertTrue(library_container.has_validation_warning)
self.assertIn(expected_text, library_container.validation_warning_text)
edit_modal = StudioLibraryContentXBlockEditModal(library_container.edit())
library_container.edit()
edit_modal = StudioLibraryContentEditor(self.browser, library_container.locator)
self.assertEqual(edit_modal.capa_type, "Custom Evaluated Script") # precondition check
edit_modal.capa_type = "Dropdown"
library_container.save_settings()
......@@ -237,16 +219,17 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
And I set Problem Type selector so "Any"
Then I can see that "No matching content" warning is shown
"""
expected_tpl = "The specified libraries are configured to fetch {count} problems, " \
expected_tpl = "The specified library is configured to fetch {count} problems, " \
"but there are only {actual} matching problems."
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[0])
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[1])
# precondition check - assert block is configured fine
self.assertFalse(library_container.has_validation_error)
self.assertFalse(library_container.has_validation_warning)
edit_modal = StudioLibraryContentXBlockEditModal(library_container.edit())
library_container.edit()
edit_modal = StudioLibraryContentEditor(self.browser, library_container.locator)
edit_modal.count = 50
library_container.save_settings()
......
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