refactor: rename descriptor -> block within xmodule/tests
Co-authored-by: Agrendalath <piotr@surowiec.it>
This commit is contained in:
committed by
Agrendalath
parent
537cfe4e0f
commit
ce94d896cf
@@ -191,7 +191,7 @@ def prepare_block_runtime(
|
||||
add_get_block=False,
|
||||
):
|
||||
"""
|
||||
Sets properties in the runtime of the specified descriptor that is
|
||||
Sets properties in the runtime of the specified block that is
|
||||
required for tests.
|
||||
"""
|
||||
|
||||
|
||||
@@ -2492,22 +2492,22 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
</problem>
|
||||
""")
|
||||
|
||||
def _create_descriptor(self, xml, name=None):
|
||||
def _create_block(self, xml, name=None):
|
||||
""" Creates a ProblemBlock to run test against """
|
||||
descriptor = CapaFactory.create()
|
||||
descriptor.data = xml
|
||||
block = CapaFactory.create()
|
||||
block.data = xml
|
||||
if name:
|
||||
descriptor.display_name = name
|
||||
return descriptor
|
||||
block.display_name = name
|
||||
return block
|
||||
|
||||
@ddt.data(*sorted(responsetypes.registry.registered_tags()))
|
||||
def test_all_response_types(self, response_tag):
|
||||
""" Tests that every registered response tag is correctly returned """
|
||||
xml = "<problem><{response_tag}></{response_tag}></problem>".format(response_tag=response_tag)
|
||||
name = "Some Capa Problem"
|
||||
descriptor = self._create_descriptor(xml, name=name)
|
||||
assert descriptor.problem_types == {response_tag}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
block = self._create_block(xml, name=name)
|
||||
assert block.problem_types == {response_tag}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': [response_tag],
|
||||
'content': {'display_name': name, 'capa_content': ''}}
|
||||
@@ -2528,9 +2528,9 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
</problem>
|
||||
""")
|
||||
name = "Test Capa Problem"
|
||||
descriptor = self._create_descriptor(xml, name=name)
|
||||
assert descriptor.problem_types == {'multiplechoiceresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
block = self._create_block(xml, name=name)
|
||||
assert block.problem_types == {'multiplechoiceresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['multiplechoiceresponse'],
|
||||
'content': {'display_name': name, 'capa_content': ' Label Some comment Apple Banana Chocolate Donut '}}
|
||||
@@ -2556,14 +2556,14 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
</problem>
|
||||
""")
|
||||
name = "Other Test Capa Problem"
|
||||
descriptor = self._create_descriptor(xml, name=name)
|
||||
assert descriptor.problem_types == {'multiplechoiceresponse', 'optionresponse'}
|
||||
block = self._create_block(xml, name=name)
|
||||
assert block.problem_types == {'multiplechoiceresponse', 'optionresponse'}
|
||||
|
||||
# We are converting problem_types to a set to compare it later without taking into account the order
|
||||
# the reasoning behind is that the problem_types (property) is represented by dict and when it is converted
|
||||
# to list its ordering is different everytime.
|
||||
|
||||
indexing_result = descriptor.index_dictionary()
|
||||
indexing_result = block.index_dictionary()
|
||||
indexing_result['problem_types'] = set(indexing_result['problem_types'])
|
||||
self.assertDictEqual(
|
||||
indexing_result, {
|
||||
@@ -2608,15 +2608,15 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
</problem>
|
||||
""")
|
||||
name = "Blank Common Capa Problem"
|
||||
descriptor = self._create_descriptor(xml, name=name)
|
||||
assert descriptor.index_dictionary() ==\
|
||||
block = self._create_block(xml, name=name)
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': [],
|
||||
'content': {'display_name': name, 'capa_content': ' '}}
|
||||
|
||||
def test_indexing_checkboxes(self):
|
||||
name = "Checkboxes"
|
||||
descriptor = self._create_descriptor(self.sample_checkbox_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_checkbox_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
Title
|
||||
Description
|
||||
@@ -2629,30 +2629,30 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
Hungarian
|
||||
Note: Make sure you select all of the correct options—there may be more than one!
|
||||
""")
|
||||
assert descriptor.problem_types == {'choiceresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'choiceresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['choiceresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
|
||||
def test_indexing_dropdown(self):
|
||||
name = "Dropdown"
|
||||
descriptor = self._create_descriptor(self.sample_dropdown_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_dropdown_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
Dropdown problems allow learners to select only one option from a list of options.
|
||||
Description
|
||||
You can use the following example problem as a model.
|
||||
Which of the following countries celebrates its independence on August 15? 'India','Spain','China','Bermuda'
|
||||
""")
|
||||
assert descriptor.problem_types == {'optionresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'optionresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['optionresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
|
||||
def test_indexing_multiple_choice(self):
|
||||
name = "Multiple Choice"
|
||||
descriptor = self._create_descriptor(self.sample_multichoice_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_multichoice_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
Multiple choice problems allow learners to select only one option.
|
||||
When you add the problem, be sure to select Settings to specify a Display Name and other values.
|
||||
@@ -2663,15 +2663,15 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
Indonesia
|
||||
Russia
|
||||
""")
|
||||
assert descriptor.problem_types == {'multiplechoiceresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'multiplechoiceresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['multiplechoiceresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
|
||||
def test_indexing_numerical_input(self):
|
||||
name = "Numerical Input"
|
||||
descriptor = self._create_descriptor(self.sample_numerical_input_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_numerical_input_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
In a numerical input problem, learners enter numbers or a specific and relatively simple mathematical
|
||||
expression. Learners enter the response in plain text, and the system then converts the text to a symbolic
|
||||
@@ -2685,15 +2685,15 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
How many miles away from Earth is the sun? Use scientific notation to answer.
|
||||
The square of what number is -100?
|
||||
""")
|
||||
assert descriptor.problem_types == {'numericalresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'numericalresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['numericalresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
|
||||
def test_indexing_text_input(self):
|
||||
name = "Text Input"
|
||||
descriptor = self._create_descriptor(self.sample_text_input_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_text_input_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
In text input problems, also known as "fill-in-the-blank" problems, learners enter text into a response
|
||||
field. The text can include letters and characters such as punctuation marks. The text that the learner
|
||||
@@ -2704,8 +2704,8 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
You can use the following example problem as a model.
|
||||
What was the first post-secondary school in China to allow both male and female students?
|
||||
""")
|
||||
assert descriptor.problem_types == {'stringresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'stringresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['stringresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
@@ -2718,15 +2718,15 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
</problem>
|
||||
""")
|
||||
name = "Non latin Input"
|
||||
descriptor = self._create_descriptor(sample_text_input_problem_xml, name=name)
|
||||
block = self._create_block(sample_text_input_problem_xml, name=name)
|
||||
capa_content = " Δοκιμή με μεταβλητές με Ελληνικούς χαρακτήρες μέσα σε python: $FX1_VAL "
|
||||
|
||||
descriptor_dict = descriptor.index_dictionary()
|
||||
assert descriptor_dict['content']['capa_content'] == smart_str(capa_content)
|
||||
block_dict = block.index_dictionary()
|
||||
assert block_dict['content']['capa_content'] == smart_str(capa_content)
|
||||
|
||||
def test_indexing_checkboxes_with_hints_and_feedback(self):
|
||||
name = "Checkboxes with Hints and Feedback"
|
||||
descriptor = self._create_descriptor(self.sample_checkboxes_with_hints_and_feedback_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_checkboxes_with_hints_and_feedback_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
You can provide feedback for each option in a checkbox problem, with distinct feedback depending on
|
||||
whether or not the learner selects that option.
|
||||
@@ -2742,15 +2742,15 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
potato
|
||||
tomato
|
||||
""")
|
||||
assert descriptor.problem_types == {'choiceresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'choiceresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['choiceresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
|
||||
def test_indexing_dropdown_with_hints_and_feedback(self):
|
||||
name = "Dropdown with Hints and Feedback"
|
||||
descriptor = self._create_descriptor(self.sample_dropdown_with_hints_and_feedback_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_dropdown_with_hints_and_feedback_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
You can provide feedback for each available option in a dropdown problem.
|
||||
You can also add hints for learners.
|
||||
@@ -2762,15 +2762,15 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
potato
|
||||
tomato
|
||||
""")
|
||||
assert descriptor.problem_types == {'optionresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'optionresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['optionresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
|
||||
def test_indexing_multiple_choice_with_hints_and_feedback(self):
|
||||
name = "Multiple Choice with Hints and Feedback"
|
||||
descriptor = self._create_descriptor(self.sample_multichoice_with_hints_and_feedback_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_multichoice_with_hints_and_feedback_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
You can provide feedback for each option in a multiple choice problem.
|
||||
You can also add hints for learners.
|
||||
@@ -2782,15 +2782,15 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
potato
|
||||
tomato
|
||||
""")
|
||||
assert descriptor.problem_types == {'multiplechoiceresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'multiplechoiceresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['multiplechoiceresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
|
||||
def test_indexing_numerical_input_with_hints_and_feedback(self):
|
||||
name = "Numerical Input with Hints and Feedback"
|
||||
descriptor = self._create_descriptor(self.sample_numerical_input_with_hints_and_feedback_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_numerical_input_with_hints_and_feedback_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
You can provide feedback for correct answers in numerical input problems. You cannot provide feedback
|
||||
for incorrect answers.
|
||||
@@ -2800,15 +2800,15 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
Use the following example problem as a model.
|
||||
What is the arithmetic mean for the following set of numbers? (1, 5, 6, 3, 5)
|
||||
""")
|
||||
assert descriptor.problem_types == {'numericalresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'numericalresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['numericalresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
|
||||
def test_indexing_text_input_with_hints_and_feedback(self):
|
||||
name = "Text Input with Hints and Feedback"
|
||||
descriptor = self._create_descriptor(self.sample_text_input_with_hints_and_feedback_problem_xml, name=name)
|
||||
block = self._create_block(self.sample_text_input_with_hints_and_feedback_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
You can provide feedback for the correct answer in text input problems, as well as for specific
|
||||
incorrect answers.
|
||||
@@ -2818,8 +2818,8 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
Use the following example problem as a model.
|
||||
Which U.S. state has the largest land area?
|
||||
""")
|
||||
assert descriptor.problem_types == {'stringresponse'}
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.problem_types == {'stringresponse'}
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': ['stringresponse'],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
@@ -2840,12 +2840,12 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
</problem>
|
||||
""")
|
||||
name = "Mixed business"
|
||||
descriptor = self._create_descriptor(sample_problem_xml, name=name)
|
||||
block = self._create_block(sample_problem_xml, name=name)
|
||||
capa_content = textwrap.dedent("""
|
||||
This has HTML comment in it.
|
||||
HTML end.
|
||||
""")
|
||||
assert descriptor.index_dictionary() ==\
|
||||
assert block.index_dictionary() ==\
|
||||
{'content_type': ProblemBlock.INDEX_CONTENT_TYPE,
|
||||
'problem_types': [],
|
||||
'content': {'display_name': name, 'capa_content': capa_content.replace('\n', ' ')}}
|
||||
@@ -2860,7 +2860,7 @@ class ProblemBlockXMLTest(unittest.TestCase): # lint-amnesty, pylint: disable=m
|
||||
</proble-oh no my finger broke and I can't close the problem tag properly...
|
||||
""")
|
||||
with pytest.raises(etree.XMLSyntaxError):
|
||||
self._create_descriptor(sample_invalid_xml, name="Invalid XML")
|
||||
self._create_block(sample_invalid_xml, name="Invalid XML")
|
||||
|
||||
def test_invalid_dropdown_xml(self):
|
||||
"""
|
||||
@@ -3226,29 +3226,29 @@ class ProblemBlockReportGenerationTest(unittest.TestCase):
|
||||
scope=None,
|
||||
)
|
||||
|
||||
def _get_descriptor(self): # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
def _get_block(self): # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
scope_ids = Mock(block_type='problem')
|
||||
descriptor = ProblemBlock(get_test_system(), scope_ids=scope_ids)
|
||||
descriptor.runtime = Mock()
|
||||
descriptor.data = '<problem/>'
|
||||
return descriptor
|
||||
block = ProblemBlock(get_test_system(), scope_ids=scope_ids)
|
||||
block.runtime = Mock()
|
||||
block.data = '<problem/>'
|
||||
return block
|
||||
|
||||
def test_generate_report_data_not_implemented(self):
|
||||
scope_ids = Mock(block_type='noproblem')
|
||||
descriptor = ProblemBlock(get_test_system(), scope_ids=scope_ids)
|
||||
block = ProblemBlock(get_test_system(), scope_ids=scope_ids)
|
||||
with pytest.raises(NotImplementedError):
|
||||
next(descriptor.generate_report_data(iter([])))
|
||||
next(block.generate_report_data(iter([])))
|
||||
|
||||
def test_generate_report_data_limit_responses(self):
|
||||
descriptor = self._get_descriptor()
|
||||
report_data = list(descriptor.generate_report_data(self._mock_user_state_generator(), 2))
|
||||
block = self._get_block()
|
||||
report_data = list(block.generate_report_data(self._mock_user_state_generator(), 2))
|
||||
assert 2 == len(report_data)
|
||||
|
||||
def test_generate_report_data_dont_limit_responses(self):
|
||||
descriptor = self._get_descriptor()
|
||||
block = self._get_block()
|
||||
user_count = 5
|
||||
response_count = 10
|
||||
report_data = list(descriptor.generate_report_data(
|
||||
report_data = list(block.generate_report_data(
|
||||
self._mock_user_state_generator(
|
||||
user_count=user_count,
|
||||
response_count=response_count,
|
||||
@@ -3257,17 +3257,17 @@ class ProblemBlockReportGenerationTest(unittest.TestCase):
|
||||
assert (user_count * response_count) == len(report_data)
|
||||
|
||||
def test_generate_report_data_skip_dynamath(self):
|
||||
descriptor = self._get_descriptor()
|
||||
block = self._get_block()
|
||||
iterator = iter([self._user_state(suffix='_dynamath')])
|
||||
report_data = list(descriptor.generate_report_data(iterator))
|
||||
report_data = list(block.generate_report_data(iterator))
|
||||
assert 0 == len(report_data)
|
||||
|
||||
def test_generate_report_data_report_loncapa_error(self):
|
||||
#Test to make sure reports continue despite loncappa errors, and write them into the report.
|
||||
descriptor = self._get_descriptor()
|
||||
block = self._get_block()
|
||||
with patch('xmodule.capa_block.LoncapaProblem') as mock_LoncapaProblem:
|
||||
mock_LoncapaProblem.side_effect = LoncapaProblemError
|
||||
report_data = list(descriptor.generate_report_data(
|
||||
report_data = list(block.generate_report_data(
|
||||
self._mock_user_state_generator(
|
||||
user_count=1,
|
||||
response_count=5,
|
||||
|
||||
@@ -67,33 +67,33 @@ class ConditionalFactory:
|
||||
if the source_is_error_block flag is set, create a real ErrorBlock for the source.
|
||||
"""
|
||||
|
||||
# construct source descriptor and module:
|
||||
# construct source block and module:
|
||||
source_location = BlockUsageLocator(CourseLocator("edX", "conditional_test", "test_run", deprecated=True),
|
||||
"problem", "SampleProblem", deprecated=True)
|
||||
if source_is_error_block:
|
||||
# Make an error descriptor and block
|
||||
source_descriptor = ErrorBlock.from_xml(
|
||||
# Make an error block
|
||||
source_block = ErrorBlock.from_xml(
|
||||
'some random xml data',
|
||||
system,
|
||||
id_generator=CourseLocationManager(source_location.course_key),
|
||||
error_msg='random error message'
|
||||
)
|
||||
else:
|
||||
source_descriptor = Mock(name='source_descriptor')
|
||||
source_descriptor.location = source_location
|
||||
source_block = Mock(name='source_block')
|
||||
source_block.location = source_location
|
||||
|
||||
source_descriptor.visible_to_staff_only = source_visible_to_staff_only
|
||||
source_descriptor.runtime = system
|
||||
source_descriptor.render = lambda view, context=None: system.render(source_descriptor, view, context)
|
||||
source_block.visible_to_staff_only = source_visible_to_staff_only
|
||||
source_block.runtime = system
|
||||
source_block.render = lambda view, context=None: system.render(source_block, view, context)
|
||||
|
||||
# construct other descriptors:
|
||||
child_descriptor = Mock(name='child_descriptor')
|
||||
child_descriptor.visible_to_staff_only = False
|
||||
child_descriptor._xmodule.student_view.return_value = Fragment(content='<p>This is a secret</p>') # lint-amnesty, pylint: disable=protected-access
|
||||
child_descriptor.student_view = child_descriptor._xmodule.student_view # lint-amnesty, pylint: disable=protected-access
|
||||
child_descriptor.runtime = system
|
||||
child_descriptor.render = lambda view, context=None: system.render(child_descriptor, view, context)
|
||||
child_descriptor.location = source_location.replace(category='html', name='child')
|
||||
# construct other blocks:
|
||||
child_block = Mock(name='child_block')
|
||||
child_block.visible_to_staff_only = False
|
||||
child_block._xmodule.student_view.return_value = Fragment(content='<p>This is a secret</p>') # lint-amnesty, pylint: disable=protected-access
|
||||
child_block.student_view = child_block._xmodule.student_view # lint-amnesty, pylint: disable=protected-access
|
||||
child_block.runtime = system
|
||||
child_block.render = lambda view, context=None: system.render(child_block, view, context)
|
||||
child_block.location = source_location.replace(category='html', name='child')
|
||||
|
||||
def visible_to_nonstaff_users(desc):
|
||||
"""
|
||||
@@ -104,8 +104,8 @@ class ConditionalFactory:
|
||||
def load_item(usage_id, for_parent=None): # pylint: disable=unused-argument
|
||||
"""Test-only implementation of load_item that simply returns static xblocks."""
|
||||
return {
|
||||
child_descriptor.location: child_descriptor,
|
||||
source_location: source_descriptor
|
||||
child_block.location: child_block,
|
||||
source_location: source_block
|
||||
}.get(usage_id)
|
||||
|
||||
system.load_item = load_item
|
||||
@@ -118,23 +118,23 @@ class ConditionalFactory:
|
||||
'conditional_attr': 'attempted',
|
||||
'conditional_value': 'true',
|
||||
'xml_attributes': {'attempted': 'true'},
|
||||
'children': [child_descriptor.location],
|
||||
'children': [child_block.location],
|
||||
})
|
||||
|
||||
cond_descriptor = ConditionalBlock(
|
||||
cond_block = ConditionalBlock(
|
||||
system,
|
||||
field_data,
|
||||
ScopeIds(None, None, cond_location, cond_location)
|
||||
)
|
||||
system.get_block_for_descriptor = lambda desc: desc if visible_to_nonstaff_users(desc) else None
|
||||
cond_descriptor.get_required_blocks = [
|
||||
system.get_block_for_descriptor(source_descriptor),
|
||||
cond_block.get_required_blocks = [
|
||||
system.get_block_for_descriptor(source_block),
|
||||
]
|
||||
|
||||
# return dict:
|
||||
return {'cond_block': cond_descriptor,
|
||||
'source_block': source_descriptor,
|
||||
'child_block': child_descriptor}
|
||||
return {'cond_block': cond_block,
|
||||
'source_block': source_block,
|
||||
'child_block': child_block}
|
||||
|
||||
|
||||
class ConditionalBlockBasicTest(unittest.TestCase):
|
||||
@@ -228,10 +228,10 @@ class ConditionalBlockXmlTest(unittest.TestCase):
|
||||
self.course = courses[0]
|
||||
|
||||
def get_block_for_location(self, location):
|
||||
descriptor = self.modulestore.get_item(location, depth=None)
|
||||
return self.test_system.get_block_for_descriptor(descriptor)
|
||||
block = self.modulestore.get_item(location, depth=None)
|
||||
return self.test_system.get_block_for_descriptor(block)
|
||||
|
||||
@patch('xmodule.x_module.descriptor_global_local_resource_url')
|
||||
@patch('xmodule.x_module.block_global_local_resource_url')
|
||||
@patch.dict(settings.FEATURES, {'ENABLE_EDXNOTES': False})
|
||||
def test_conditional_block(self, _):
|
||||
"""Make sure that conditional block works"""
|
||||
|
||||
@@ -235,36 +235,36 @@ class IsNewCourseTestCase(unittest.TestCase):
|
||||
assert d.start_date_is_still_default == s[3]
|
||||
|
||||
def test_display_organization(self):
|
||||
descriptor = get_dummy_course(start='2012-12-02T12:00', is_new=True)
|
||||
assert descriptor.location.org != descriptor.display_org_with_default
|
||||
assert descriptor.display_org_with_default == f'{ORG}_display'
|
||||
block = get_dummy_course(start='2012-12-02T12:00', is_new=True)
|
||||
assert block.location.org != block.display_org_with_default
|
||||
assert block.display_org_with_default == f'{ORG}_display'
|
||||
|
||||
def test_display_coursenumber(self):
|
||||
descriptor = get_dummy_course(start='2012-12-02T12:00', is_new=True)
|
||||
assert descriptor.location.course != descriptor.display_number_with_default
|
||||
assert descriptor.display_number_with_default == f'{COURSE}_display'
|
||||
block = get_dummy_course(start='2012-12-02T12:00', is_new=True)
|
||||
assert block.location.course != block.display_number_with_default
|
||||
assert block.display_number_with_default == f'{COURSE}_display'
|
||||
|
||||
def test_is_newish(self):
|
||||
descriptor = get_dummy_course(start='2012-12-02T12:00', is_new=True)
|
||||
assert descriptor.is_newish is True
|
||||
block = get_dummy_course(start='2012-12-02T12:00', is_new=True)
|
||||
assert block.is_newish is True
|
||||
|
||||
descriptor = get_dummy_course(start='2013-02-02T12:00', is_new=False)
|
||||
assert descriptor.is_newish is False
|
||||
block = get_dummy_course(start='2013-02-02T12:00', is_new=False)
|
||||
assert block.is_newish is False
|
||||
|
||||
descriptor = get_dummy_course(start='2013-02-02T12:00', is_new=True)
|
||||
assert descriptor.is_newish is True
|
||||
block = get_dummy_course(start='2013-02-02T12:00', is_new=True)
|
||||
assert block.is_newish is True
|
||||
|
||||
descriptor = get_dummy_course(start='2013-01-15T12:00')
|
||||
assert descriptor.is_newish is True
|
||||
block = get_dummy_course(start='2013-01-15T12:00')
|
||||
assert block.is_newish is True
|
||||
|
||||
descriptor = get_dummy_course(start='2013-03-01T12:00')
|
||||
assert descriptor.is_newish is True
|
||||
block = get_dummy_course(start='2013-03-01T12:00')
|
||||
assert block.is_newish is True
|
||||
|
||||
descriptor = get_dummy_course(start='2012-10-15T12:00')
|
||||
assert descriptor.is_newish is False
|
||||
block = get_dummy_course(start='2012-10-15T12:00')
|
||||
assert block.is_newish is False
|
||||
|
||||
descriptor = get_dummy_course(start='2012-12-31T12:00')
|
||||
assert descriptor.is_newish is True
|
||||
block = get_dummy_course(start='2012-12-31T12:00')
|
||||
assert block.is_newish is True
|
||||
|
||||
|
||||
class DiscussionTopicsTestCase(unittest.TestCase):
|
||||
|
||||
@@ -31,14 +31,14 @@ class TestErrorBlock(SetupTestErrorBlock):
|
||||
"""
|
||||
|
||||
def test_error_block_xml_rendering(self):
|
||||
descriptor = ErrorBlock.from_xml(
|
||||
block = ErrorBlock.from_xml(
|
||||
self.valid_xml,
|
||||
self.system,
|
||||
CourseLocationManager(self.course_id),
|
||||
self.error_msg
|
||||
)
|
||||
assert isinstance(descriptor, ErrorBlock)
|
||||
descriptor.runtime = self.system
|
||||
context_repr = self.system.render(descriptor, STUDENT_VIEW).content
|
||||
assert isinstance(block, ErrorBlock)
|
||||
block.runtime = self.system
|
||||
context_repr = self.system.render(block, STUDENT_VIEW).content
|
||||
assert self.error_msg in context_repr
|
||||
assert repr(self.valid_xml) in context_repr
|
||||
|
||||
@@ -28,22 +28,22 @@ from xmodule.tests import DATA_DIR
|
||||
from xmodule.x_module import XModuleMixin
|
||||
|
||||
|
||||
def strip_filenames(descriptor):
|
||||
def strip_filenames(block):
|
||||
"""
|
||||
Recursively strips 'filename' from all children's definitions.
|
||||
"""
|
||||
print(f"strip filename from {str(descriptor.location)}")
|
||||
if descriptor._field_data.has(descriptor, 'filename'): # lint-amnesty, pylint: disable=protected-access
|
||||
descriptor._field_data.delete(descriptor, 'filename') # lint-amnesty, pylint: disable=protected-access
|
||||
print(f"strip filename from {str(block.location)}")
|
||||
if block._field_data.has(block, 'filename'): # lint-amnesty, pylint: disable=protected-access
|
||||
block._field_data.delete(block, 'filename') # lint-amnesty, pylint: disable=protected-access
|
||||
|
||||
if hasattr(descriptor, 'xml_attributes'):
|
||||
if 'filename' in descriptor.xml_attributes:
|
||||
del descriptor.xml_attributes['filename']
|
||||
if hasattr(block, 'xml_attributes'):
|
||||
if 'filename' in block.xml_attributes:
|
||||
del block.xml_attributes['filename']
|
||||
|
||||
for child in descriptor.get_children():
|
||||
for child in block.get_children():
|
||||
strip_filenames(child)
|
||||
|
||||
descriptor.save()
|
||||
block.save()
|
||||
|
||||
|
||||
class PureXBlock(XBlock):
|
||||
|
||||
@@ -16,9 +16,9 @@ from ..x_module import PUBLIC_VIEW, STUDENT_VIEW
|
||||
from . import get_test_descriptor_system, get_test_system
|
||||
|
||||
|
||||
def instantiate_descriptor(**field_data):
|
||||
def instantiate_block(**field_data):
|
||||
"""
|
||||
Instantiate descriptor with most properties.
|
||||
Instantiate block with most properties.
|
||||
"""
|
||||
system = get_test_descriptor_system()
|
||||
course_key = CourseLocator('org', 'course', 'run')
|
||||
@@ -152,8 +152,8 @@ class HtmlBlockIndexingTestCase(unittest.TestCase):
|
||||
<p>Hello World!</p>
|
||||
</html>
|
||||
'''
|
||||
descriptor = instantiate_descriptor(data=sample_xml)
|
||||
assert descriptor.index_dictionary() ==\
|
||||
block = instantiate_block(data=sample_xml)
|
||||
assert block.index_dictionary() ==\
|
||||
{'content': {'html_content': ' Hello World! ', 'display_name': 'Text'}, 'content_type': 'Text'}
|
||||
|
||||
def test_index_dictionary_cdata_html_block(self):
|
||||
@@ -163,8 +163,8 @@ class HtmlBlockIndexingTestCase(unittest.TestCase):
|
||||
<![CDATA[This is just a CDATA!]]>
|
||||
</html>
|
||||
'''
|
||||
descriptor = instantiate_descriptor(data=sample_xml_cdata)
|
||||
assert descriptor.index_dictionary() ==\
|
||||
block = instantiate_block(data=sample_xml_cdata)
|
||||
assert block.index_dictionary() ==\
|
||||
{'content': {'html_content': ' This has CDATA in it. ', 'display_name': 'Text'}, 'content_type': 'Text'}
|
||||
|
||||
def test_index_dictionary_multiple_spaces_html_block(self):
|
||||
@@ -173,8 +173,8 @@ class HtmlBlockIndexingTestCase(unittest.TestCase):
|
||||
<p> Text has spaces :) </p>
|
||||
</html>
|
||||
'''
|
||||
descriptor = instantiate_descriptor(data=sample_xml_tab_spaces)
|
||||
assert descriptor.index_dictionary() ==\
|
||||
block = instantiate_block(data=sample_xml_tab_spaces)
|
||||
assert block.index_dictionary() ==\
|
||||
{'content': {'html_content': ' Text has spaces :) ', 'display_name': 'Text'}, 'content_type': 'Text'}
|
||||
|
||||
def test_index_dictionary_html_block_with_comment(self):
|
||||
@@ -184,8 +184,8 @@ class HtmlBlockIndexingTestCase(unittest.TestCase):
|
||||
<!-- Html Comment -->
|
||||
</html>
|
||||
'''
|
||||
descriptor = instantiate_descriptor(data=sample_xml_comment)
|
||||
assert descriptor.index_dictionary() == {'content': {'html_content': ' This has HTML comment in it. ', 'display_name': 'Text'}, 'content_type': 'Text'} # pylint: disable=line-too-long
|
||||
block = instantiate_block(data=sample_xml_comment)
|
||||
assert block.index_dictionary() == {'content': {'html_content': ' This has HTML comment in it. ', 'display_name': 'Text'}, 'content_type': 'Text'} # pylint: disable=line-too-long
|
||||
|
||||
def test_index_dictionary_html_block_with_both_comments_and_cdata(self):
|
||||
sample_xml_mix_comment_cdata = '''
|
||||
@@ -197,8 +197,8 @@ class HtmlBlockIndexingTestCase(unittest.TestCase):
|
||||
<p>HTML end.</p>
|
||||
</html>
|
||||
'''
|
||||
descriptor = instantiate_descriptor(data=sample_xml_mix_comment_cdata)
|
||||
assert descriptor.index_dictionary() ==\
|
||||
block = instantiate_block(data=sample_xml_mix_comment_cdata)
|
||||
assert block.index_dictionary() ==\
|
||||
{'content': {'html_content': ' This has HTML comment in it. HTML end. ',
|
||||
'display_name': 'Text'}, 'content_type': 'Text'}
|
||||
|
||||
@@ -216,8 +216,8 @@ class HtmlBlockIndexingTestCase(unittest.TestCase):
|
||||
</script>
|
||||
</html>
|
||||
'''
|
||||
descriptor = instantiate_descriptor(data=sample_xml_style_script_tags)
|
||||
assert descriptor.index_dictionary() ==\
|
||||
block = instantiate_block(data=sample_xml_style_script_tags)
|
||||
assert block.index_dictionary() ==\
|
||||
{'content': {'html_content': ' This has HTML comment in it. HTML end. ',
|
||||
'display_name': 'Text'}, 'content_type': 'Text'}
|
||||
|
||||
|
||||
@@ -106,9 +106,9 @@ class PureXBlockImportTest(BaseCourseTestCase):
|
||||
@patch('xmodule.x_module.XModuleMixin.location')
|
||||
def test_parsing_pure_xblock(self, xml, mock_location):
|
||||
system = self.get_system(load_error_blocks=False)
|
||||
descriptor = system.process_xml(xml)
|
||||
assert isinstance(descriptor, GenericXBlock)
|
||||
self.assert_xblocks_are_good(descriptor)
|
||||
block = system.process_xml(xml)
|
||||
assert isinstance(block, GenericXBlock)
|
||||
self.assert_xblocks_are_good(block)
|
||||
assert not mock_location.called
|
||||
|
||||
|
||||
@@ -122,9 +122,9 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
bad_xml = '''<sequential display_name="oops\N{SNOWMAN}"><video url="hi"></sequential>'''
|
||||
system = self.get_system()
|
||||
|
||||
descriptor = system.process_xml(bad_xml)
|
||||
block = system.process_xml(bad_xml)
|
||||
|
||||
assert descriptor.__class__.__name__ == 'ErrorBlockWithMixins'
|
||||
assert block.__class__.__name__ == 'ErrorBlockWithMixins'
|
||||
|
||||
def test_unique_url_names(self):
|
||||
'''Check that each error gets its very own url_name'''
|
||||
@@ -132,19 +132,19 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
bad_xml2 = '''<sequential url_name="oops"><video url="hi"></sequential>'''
|
||||
system = self.get_system()
|
||||
|
||||
descriptor1 = system.process_xml(bad_xml)
|
||||
descriptor2 = system.process_xml(bad_xml2)
|
||||
block1 = system.process_xml(bad_xml)
|
||||
block2 = system.process_xml(bad_xml2)
|
||||
|
||||
assert descriptor1.location != descriptor2.location
|
||||
assert block1.location != block2.location
|
||||
|
||||
# Check that each vertical gets its very own url_name
|
||||
bad_xml = '''<vertical display_name="abc"><problem url_name="exam1:2013_Spring:abc"/></vertical>'''
|
||||
bad_xml2 = '''<vertical display_name="abc"><problem url_name="exam2:2013_Spring:abc"/></vertical>'''
|
||||
|
||||
descriptor1 = system.process_xml(bad_xml)
|
||||
descriptor2 = system.process_xml(bad_xml2)
|
||||
block1 = system.process_xml(bad_xml)
|
||||
block2 = system.process_xml(bad_xml2)
|
||||
|
||||
assert descriptor1.location != descriptor2.location
|
||||
assert block1.location != block2.location
|
||||
|
||||
def test_reimport(self):
|
||||
'''Make sure an already-exported error xml tag loads properly'''
|
||||
@@ -152,16 +152,16 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
self.maxDiff = None
|
||||
bad_xml = '''<sequential display_name="oops"><video url="hi"></sequential>'''
|
||||
system = self.get_system()
|
||||
descriptor = system.process_xml(bad_xml)
|
||||
block = system.process_xml(bad_xml)
|
||||
|
||||
node = etree.Element('unknown')
|
||||
descriptor.add_xml_to_node(node)
|
||||
re_import_descriptor = system.process_xml(etree.tostring(node))
|
||||
block.add_xml_to_node(node)
|
||||
re_import_block = system.process_xml(etree.tostring(node))
|
||||
|
||||
assert re_import_descriptor.__class__.__name__ == 'ErrorBlockWithMixins'
|
||||
assert re_import_block.__class__.__name__ == 'ErrorBlockWithMixins'
|
||||
|
||||
assert descriptor.contents == re_import_descriptor.contents
|
||||
assert descriptor.error_msg == re_import_descriptor.error_msg
|
||||
assert block.contents == re_import_block.contents
|
||||
assert block.error_msg == re_import_block.error_msg
|
||||
|
||||
def test_fixed_xml_tag(self):
|
||||
"""Make sure a tag that's been fixed exports as the original tag type"""
|
||||
@@ -175,25 +175,25 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
|
||||
# load it
|
||||
system = self.get_system()
|
||||
descriptor = system.process_xml(xml_str_in)
|
||||
block = system.process_xml(xml_str_in)
|
||||
|
||||
# export it
|
||||
node = etree.Element('unknown')
|
||||
descriptor.add_xml_to_node(node)
|
||||
block.add_xml_to_node(node)
|
||||
|
||||
# Now make sure the exported xml is a sequential
|
||||
assert node.tag == 'sequential'
|
||||
|
||||
def course_descriptor_inheritance_check(self, descriptor, from_date_string, unicorn_color, course_run=RUN):
|
||||
def course_block_inheritance_check(self, block, from_date_string, unicorn_color, course_run=RUN):
|
||||
"""
|
||||
Checks to make sure that metadata inheritance on a course descriptor is respected.
|
||||
Checks to make sure that metadata inheritance on a course block is respected.
|
||||
"""
|
||||
# pylint: disable=protected-access
|
||||
print((descriptor, descriptor._field_data))
|
||||
assert descriptor.due == ImportTestCase.date.from_json(from_date_string)
|
||||
print((block, block._field_data))
|
||||
assert block.due == ImportTestCase.date.from_json(from_date_string)
|
||||
|
||||
# Check that the child inherits due correctly
|
||||
child = descriptor.get_children()[0]
|
||||
child = block.get_children()[0]
|
||||
assert child.due == ImportTestCase.date.from_json(from_date_string)
|
||||
# need to convert v to canonical json b4 comparing
|
||||
assert ImportTestCase.date.to_json(ImportTestCase.date.from_json(from_date_string)) ==\
|
||||
@@ -201,9 +201,9 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
|
||||
# Now export and check things
|
||||
file_system = OSFS(mkdtemp())
|
||||
descriptor.runtime.export_fs = file_system.makedir('course', recreate=True)
|
||||
block.runtime.export_fs = file_system.makedir('course', recreate=True)
|
||||
node = etree.Element('unknown')
|
||||
descriptor.add_xml_to_node(node)
|
||||
block.add_xml_to_node(node)
|
||||
|
||||
# Check that the exported xml is just a pointer
|
||||
print(("Exported xml:", etree.tostring(node)))
|
||||
@@ -213,7 +213,7 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
assert node.attrib['org'] == ORG
|
||||
|
||||
# Does the course still have unicorns?
|
||||
with descriptor.runtime.export_fs.open(f'course/{course_run}.xml') as f:
|
||||
with block.runtime.export_fs.open(f'course/{course_run}.xml') as f:
|
||||
course_xml = etree.fromstring(f.read())
|
||||
|
||||
assert course_xml.attrib['unicorn'] == unicorn_color
|
||||
@@ -227,7 +227,7 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
|
||||
# Does the chapter tag now have a due attribute?
|
||||
# hardcoded path to child
|
||||
with descriptor.runtime.export_fs.open('chapter/ch.xml') as f:
|
||||
with block.runtime.export_fs.open('chapter/ch.xml') as f:
|
||||
chapter_xml = etree.fromstring(f.read())
|
||||
assert chapter_xml.tag == 'chapter'
|
||||
assert 'due' not in chapter_xml.attrib
|
||||
@@ -250,9 +250,9 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
</course>'''.format(
|
||||
due=from_date_string, org=ORG, course=COURSE, url_name=url_name, unicorn_color=unicorn_color
|
||||
)
|
||||
descriptor = system.process_xml(start_xml)
|
||||
compute_inherited_metadata(descriptor)
|
||||
self.course_descriptor_inheritance_check(descriptor, from_date_string, unicorn_color)
|
||||
block = system.process_xml(start_xml)
|
||||
compute_inherited_metadata(block)
|
||||
self.course_block_inheritance_check(block, from_date_string, unicorn_color)
|
||||
|
||||
def test_library_metadata_import_export(self):
|
||||
"""Two checks:
|
||||
@@ -274,18 +274,18 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
</library>'''.format(
|
||||
due=from_date_string, org=ORG, course=COURSE, url_name=url_name, unicorn_color=unicorn_color
|
||||
)
|
||||
descriptor = system.process_xml(start_xml)
|
||||
block = system.process_xml(start_xml)
|
||||
|
||||
# pylint: disable=protected-access
|
||||
original_unwrapped = descriptor._unwrapped_field_data
|
||||
LibraryXMLModuleStore.patch_descriptor_kvs(descriptor)
|
||||
# '_unwrapped_field_data' is reset in `patch_descriptor_kvs`
|
||||
original_unwrapped = block._unwrapped_field_data
|
||||
LibraryXMLModuleStore.patch_block_kvs(block)
|
||||
# '_unwrapped_field_data' is reset in `patch_block_kvs`
|
||||
# pylint: disable=protected-access
|
||||
assert original_unwrapped is not descriptor._unwrapped_field_data
|
||||
compute_inherited_metadata(descriptor)
|
||||
assert original_unwrapped is not block._unwrapped_field_data
|
||||
compute_inherited_metadata(block)
|
||||
# Check the course block, since it has inheritance
|
||||
descriptor = descriptor.get_children()[0]
|
||||
self.course_descriptor_inheritance_check(descriptor, from_date_string, unicorn_color)
|
||||
block = block.get_children()[0]
|
||||
self.course_block_inheritance_check(block, from_date_string, unicorn_color)
|
||||
|
||||
def test_metadata_no_inheritance(self):
|
||||
"""
|
||||
@@ -301,9 +301,9 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
<html url_name="h" display_name="H">Two houses, ...</html>
|
||||
</chapter>
|
||||
</course>'''.format(org=ORG, course=COURSE, url_name=url_name)
|
||||
descriptor = system.process_xml(start_xml)
|
||||
compute_inherited_metadata(descriptor)
|
||||
self.course_descriptor_no_inheritance_check(descriptor)
|
||||
block = system.process_xml(start_xml)
|
||||
compute_inherited_metadata(block)
|
||||
self.course_block_no_inheritance_check(block)
|
||||
|
||||
def test_library_metadata_no_inheritance(self):
|
||||
"""
|
||||
@@ -321,31 +321,31 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
</chapter>
|
||||
</course>
|
||||
</library>'''.format(org=ORG, course=COURSE, url_name=url_name)
|
||||
descriptor = system.process_xml(start_xml)
|
||||
LibraryXMLModuleStore.patch_descriptor_kvs(descriptor)
|
||||
compute_inherited_metadata(descriptor)
|
||||
block = system.process_xml(start_xml)
|
||||
LibraryXMLModuleStore.patch_block_kvs(block)
|
||||
compute_inherited_metadata(block)
|
||||
# Run the checks on the course node instead.
|
||||
descriptor = descriptor.get_children()[0]
|
||||
self.course_descriptor_no_inheritance_check(descriptor)
|
||||
block = block.get_children()[0]
|
||||
self.course_block_no_inheritance_check(block)
|
||||
|
||||
def course_descriptor_no_inheritance_check(self, descriptor):
|
||||
def course_block_no_inheritance_check(self, block):
|
||||
"""
|
||||
Verifies that a default value of None (for due) does not get marked as inherited.
|
||||
"""
|
||||
assert descriptor.due is None
|
||||
assert block.due is None
|
||||
|
||||
# Check that the child does not inherit a value for due
|
||||
child = descriptor.get_children()[0]
|
||||
child = block.get_children()[0]
|
||||
assert child.due is None
|
||||
|
||||
# Check that the child hasn't started yet
|
||||
assert datetime.datetime.now(UTC) <= child.start
|
||||
|
||||
def override_metadata_check(self, descriptor, child, course_due, child_due):
|
||||
def override_metadata_check(self, block, child, course_due, child_due):
|
||||
"""
|
||||
Verifies that due date can be overriden at child level.
|
||||
"""
|
||||
assert descriptor.due == ImportTestCase.date.from_json(course_due)
|
||||
assert block.due == ImportTestCase.date.from_json(course_due)
|
||||
assert child.due == ImportTestCase.date.from_json(child_due)
|
||||
# Test inherited metadata. Due does not appear here (because explicitly set on child).
|
||||
assert ImportTestCase.date.to_json(ImportTestCase.date.from_json(course_due)) == child.xblock_kvs.inherited_settings['due'] # pylint: disable=line-too-long
|
||||
@@ -365,12 +365,12 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
<html url_name="h" display_name="H">Two houses, ...</html>
|
||||
</chapter>
|
||||
</course>'''.format(due=course_due, org=ORG, course=COURSE, url_name=url_name)
|
||||
descriptor = system.process_xml(start_xml)
|
||||
child = descriptor.get_children()[0]
|
||||
block = system.process_xml(start_xml)
|
||||
child = block.get_children()[0]
|
||||
# pylint: disable=protected-access
|
||||
child._field_data.set(child, 'due', child_due)
|
||||
compute_inherited_metadata(descriptor)
|
||||
self.override_metadata_check(descriptor, child, course_due, child_due)
|
||||
compute_inherited_metadata(block)
|
||||
self.override_metadata_check(block, child, course_due, child_due)
|
||||
|
||||
def test_library_metadata_override_default(self):
|
||||
"""
|
||||
@@ -389,15 +389,15 @@ class ImportTestCase(BaseCourseTestCase): # lint-amnesty, pylint: disable=missi
|
||||
</chapter>
|
||||
</course>
|
||||
</library>'''.format(due=course_due, org=ORG, course=COURSE, url_name=url_name)
|
||||
descriptor = system.process_xml(start_xml)
|
||||
LibraryXMLModuleStore.patch_descriptor_kvs(descriptor)
|
||||
block = system.process_xml(start_xml)
|
||||
LibraryXMLModuleStore.patch_block_kvs(block)
|
||||
# Chapter is two levels down here.
|
||||
child = descriptor.get_children()[0].get_children()[0]
|
||||
child = block.get_children()[0].get_children()[0]
|
||||
# pylint: disable=protected-access
|
||||
child._field_data.set(child, 'due', child_due)
|
||||
compute_inherited_metadata(descriptor)
|
||||
descriptor = descriptor.get_children()[0]
|
||||
self.override_metadata_check(descriptor, child, course_due, child_due)
|
||||
compute_inherited_metadata(block)
|
||||
block = block.get_children()[0]
|
||||
self.override_metadata_check(block, child, course_due, child_due)
|
||||
|
||||
def test_is_pointer_tag(self):
|
||||
"""
|
||||
|
||||
@@ -223,7 +223,7 @@ class LibraryContentBlockTestMixin:
|
||||
assert len(self.lc_block.children) == len(self.lib_blocks)
|
||||
|
||||
# Check how many children each user will see:
|
||||
assert len(self.lc_block.get_child_descriptors()) == 1
|
||||
assert len(self.lc_block.get_child_blocks()) == 1
|
||||
# Check that get_content_titles() doesn't return titles for hidden/unused children
|
||||
assert len(self.lc_block.get_content_titles()) == 1
|
||||
|
||||
@@ -388,7 +388,7 @@ class LibraryContentBlockTestMixin:
|
||||
children, and asserts that the number of selected children equals the count provided.
|
||||
"""
|
||||
self.lc_block.max_count = count
|
||||
selected = self.lc_block.get_child_descriptors()
|
||||
selected = self.lc_block.get_child_blocks()
|
||||
assert len(selected) == count
|
||||
return selected
|
||||
|
||||
@@ -532,7 +532,7 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
Test the "assigned" event emitted when a student is assigned specific blocks.
|
||||
"""
|
||||
# In the beginning was the lc_block and it assigned one child to the student:
|
||||
child = self.lc_block.get_child_descriptors()[0]
|
||||
child = self.lc_block.get_child_blocks()[0]
|
||||
child_lib_location, child_lib_version = self.store.get_block_original_usage(child.location)
|
||||
assert isinstance(child_lib_version, ObjectId)
|
||||
event_data = self._assert_event_was_published("assigned")
|
||||
@@ -551,7 +551,7 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
|
||||
# Now increase max_count so that one more child will be added:
|
||||
self.lc_block.max_count = 2
|
||||
children = self.lc_block.get_child_descriptors()
|
||||
children = self.lc_block.get_child_blocks()
|
||||
assert len(children) == 2
|
||||
child, new_child = children if children[0].location == child.location else reversed(children)
|
||||
event_data = self._assert_event_was_published("assigned")
|
||||
@@ -597,7 +597,7 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
course_usage_problem = inner_vertical_in_course.children[1]
|
||||
|
||||
# Trigger a publish event:
|
||||
self.lc_block.get_child_descriptors()
|
||||
self.lc_block.get_child_blocks()
|
||||
event_data = self._assert_event_was_published("assigned")
|
||||
|
||||
for block_list in (event_data["added"], event_data["result"]):
|
||||
@@ -628,12 +628,12 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
We go from one blocks assigned to none because max_count has been decreased.
|
||||
"""
|
||||
# Decrease max_count to 1, causing the block to be overlimit:
|
||||
self.lc_block.get_child_descriptors() # This line is needed in the test environment or the change has no effect
|
||||
self.lc_block.get_child_blocks() # This line is needed in the test environment or the change has no effect
|
||||
self.publisher.reset_mock() # Clear the "assigned" event that was just published.
|
||||
self.lc_block.max_count = 0
|
||||
|
||||
# Check that the event says that one block was removed, leaving no blocks left:
|
||||
children = self.lc_block.get_child_descriptors()
|
||||
children = self.lc_block.get_child_blocks()
|
||||
assert len(children) == 0
|
||||
event_data = self._assert_event_was_published("removed")
|
||||
assert len(event_data['removed']) == 1
|
||||
@@ -646,9 +646,9 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
We go from two blocks assigned, to one because the others have been deleted from the library.
|
||||
"""
|
||||
# Start by assigning two blocks to the student:
|
||||
self.lc_block.get_child_descriptors() # This line is needed in the test environment or the change has no effect
|
||||
self.lc_block.get_child_blocks() # This line is needed in the test environment or the change has no effect
|
||||
self.lc_block.max_count = 2
|
||||
initial_blocks_assigned = self.lc_block.get_child_descriptors()
|
||||
initial_blocks_assigned = self.lc_block.get_child_blocks()
|
||||
assert len(initial_blocks_assigned) == 2
|
||||
self.publisher.reset_mock() # Clear the "assigned" event that was just published.
|
||||
# Now make sure that one of the assigned blocks will have to be un-assigned.
|
||||
@@ -663,7 +663,7 @@ class TestLibraryContentAnalytics(LibraryContentTest):
|
||||
self.lc_block.refresh_children()
|
||||
|
||||
# Check that the event says that one block was removed, leaving one block left:
|
||||
children = self.lc_block.get_child_descriptors()
|
||||
children = self.lc_block.get_child_blocks()
|
||||
assert len(children) == 1
|
||||
event_data = self._assert_event_was_published("removed")
|
||||
assert event_data['removed'] ==\
|
||||
|
||||
@@ -104,8 +104,8 @@ class RandomizeBlockTest(MixedSplitTestCase):
|
||||
assert len(randomize_block.children) == 3
|
||||
|
||||
# Check how many children each user will see:
|
||||
assert len(randomize_block.get_child_descriptors()) == 1
|
||||
assert randomize_block.get_child_descriptors()[0].display_name == 'Hello HTML 1'
|
||||
assert len(randomize_block.get_child_blocks()) == 1
|
||||
assert randomize_block.get_child_blocks()[0].display_name == 'Hello HTML 1'
|
||||
# Check that get_content_titles() doesn't return titles for hidden/unused children
|
||||
# get_content_titles() is not overridden in RandomizeBlock so titles of the 3 children are returned.
|
||||
assert len(randomize_block.get_content_titles()) == 3
|
||||
@@ -113,4 +113,4 @@ class RandomizeBlockTest(MixedSplitTestCase):
|
||||
# Bind to another user and check a different child block is displayed to user.
|
||||
randomize_block = self.store.get_item(self.randomize_block.location)
|
||||
self._bind_module_system(randomize_block, 1)
|
||||
assert randomize_block.get_child_descriptors()[0].display_name == 'Hello HTML 2'
|
||||
assert randomize_block.get_child_blocks()[0].display_name == 'Hello HTML 2'
|
||||
|
||||
@@ -142,7 +142,7 @@ class SplitTestBlockLMSTest(SplitTestBlockTest):
|
||||
@ddt.unpack
|
||||
def test_child(self, user_tag, child_url_name):
|
||||
self.user_partition.scheme.current_group = self.user_partition.groups[user_tag]
|
||||
assert self.split_test_block.child_descriptor.url_name == child_url_name
|
||||
assert self.split_test_block.child_block.url_name == child_url_name
|
||||
|
||||
@ddt.data((0, 'HTML FOR GROUP 0'), (1, 'HTML FOR GROUP 1'))
|
||||
@ddt.unpack
|
||||
@@ -153,14 +153,14 @@ class SplitTestBlockLMSTest(SplitTestBlockTest):
|
||||
@ddt.data(0, 1)
|
||||
def test_child_missing_tag_value(self, _user_tag):
|
||||
# If user_tag has a missing value, we should still get back a valid child url
|
||||
assert self.split_test_block.child_descriptor.url_name in ['split_test_cond0', 'split_test_cond1']
|
||||
assert self.split_test_block.child_block.url_name in ['split_test_cond0', 'split_test_cond1']
|
||||
|
||||
@ddt.data(100, 200, 300, 400, 500, 600, 700, 800, 900, 1000)
|
||||
def test_child_persist_new_tag_value_when_tag_missing(self, _user_tag):
|
||||
# If a user_tag has a missing value, a group should be saved/persisted for that user.
|
||||
# So, we check that we get the same url_name when we call on the url_name twice.
|
||||
# We run the test ten times so that, if our storage is failing, we'll be most likely to notice it.
|
||||
assert self.split_test_block.child_descriptor.url_name == self.split_test_block.child_descriptor.url_name
|
||||
assert self.split_test_block.child_block.url_name == self.split_test_block.child_block.url_name
|
||||
|
||||
# Patch the definition_to_xml for the html children.
|
||||
@patch('xmodule.html_block.HtmlBlock.definition_to_xml')
|
||||
@@ -170,7 +170,7 @@ class SplitTestBlockLMSTest(SplitTestBlockTest):
|
||||
def_to_xml.return_value = lxml.etree.Element('html')
|
||||
|
||||
# Mock out the process_xml
|
||||
# Expect it to return a child descriptor for the SplitTestDescriptor when called.
|
||||
# Expect it to return a child block for the SplitTestDescriptor when called.
|
||||
self.course.runtime.process_xml = Mock()
|
||||
|
||||
# Write out the xml.
|
||||
|
||||
@@ -82,9 +82,9 @@ ALL_LANGUAGES = (
|
||||
)
|
||||
|
||||
|
||||
def instantiate_descriptor(**field_data):
|
||||
def instantiate_block(**field_data):
|
||||
"""
|
||||
Instantiate descriptor with most properties.
|
||||
Instantiate block with most properties.
|
||||
"""
|
||||
if field_data.get('data', None):
|
||||
field_data = VideoBlock.parse_video_xml(field_data['data'])
|
||||
@@ -172,7 +172,7 @@ class VideoBlockTestBase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.descriptor = instantiate_descriptor()
|
||||
self.block = instantiate_block()
|
||||
|
||||
def assertXmlEqual(self, expected, xml):
|
||||
"""
|
||||
@@ -195,29 +195,29 @@ class VideoBlockTestBase(unittest.TestCase):
|
||||
|
||||
class TestCreateYoutubeString(VideoBlockTestBase):
|
||||
"""
|
||||
Checks that create_youtube_string correcty extracts information from Video descriptor.
|
||||
Checks that create_youtube_string correcty extracts information from Video block.
|
||||
"""
|
||||
|
||||
def test_create_youtube_string(self):
|
||||
"""
|
||||
Test that Youtube ID strings are correctly created when writing back out to XML.
|
||||
"""
|
||||
self.descriptor.youtube_id_0_75 = 'izygArpw-Qo'
|
||||
self.descriptor.youtube_id_1_0 = 'p2Q6BrNhdh8'
|
||||
self.descriptor.youtube_id_1_25 = '1EeWXzPdhSA'
|
||||
self.descriptor.youtube_id_1_5 = 'rABDYkeK0x8'
|
||||
self.block.youtube_id_0_75 = 'izygArpw-Qo'
|
||||
self.block.youtube_id_1_0 = 'p2Q6BrNhdh8'
|
||||
self.block.youtube_id_1_25 = '1EeWXzPdhSA'
|
||||
self.block.youtube_id_1_5 = 'rABDYkeK0x8'
|
||||
expected = "0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8"
|
||||
assert create_youtube_string(self.descriptor) == expected
|
||||
assert create_youtube_string(self.block) == expected
|
||||
|
||||
def test_create_youtube_string_missing(self):
|
||||
"""
|
||||
Test that Youtube IDs which aren't explicitly set aren't included in the output string.
|
||||
"""
|
||||
self.descriptor.youtube_id_0_75 = 'izygArpw-Qo'
|
||||
self.descriptor.youtube_id_1_0 = 'p2Q6BrNhdh8'
|
||||
self.descriptor.youtube_id_1_25 = '1EeWXzPdhSA'
|
||||
self.block.youtube_id_0_75 = 'izygArpw-Qo'
|
||||
self.block.youtube_id_1_0 = 'p2Q6BrNhdh8'
|
||||
self.block.youtube_id_1_25 = '1EeWXzPdhSA'
|
||||
expected = "0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA"
|
||||
assert create_youtube_string(self.descriptor) == expected
|
||||
assert create_youtube_string(self.block) == expected
|
||||
|
||||
|
||||
class TestCreateYouTubeUrl(VideoBlockTestBase):
|
||||
@@ -230,7 +230,7 @@ class TestCreateYouTubeUrl(VideoBlockTestBase):
|
||||
Test that passing unicode to `create_youtube_url` doesn't throw
|
||||
an error.
|
||||
"""
|
||||
self.descriptor.create_youtube_url("üñîçø∂é")
|
||||
self.block.create_youtube_url("üñîçø∂é")
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -263,8 +263,8 @@ class VideoBlockImportTestCase(TestCase):
|
||||
<transcript language="ge" src="german_translation.srt" />
|
||||
</video>
|
||||
'''
|
||||
descriptor = instantiate_descriptor(data=sample_xml)
|
||||
self.assert_attributes_equal(descriptor, {
|
||||
block = instantiate_block(data=sample_xml)
|
||||
self.assert_attributes_equal(block, {
|
||||
'youtube_id_0_75': 'izygArpw-Qo',
|
||||
'youtube_id_1_0': 'p2Q6BrNhdh8',
|
||||
'youtube_id_1_25': '1EeWXzPdhSA',
|
||||
@@ -698,22 +698,22 @@ class VideoExportTestCase(VideoBlockTestBase):
|
||||
transcripts={}
|
||||
)
|
||||
)
|
||||
self.descriptor.youtube_id_0_75 = 'izygArpw-Qo'
|
||||
self.descriptor.youtube_id_1_0 = 'p2Q6BrNhdh8'
|
||||
self.descriptor.youtube_id_1_25 = '1EeWXzPdhSA'
|
||||
self.descriptor.youtube_id_1_5 = 'rABDYkeK0x8'
|
||||
self.descriptor.show_captions = False
|
||||
self.descriptor.start_time = datetime.timedelta(seconds=1.0)
|
||||
self.descriptor.end_time = datetime.timedelta(seconds=60)
|
||||
self.descriptor.track = 'http://www.example.com/track'
|
||||
self.descriptor.handout = 'http://www.example.com/handout'
|
||||
self.descriptor.download_track = True
|
||||
self.descriptor.html5_sources = ['http://www.example.com/source.mp4', 'http://www.example.com/source1.ogg']
|
||||
self.descriptor.download_video = True
|
||||
self.descriptor.transcripts = {'ua': 'ukrainian_translation.srt', 'ge': 'german_translation.srt'}
|
||||
self.descriptor.edx_video_id = edx_video_id
|
||||
self.block.youtube_id_0_75 = 'izygArpw-Qo'
|
||||
self.block.youtube_id_1_0 = 'p2Q6BrNhdh8'
|
||||
self.block.youtube_id_1_25 = '1EeWXzPdhSA'
|
||||
self.block.youtube_id_1_5 = 'rABDYkeK0x8'
|
||||
self.block.show_captions = False
|
||||
self.block.start_time = datetime.timedelta(seconds=1.0)
|
||||
self.block.end_time = datetime.timedelta(seconds=60)
|
||||
self.block.track = 'http://www.example.com/track'
|
||||
self.block.handout = 'http://www.example.com/handout'
|
||||
self.block.download_track = True
|
||||
self.block.html5_sources = ['http://www.example.com/source.mp4', 'http://www.example.com/source1.ogg']
|
||||
self.block.download_video = True
|
||||
self.block.transcripts = {'ua': 'ukrainian_translation.srt', 'ge': 'german_translation.srt'}
|
||||
self.block.edx_video_id = edx_video_id
|
||||
|
||||
xml = self.descriptor.definition_to_xml(self.file_system)
|
||||
xml = self.block.definition_to_xml(self.file_system)
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
xml_string = '''\
|
||||
<video
|
||||
@@ -741,7 +741,7 @@ class VideoExportTestCase(VideoBlockTestBase):
|
||||
video_id=edx_video_id,
|
||||
static_dir=EXPORT_IMPORT_STATIC_DIR,
|
||||
resource_fs=self.file_system,
|
||||
course_id=self.descriptor.scope_ids.usage_id.context_key,
|
||||
course_id=self.block.scope_ids.usage_id.context_key,
|
||||
)
|
||||
|
||||
@patch('xmodule.video_block.video_block.edxval_api')
|
||||
@@ -749,9 +749,9 @@ class VideoExportTestCase(VideoBlockTestBase):
|
||||
# Export should succeed without VAL data if video does not exist
|
||||
mock_val_api.ValVideoNotFoundError = _MockValVideoNotFoundError
|
||||
mock_val_api.export_to_xml = Mock(side_effect=mock_val_api.ValVideoNotFoundError)
|
||||
self.descriptor.edx_video_id = 'test_edx_video_id'
|
||||
self.block.edx_video_id = 'test_edx_video_id'
|
||||
|
||||
xml = self.descriptor.definition_to_xml(self.file_system)
|
||||
xml = self.block.definition_to_xml(self.file_system)
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
xml_string = '<video youtube="1.00:3_yD_cEKoCk" url_name="SampleProblem"/>'
|
||||
expected = etree.XML(xml_string, parser=parser)
|
||||
@@ -762,19 +762,19 @@ class VideoExportTestCase(VideoBlockTestBase):
|
||||
"""
|
||||
Test that we write the correct XML on export.
|
||||
"""
|
||||
self.descriptor.youtube_id_0_75 = 'izygArpw-Qo'
|
||||
self.descriptor.youtube_id_1_0 = 'p2Q6BrNhdh8'
|
||||
self.descriptor.youtube_id_1_25 = '1EeWXzPdhSA'
|
||||
self.descriptor.youtube_id_1_5 = 'rABDYkeK0x8'
|
||||
self.descriptor.show_captions = False
|
||||
self.descriptor.start_time = datetime.timedelta(seconds=5.0)
|
||||
self.descriptor.end_time = datetime.timedelta(seconds=0.0)
|
||||
self.descriptor.track = 'http://www.example.com/track'
|
||||
self.descriptor.download_track = True
|
||||
self.descriptor.html5_sources = ['http://www.example.com/source.mp4', 'http://www.example.com/source.ogg']
|
||||
self.descriptor.download_video = True
|
||||
self.block.youtube_id_0_75 = 'izygArpw-Qo'
|
||||
self.block.youtube_id_1_0 = 'p2Q6BrNhdh8'
|
||||
self.block.youtube_id_1_25 = '1EeWXzPdhSA'
|
||||
self.block.youtube_id_1_5 = 'rABDYkeK0x8'
|
||||
self.block.show_captions = False
|
||||
self.block.start_time = datetime.timedelta(seconds=5.0)
|
||||
self.block.end_time = datetime.timedelta(seconds=0.0)
|
||||
self.block.track = 'http://www.example.com/track'
|
||||
self.block.download_track = True
|
||||
self.block.html5_sources = ['http://www.example.com/source.mp4', 'http://www.example.com/source.ogg']
|
||||
self.block.download_video = True
|
||||
|
||||
xml = self.descriptor.definition_to_xml(self.file_system)
|
||||
xml = self.block.definition_to_xml(self.file_system)
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
xml_string = '''\
|
||||
<video url_name="SampleProblem" start_time="0:00:05" youtube="0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8" show_captions="false" download_video="true" download_track="true">
|
||||
@@ -791,7 +791,7 @@ class VideoExportTestCase(VideoBlockTestBase):
|
||||
"""
|
||||
Test XML export with defaults.
|
||||
"""
|
||||
xml = self.descriptor.definition_to_xml(self.file_system)
|
||||
xml = self.block.definition_to_xml(self.file_system)
|
||||
# Check that download_video field is also set to default (False) in xml for backward compatibility
|
||||
expected = '<video youtube="1.00:3_yD_cEKoCk" url_name="SampleProblem"/>\n'
|
||||
assert expected == etree.tostring(xml, pretty_print=True).decode('utf-8')
|
||||
@@ -801,8 +801,8 @@ class VideoExportTestCase(VideoBlockTestBase):
|
||||
"""
|
||||
Test XML export with transcripts being overridden to None.
|
||||
"""
|
||||
self.descriptor.transcripts = None
|
||||
xml = self.descriptor.definition_to_xml(self.file_system)
|
||||
self.block.transcripts = None
|
||||
xml = self.block.definition_to_xml(self.file_system)
|
||||
expected = b'<video youtube="1.00:3_yD_cEKoCk" url_name="SampleProblem"/>\n'
|
||||
assert expected == etree.tostring(xml, pretty_print=True)
|
||||
|
||||
@@ -812,8 +812,8 @@ class VideoExportTestCase(VideoBlockTestBase):
|
||||
Test XML export will *not* raise TypeError by lxml library if contains illegal characters.
|
||||
The illegal characters in a String field are removed from the string instead.
|
||||
"""
|
||||
self.descriptor.display_name = 'Display\x1eName'
|
||||
xml = self.descriptor.definition_to_xml(self.file_system)
|
||||
self.block.display_name = 'Display\x1eName'
|
||||
xml = self.block.definition_to_xml(self.file_system)
|
||||
assert xml.get('display_name') == 'DisplayName'
|
||||
|
||||
@patch('xmodule.video_block.video_block.edxval_api', None)
|
||||
@@ -821,8 +821,8 @@ class VideoExportTestCase(VideoBlockTestBase):
|
||||
"""
|
||||
Test XML export handles the unicode characters.
|
||||
"""
|
||||
self.descriptor.display_name = '这是文'
|
||||
xml = self.descriptor.definition_to_xml(self.file_system)
|
||||
self.block.display_name = '这是文'
|
||||
xml = self.block.definition_to_xml(self.file_system)
|
||||
assert xml.get('display_name') == '这是文'
|
||||
|
||||
|
||||
@@ -869,8 +869,8 @@ class VideoBlockStudentViewDataTestCase(unittest.TestCase):
|
||||
"""
|
||||
Ensure that student_view_data returns the expected results for video blocks.
|
||||
"""
|
||||
descriptor = instantiate_descriptor(**field_data)
|
||||
student_view_data = descriptor.student_view_data()
|
||||
block = instantiate_block(**field_data)
|
||||
student_view_data = block.student_view_data()
|
||||
assert student_view_data == expected_student_view_data
|
||||
|
||||
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
|
||||
@@ -903,9 +903,9 @@ class VideoBlockStudentViewDataTestCase(unittest.TestCase):
|
||||
'file_name': 'edx.sjson'
|
||||
}
|
||||
|
||||
descriptor = instantiate_descriptor(edx_video_id='example_id', only_on_web=False)
|
||||
descriptor.runtime.handler_url = MagicMock()
|
||||
student_view_data = descriptor.student_view_data()
|
||||
block = instantiate_block(edx_video_id='example_id', only_on_web=False)
|
||||
block.runtime.handler_url = MagicMock()
|
||||
student_view_data = block.student_view_data()
|
||||
expected_video_data = {'hls': {'url': 'http://www.meowmix.com', 'file_size': 25556}}
|
||||
self.assertDictEqual(student_view_data.get('encoded_videos'), expected_video_data)
|
||||
|
||||
@@ -973,8 +973,8 @@ class VideoBlockIndexingTestCase(unittest.TestCase):
|
||||
<handout src="http://www.example.com/handout"/>
|
||||
</video>
|
||||
'''
|
||||
descriptor = instantiate_descriptor(data=xml_data)
|
||||
assert descriptor.index_dictionary() == {'content': {'display_name': 'Test Video'}, 'content_type': 'Video'}
|
||||
block = instantiate_block(data=xml_data)
|
||||
assert block.index_dictionary() == {'content': {'display_name': 'Test Video'}, 'content_type': 'Video'}
|
||||
|
||||
def test_video_with_multiple_transcripts_index_dictionary(self):
|
||||
"""
|
||||
@@ -997,10 +997,10 @@ class VideoBlockIndexingTestCase(unittest.TestCase):
|
||||
</video>
|
||||
'''
|
||||
|
||||
descriptor = instantiate_descriptor(data=xml_data_transcripts)
|
||||
save_to_store(SRT_FILEDATA, "subs_grmtran1.srt", 'text/srt', descriptor.location)
|
||||
save_to_store(CRO_SRT_FILEDATA, "subs_croatian1.srt", 'text/srt', descriptor.location)
|
||||
assert descriptor.index_dictionary() ==\
|
||||
block = instantiate_block(data=xml_data_transcripts)
|
||||
save_to_store(SRT_FILEDATA, "subs_grmtran1.srt", 'text/srt', block.location)
|
||||
save_to_store(CRO_SRT_FILEDATA, "subs_croatian1.srt", 'text/srt', block.location)
|
||||
assert block.index_dictionary() ==\
|
||||
{'content': {'display_name': 'Test Video',
|
||||
'transcript_ge': 'sprechen sie deutsch? Ja, ich spreche Deutsch',
|
||||
'transcript_hr': 'Dobar dan! Kako ste danas?'}, 'content_type': 'Video'}
|
||||
@@ -1026,8 +1026,8 @@ class VideoBlockIndexingTestCase(unittest.TestCase):
|
||||
</video>
|
||||
'''
|
||||
|
||||
descriptor = instantiate_descriptor(data=xml_data_transcripts)
|
||||
translations = descriptor.available_translations(descriptor.get_transcripts_info())
|
||||
block = instantiate_block(data=xml_data_transcripts)
|
||||
translations = block.available_translations(block.get_transcripts_info())
|
||||
assert sorted(translations) == sorted(['hr', 'ge'])
|
||||
|
||||
def test_video_with_no_transcripts_translation_retrieval(self):
|
||||
@@ -1036,14 +1036,14 @@ class VideoBlockIndexingTestCase(unittest.TestCase):
|
||||
no transcripts uploaded by a user- ie, that retrieval
|
||||
does not throw an exception.
|
||||
"""
|
||||
descriptor = instantiate_descriptor(data=None)
|
||||
translations_with_fallback = descriptor.available_translations(descriptor.get_transcripts_info())
|
||||
block = instantiate_block(data=None)
|
||||
translations_with_fallback = block.available_translations(block.get_transcripts_info())
|
||||
assert translations_with_fallback == ['en']
|
||||
|
||||
with patch.dict(settings.FEATURES, FALLBACK_TO_ENGLISH_TRANSCRIPTS=False):
|
||||
# Some organizations don't have English transcripts for all videos
|
||||
# This feature makes it configurable
|
||||
translations_no_fallback = descriptor.available_translations(descriptor.get_transcripts_info())
|
||||
translations_no_fallback = block.available_translations(block.get_transcripts_info())
|
||||
assert translations_no_fallback == []
|
||||
|
||||
@override_settings(ALL_LANGUAGES=ALL_LANGUAGES)
|
||||
@@ -1066,8 +1066,8 @@ class VideoBlockIndexingTestCase(unittest.TestCase):
|
||||
<transcript language="ur" src="" />
|
||||
</video>
|
||||
'''
|
||||
descriptor = instantiate_descriptor(data=xml_data_transcripts)
|
||||
translations = descriptor.available_translations(descriptor.get_transcripts_info(), verify_assets=False)
|
||||
block = instantiate_block(data=xml_data_transcripts)
|
||||
translations = block.available_translations(block.get_transcripts_info(), verify_assets=False)
|
||||
assert translations != ['ur']
|
||||
|
||||
def assert_validation_message(self, validation, expected_msg):
|
||||
@@ -1114,16 +1114,16 @@ class VideoBlockIndexingTestCase(unittest.TestCase):
|
||||
{xml_transcripts}
|
||||
</video>
|
||||
'''.format(xml_transcripts=xml_transcripts)
|
||||
descriptor = instantiate_descriptor(data=xml_data_transcripts)
|
||||
validation = descriptor.validate()
|
||||
block = instantiate_block(data=xml_data_transcripts)
|
||||
validation = block.validate()
|
||||
self.assert_validation_message(validation, expected_validation_msg)
|
||||
|
||||
def test_video_transcript_none(self):
|
||||
"""
|
||||
Test video when transcripts is None.
|
||||
"""
|
||||
descriptor = instantiate_descriptor(data=None)
|
||||
descriptor.transcripts = None
|
||||
response = descriptor.get_transcripts_info()
|
||||
block = instantiate_block(data=None)
|
||||
block.transcripts = None
|
||||
response = block.get_transcripts_info()
|
||||
expected = {'transcripts': {}, 'sub': ''}
|
||||
assert expected == response
|
||||
|
||||
@@ -251,8 +251,8 @@ class EditableMetadataFieldsTest(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_integer_field(self):
|
||||
descriptor = self.get_descriptor(DictFieldData({'max_attempts': '7'}))
|
||||
editable_fields = descriptor.editable_metadata_fields
|
||||
block = self.get_block(DictFieldData({'max_attempts': '7'}))
|
||||
editable_fields = block.editable_metadata_fields
|
||||
assert 8 == len(editable_fields)
|
||||
self.assert_field_values(
|
||||
editable_fields, 'max_attempts', TestFields.max_attempts,
|
||||
@@ -264,7 +264,7 @@ class EditableMetadataFieldsTest(unittest.TestCase):
|
||||
explicitly_set=False, value='local default', default_value='local default'
|
||||
)
|
||||
|
||||
editable_fields = self.get_descriptor(DictFieldData({})).editable_metadata_fields
|
||||
editable_fields = self.get_block(DictFieldData({})).editable_metadata_fields
|
||||
self.assert_field_values(
|
||||
editable_fields, 'max_attempts', TestFields.max_attempts,
|
||||
explicitly_set=False, value=1000, default_value=1000, type='Integer',
|
||||
@@ -274,8 +274,8 @@ class EditableMetadataFieldsTest(unittest.TestCase):
|
||||
def test_inherited_field(self):
|
||||
kvs = InheritanceKeyValueStore(initial_values={}, inherited_settings={'showanswer': 'inherited'})
|
||||
model_data = KvsFieldData(kvs)
|
||||
descriptor = self.get_descriptor(model_data)
|
||||
editable_fields = descriptor.editable_metadata_fields
|
||||
block = self.get_block(model_data)
|
||||
editable_fields = block.editable_metadata_fields
|
||||
self.assert_field_values(
|
||||
editable_fields, 'showanswer', InheritanceMixin.showanswer,
|
||||
explicitly_set=False, value='inherited', default_value='inherited'
|
||||
@@ -287,8 +287,8 @@ class EditableMetadataFieldsTest(unittest.TestCase):
|
||||
inherited_settings={'showanswer': 'inheritable value'}
|
||||
)
|
||||
model_data = KvsFieldData(kvs)
|
||||
descriptor = self.get_descriptor(model_data)
|
||||
editable_fields = descriptor.editable_metadata_fields
|
||||
block = self.get_block(model_data)
|
||||
editable_fields = block.editable_metadata_fields
|
||||
self.assert_field_values(
|
||||
editable_fields, 'showanswer', InheritanceMixin.showanswer,
|
||||
explicitly_set=True, value='explicit', default_value='inheritable value'
|
||||
@@ -298,8 +298,8 @@ class EditableMetadataFieldsTest(unittest.TestCase):
|
||||
# test_display_name_field verifies that a String field is of type "Generic".
|
||||
# test_integer_field verifies that a Integer field is of type "Integer".
|
||||
|
||||
descriptor = self.get_descriptor(DictFieldData({}))
|
||||
editable_fields = descriptor.editable_metadata_fields
|
||||
block = self.get_block(DictFieldData({}))
|
||||
editable_fields = block.editable_metadata_fields
|
||||
|
||||
# Tests for select
|
||||
self.assert_field_values(
|
||||
@@ -343,16 +343,16 @@ class EditableMetadataFieldsTest(unittest.TestCase):
|
||||
field_data=field_data,
|
||||
).editable_metadata_fields
|
||||
|
||||
def get_descriptor(self, field_data):
|
||||
class TestModuleDescriptor(TestFields, self.TestableXmlXBlock): # lint-amnesty, pylint: disable=abstract-method
|
||||
def get_block(self, field_data):
|
||||
class TestModuleBlock(TestFields, self.TestableXmlXBlock): # lint-amnesty, pylint: disable=abstract-method
|
||||
@property
|
||||
def non_editable_metadata_fields(self):
|
||||
non_editable_fields = super().non_editable_metadata_fields
|
||||
non_editable_fields.append(TestModuleDescriptor.due)
|
||||
non_editable_fields.append(TestModuleBlock.due)
|
||||
return non_editable_fields
|
||||
|
||||
system = get_test_descriptor_system(render_template=Mock())
|
||||
return system.construct_xblock_from_class(TestModuleDescriptor, field_data=field_data, scope_ids=Mock())
|
||||
return system.construct_xblock_from_class(TestModuleBlock, field_data=field_data, scope_ids=Mock())
|
||||
|
||||
def assert_field_values(self, editable_fields, name, field, explicitly_set, value, default_value, # lint-amnesty, pylint: disable=dangerous-default-value
|
||||
type='Generic', options=[]): # lint-amnesty, pylint: disable=redefined-builtin
|
||||
|
||||
@@ -23,7 +23,7 @@ class InMemorySystem(XMLParsingSystem, MakoDescriptorSystem): # pylint: disable
|
||||
def __init__(self, xml_import_data):
|
||||
self.course_id = CourseKey.from_string(xml_import_data.course_id)
|
||||
self.default_class = xml_import_data.default_class
|
||||
self._descriptors = {}
|
||||
self._blocks = {}
|
||||
|
||||
def get_policy(usage_id):
|
||||
"""Return the policy data for the specified usage"""
|
||||
@@ -42,19 +42,19 @@ class InMemorySystem(XMLParsingSystem, MakoDescriptorSystem): # pylint: disable
|
||||
)
|
||||
|
||||
def process_xml(self, xml): # pylint: disable=method-hidden
|
||||
"""Parse `xml` as an XBlock, and add it to `self._descriptors`"""
|
||||
"""Parse `xml` as an XBlock, and add it to `self._blocks`"""
|
||||
self.get_asides = Mock(return_value=[])
|
||||
descriptor = self.xblock_from_node(
|
||||
block = self.xblock_from_node(
|
||||
etree.fromstring(xml),
|
||||
None,
|
||||
CourseLocationManager(self.course_id),
|
||||
)
|
||||
self._descriptors[str(descriptor.location)] = descriptor
|
||||
return descriptor
|
||||
self._blocks[str(block.location)] = block
|
||||
return block
|
||||
|
||||
def load_item(self, location, for_parent=None): # pylint: disable=method-hidden, unused-argument
|
||||
"""Return the descriptor loaded for `location`"""
|
||||
return self._descriptors[str(location)]
|
||||
"""Return the block loaded for `location`"""
|
||||
return self._blocks[str(location)]
|
||||
|
||||
|
||||
class XModuleXmlImportTest(TestCase):
|
||||
|
||||
Reference in New Issue
Block a user