def test_export_default_discussion_id(self): """ Test that default discussion_id values are not exported. Historically, the OLX format allowed omitting discussion ID values; in such case, the IDs are generated deterministically based on the course ID and the usage ID. Moreover, Studio does not allow course authors to edit discussion_id, so all courses authored in Studio have discussion_id omitted in OLX. Forcing Studio to always export discussion_id can cause data loss when switching between an older and newer export, in a course with a course ID different from the one from which the export was created - because the discussion ID would be different. """ target_node = etree.Element('dummy') block = DiscussionXBlock(self.runtime_mock, scope_ids=self.keys, field_data=DictFieldData({})) discussion_id_field = block.fields['discussion_id'] # precondition checks - discussion_id does not have a value and uses UNIQUE_ID self.assertEqual( discussion_id_field._get_cached_value(block), # pylint: disable=protected-access NO_CACHE_VALUE ) self.assertEqual(discussion_id_field.default, UNIQUE_ID) block.add_xml_to_node(target_node) self.assertEqual(target_node.tag, "discussion") self.assertNotIn("discussion_id", target_node.attrib)
def test_export_default_discussion_id(self): """ Test that default discussion_id values are not exported. Historically, the OLX format allowed omitting discussion ID values; in such case, the IDs are generated deterministically based on the course ID and the usage ID. Moreover, Studio does not allow course authors to edit discussion_id, so all courses authored in Studio have discussion_id omitted in OLX. Forcing Studio to always export discussion_id can cause data loss when switching between an older and newer export, in a course with a course ID different from the one from which the export was created - because the discussion ID would be different. """ target_node = etree.Element('dummy') block = DiscussionXBlock(self.runtime_mock, scope_ids=self.keys, field_data=DictFieldData({})) discussion_id_field = block.fields['discussion_id'] # precondition checks - discussion_id does not have a value and uses UNIQUE_ID self.assertEqual( discussion_id_field._get_cached_value(block), # pylint: disable=protected-access NO_CACHE_VALUE) self.assertEqual(discussion_id_field.default, UNIQUE_ID) block.add_xml_to_node(target_node) self.assertEqual(target_node.tag, "discussion") self.assertNotIn("discussion_id", target_node.attrib)
def test_export_custom_discussion_id(self, discussion_id): """ Test that custom discussion_id values are exported """ target_node = etree.Element('dummy') block = DiscussionXBlock(self.runtime_mock, scope_ids=self.keys, field_data=DictFieldData({})) block.discussion_id = discussion_id # precondition check self.assertEqual(block.discussion_id, discussion_id) block.add_xml_to_node(target_node) self.assertEqual(target_node.tag, "discussion") self.assertTrue(target_node.attrib["discussion_id"], discussion_id)
def test_export_custom_discussion_id(self, discussion_id): """ Test that custom discussion_id values are exported """ target_node = etree.Element('dummy') block = DiscussionXBlock(self.runtime_mock, scope_ids=self.keys, field_data=DictFieldData({})) block.discussion_id = discussion_id # precondition check assert block.discussion_id == discussion_id block.add_xml_to_node(target_node) assert target_node.tag == 'discussion' assert target_node.attrib['discussion_id'], discussion_id
def test_xblock_export_format(self, id_pair, category_pair, target_pair, patched_load_definition_xml): """ Test that xblock export XML format can be parsed preserving field values """ xblock_xml = """ <discussion url_name="82bb87a2d22240b1adac2dfcc1e7e5e4" xblock-family="xblock.v1" {id_attr}="{id_value}" {category_attr}="{category_value}" {target_attr}="{target_value}" /> """.format( id_attr=id_pair.name, id_value=id_pair.value, category_attr=category_pair.name, category_value=category_pair.value, target_attr=target_pair.name, target_value=target_pair.value, ) node = etree.fromstring(xblock_xml) patched_load_definition_xml.side_effect = Exception("Irrelevant") block = DiscussionXBlock.parse_xml(node, self.runtime_mock, self.keys, self.id_gen_mock) try: self.assertEqual(block.discussion_id, id_pair.value) self.assertEqual(block.discussion_category, category_pair.value) self.assertEqual(block.discussion_target, target_pair.value) except AssertionError: print(xblock_xml) raise
def test_xblock_export_format(self, id_pair, category_pair, target_pair, patched_load_definition_xml): """ Test that xblock export XML format can be parsed preserving field values """ xblock_xml = u""" <discussion url_name="82bb87a2d22240b1adac2dfcc1e7e5e4" xblock-family="xblock.v1" {id_attr}="{id_value}" {category_attr}="{category_value}" {target_attr}="{target_value}" /> """.format( id_attr=id_pair.name, id_value=id_pair.value, category_attr=category_pair.name, category_value=category_pair.value, target_attr=target_pair.name, target_value=target_pair.value, ) node = etree.fromstring(xblock_xml) patched_load_definition_xml.side_effect = Exception("Irrelevant") block = DiscussionXBlock.parse_xml(node, self.runtime_mock, self.keys, self.id_gen_mock) try: self.assertEqual(block.discussion_id, id_pair.value) self.assertEqual(block.discussion_category, category_pair.value) self.assertEqual(block.discussion_target, target_pair.value) except AssertionError: print(xblock_xml) raise
def _construct_xblock_mock(self, cls, keys): # pylint: disable=unused-argument """ Builds target xblock instance (DiscussionXBlock) Signature-compatible with runtime.construct_xblock_from_class - can be used as a mock side-effect """ return DiscussionXBlock(self.runtime_mock, scope_ids=keys, field_data=DictFieldData({}))
def test_legacy_export_format(self, id_pair, category_pair, target_pair, patched_load_definition_xml): """ Test that legacy export XML format can be parsed preserving field values """ xblock_xml = """<discussion url_name="82bb87a2d22240b1adac2dfcc1e7e5e4"/>""" xblock_definition_xml = """ <discussion {id_attr}="{id_value}" {category_attr}="{category_value}" {target_attr}="{target_value}" />""".format( id_attr=id_pair.name, id_value=id_pair.value, category_attr=category_pair.name, category_value=category_pair.value, target_attr=target_pair.name, target_value=target_pair.value, ) node = etree.fromstring(xblock_xml) definition_node = etree.fromstring(xblock_definition_xml) patched_load_definition_xml.return_value = (definition_node, "irrelevant") block = DiscussionXBlock.parse_xml(node, self.runtime_mock, self.keys, self.id_gen_mock) try: assert block.discussion_id == id_pair.value assert block.discussion_category == category_pair.value assert block.discussion_target == target_pair.value except AssertionError: print(xblock_xml, xblock_definition_xml) raise