def test_concepts_should_have_unique_fully_specified_name_per_locale(self): name_fully_specified1 = LocalizedTextFactory.build( name='FullySpecifiedName1') source = OrganizationSourceFactory( custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept1_data = { **factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c1', 'parent': source, 'names': [name_fully_specified1] } concept2_data = { **factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c2', 'parent': source, 'names': [name_fully_specified1] } concept1 = Concept.persist_new(concept1_data) concept2 = Concept.persist_new(concept2_data) self.assertEqual(concept1.errors, {}) self.assertEqual( concept2.errors, dict(names=[ OPENMRS_FULLY_SPECIFIED_NAME_UNIQUE_PER_SOURCE_LOCALE + ': FullySpecifiedName1 (locale: en, preferred: no)' ]))
def test_duplicate_preferred_name_per_source_should_fail(self): source = SourceFactory(custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept1 = Concept.persist_new( dict( mnemonic='concept1', version=HEAD, name='concept1', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build( name='Concept Non Unique Preferred Name', locale='en', locale_preferred=True, type='Fully Specified' ), ] ) ) concept2 = Concept.persist_new( dict( mnemonic='concept2', version=HEAD, name='concept2', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build( name='Concept Non Unique Preferred Name', locale='en', locale_preferred=True, type='None' ), LocalizedTextFactory.build( name='any name', locale='en', locale_preferred=False, type='Fully Specified' ), ] ) ) self.assertEqual(concept1.errors, {}) self.assertEqual( concept2.errors, dict(names=[OPENMRS_PREFERRED_NAME_UNIQUE_PER_SOURCE_LOCALE + ': Concept Non Unique Preferred Name (locale: en, preferred: yes)']) )
def create_concepts(source, file, user): file = open(file, 'r') lines = file.readlines() for line in lines: data = json.loads(line) mnemonic = data.pop('id', None) if not Concept.objects.filter(parent=source, mnemonic=mnemonic, is_latest_version=True).exists(): data['mnemonic'] = mnemonic data['name'] = mnemonic data['parent'] = source Concept.persist_new(data, user)
def test_concept_should_have_exactly_one_preferred_name_per_locale(self): name_en1 = LocalizedTextFactory.build(name='PreferredName1', locale_preferred=True) name_en2 = LocalizedTextFactory.build(name='PreferredName2', locale_preferred=True) name_tr = LocalizedTextFactory.build(name='PreferredName3', locale="tr", locale_preferred=True) source = OrganizationSourceFactory( custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS) concept = Concept.persist_new( dict(mnemonic='concept', version=HEAD, name='concept', parent=source, concept_class='Diagnosis', datatype='None', names=[name_en1, name_en2, name_tr])) self.assertEqual( concept.errors, dict(names=[ OPENMRS_MUST_HAVE_EXACTLY_ONE_PREFERRED_NAME + ': PreferredName2 (locale: en, preferred: yes)' ]))
def test_unique_preferred_name_per_locale_within_concept_negative(self): source = OrganizationSourceFactory( custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept = Concept.persist_new( dict(mnemonic='concept1', version=HEAD, name='concept1', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build( name='Concept Non Unique Preferred Name', locale='es', locale_preferred=True, type='FULLY_SPECIFIED'), LocalizedTextFactory.build( name='Concept Non Unique Preferred Name', locale='es', locale_preferred=True, type='FULLY_SPECIFIED'), ])) self.assertEqual( concept.errors, { 'names': [ 'A concept may not have more than one preferred name (per locale): ' 'Concept Non Unique Preferred Name (locale: es, preferred: yes)' ] })
def test_a_preferred_name_can_not_be_a_short_name(self): source = OrganizationSourceFactory( custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept = Concept.persist_new( dict(mnemonic='concept', version=HEAD, name='concept', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build(name="ShortName", locale_preferred=True, type="Short", locale='fr'), LocalizedTextFactory.build(name='Fully Specified Name'), ])) self.assertEqual( concept.errors, dict(names=[ OPENMRS_SHORT_NAME_CANNOT_BE_PREFERRED + ': ShortName (locale: fr, preferred: yes)' ]))
def test_unretire(self): source = SourceFactory(version=HEAD) concept = Concept.persist_new({ **factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c1', 'parent': source, 'retired': True, 'names': [LocalizedTextFactory.build(locale='en', name='English', locale_preferred=True)] }) self.assertEqual(concept.versions.count(), 1) self.assertTrue(concept.retired) self.assertTrue(concept.is_head) concept.unretire(concept.created_by, 'World needs you!') # concept will become old/prev version concept.refresh_from_db() self.assertFalse(concept.is_head) self.assertEqual(concept.versions.count(), 2) self.assertTrue(concept.retired) latest_version = concept.get_latest_version() self.assertFalse(latest_version.retired) self.assertEqual(latest_version.comment, 'World needs you!') self.assertEqual( concept.unretire(concept.created_by), {'__all__': CONCEPT_IS_ALREADY_NOT_RETIRED} )
def test_no_more_than_one_short_name_per_locale(self): source = OrganizationSourceFactory( custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept = Concept.persist_new( dict(mnemonic='concept', version=HEAD, name='concept', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build(name="fully specified name1", locale='en', type='Short'), LocalizedTextFactory.build(name='fully specified name2', locale='en', type='Short'), LocalizedTextFactory.build(name='fully specified name3', locale='fr'), ])) self.assertEqual( concept.errors, dict(names=[ OPENMRS_NO_MORE_THAN_ONE_SHORT_NAME_PER_LOCALE + ': fully specified name2 (locale: en, preferred: no)' ]))
def test_retire(self): source = OrganizationSourceFactory(version=HEAD) concept = Concept.persist_new({ **factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c1', 'parent': source, 'names': [LocalizedTextFactory.build(locale='en', name='English', locale_preferred=True)] }) Concept.persist_clone(concept.clone(), concept.created_by) concept_v1 = Concept.objects.order_by('-created_at').first() concept.refresh_from_db() self.assertEqual(concept.versions.count(), 2) self.assertFalse(concept.retired) self.assertFalse(concept.is_latest_version) self.assertTrue(concept.is_versioned_object) self.assertTrue(concept_v1.is_latest_version) concept_v1.retire(concept_v1.created_by, 'Forceful retirement') # concept will become old/prev version concept.refresh_from_db() concept_v1.refresh_from_db() self.assertFalse(concept_v1.is_latest_version) self.assertEqual(concept.versions.count(), 3) self.assertTrue(concept.retired) latest_version = concept.get_latest_version() self.assertTrue(latest_version.retired) self.assertEqual(latest_version.comment, 'Forceful retirement') self.assertEqual( concept.retire(concept.created_by), {'__all__': CONCEPT_IS_ALREADY_RETIRED} )
def test_hierarchy_one_parent_child(self): parent_concept = ConceptFactory( names=[LocalizedTextFactory(locale='en', name='English', locale_preferred=True)]) source = parent_concept.parent child_concept = Concept.persist_new({ **factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c1', 'parent': source, 'names': [LocalizedTextFactory.build(locale='en', name='English', locale_preferred=True)], 'parent_concept_urls': [parent_concept.uri] }) parent_concept_latest_version = parent_concept.get_latest_version() self.assertEqual(child_concept.errors, {}) self.assertIsNotNone(child_concept.id) self.assertEqual(list(child_concept.parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(child_concept.get_latest_version().parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(child_concept.child_concept_urls), []) self.assertEqual(list(parent_concept.child_concept_urls), [child_concept.uri]) self.assertEqual(list(parent_concept_latest_version.child_concept_urls), [child_concept.uri]) self.assertEqual(list(parent_concept_latest_version.prev_version.child_concept_urls), []) another_child_concept = Concept.persist_new({ **factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c2', 'parent': source, 'names': [LocalizedTextFactory.build(locale='en', name='English', locale_preferred=True)], 'parent_concept_urls': [parent_concept.uri] }) parent_concept_latest_version = parent_concept.get_latest_version() self.assertEqual(another_child_concept.errors, {}) self.assertIsNotNone(another_child_concept.id) self.assertEqual(list(child_concept.parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(child_concept.get_latest_version().parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(child_concept.child_concept_urls), []) self.assertEqual(list(another_child_concept.parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(another_child_concept.get_latest_version().parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(another_child_concept.child_concept_urls), []) self.assertEqual( sorted(list(parent_concept.child_concept_urls)), sorted([child_concept.uri, another_child_concept.uri]) ) self.assertEqual( sorted(list(parent_concept_latest_version.child_concept_urls)), sorted([child_concept.uri, another_child_concept.uri]) ) self.assertEqual(list(parent_concept_latest_version.prev_version.child_concept_urls), [child_concept.uri])
def process(self): if self.version: instance = self.get_queryset().first().clone() errors = Concept.create_new_version_for(instance, self.data, self.user) return errors or UPDATED instance = Concept.persist_new(self.data, self.user) if instance.id: return CREATED return instance.errors or FAILED
def test_data_type_is_valid_attribute_negative(self): source = SourceFactory(custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS) concept = Concept.persist_new( dict( mnemonic='concept1', version=HEAD, name='concept1', parent=source, concept_class='Diagnosis', datatype='XYZWERRTR', names=[LocalizedTextFactory.build(name='Grip', locale='es', locale_preferred=True)] ) ) self.assertEqual( concept.errors, dict(data_type=[OPENMRS_DATATYPE]) )
def test_concept_class_is_valid_attribute_negative(self): source = OrganizationSourceFactory(custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS) concept = Concept.persist_new( dict( mnemonic='concept1', version=HEAD, name='concept1', parent=source, concept_class='XYZQWERT', datatype='None', names=[LocalizedTextFactory.build(name='Grip', locale='es', locale_preferred=True)] ) ) self.assertEqual( concept.errors, dict(concept_class=[OPENMRS_CONCEPT_CLASS]) )
def test_locale_preferred_name_uniqueness_doesnt_apply_to_shorts(self): source = SourceFactory(custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept = Concept.persist_new( dict( mnemonic='concept', version=HEAD, name='concept', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build(name="mg", locale='en', locale_preferred=True), LocalizedTextFactory.build(name='mg', locale='en', type='Short'), ] ) ) self.assertEqual(concept.errors, {}) self.assertIsNotNone(concept.id)
def test_description_locale_is_valid_attribute_negative(self): source = SourceFactory(custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS) concept = Concept.persist_new( dict( mnemonic='concept1', version=HEAD, name='concept1', parent=source, concept_class='Diagnosis', datatype='None', names=[LocalizedTextFactory.build(locale_preferred=True)], descriptions=[LocalizedTextFactory.build(locale_preferred=True, locale='FOOBAR')] ) ) self.assertEqual( concept.errors, dict(descriptions=[OPENMRS_DESCRIPTION_LOCALE]) )
def test_a_name_can_be_equal_to_a_short_name(self): source = SourceFactory(custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept = Concept.persist_new( dict( mnemonic='concept', version=HEAD, name='concept', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build(name="aName", type=SHORT), LocalizedTextFactory.build(name='aName'), ] ) ) self.assertEqual(concept.errors, {}) self.assertIsNotNone(concept.id)
def test_at_least_one_fully_specified_name_per_concept_negative(self): source = SourceFactory(custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept = Concept.persist_new( dict( mnemonic='concept', version=HEAD, name='concept', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build(name='Fully Specified Name 1', locale='tr', type='Short'), LocalizedTextFactory.build(name='Fully Specified Name 2', locale='en', type='Short') ] ) ) self.assertEqual( concept.errors, dict(names=[OPENMRS_AT_LEAST_ONE_FULLY_SPECIFIED_NAME]) )
def test_a_name_should_be_unique(self): source = SourceFactory(custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept = Concept.persist_new( dict( mnemonic='concept', version=HEAD, name='concept', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build(name="aName"), LocalizedTextFactory.build(name='aName'), ] ) ) self.assertEqual( concept.errors, dict(names=[OPENMRS_NAMES_EXCEPT_SHORT_MUST_BE_UNIQUE]) )
def test_only_one_fully_specified_name_per_locale(self): source = SourceFactory(custom_validation_schema=CUSTOM_VALIDATION_SCHEMA_OPENMRS, version=HEAD) concept = Concept.persist_new( dict( mnemonic='concept', version=HEAD, name='concept', parent=source, concept_class='Diagnosis', datatype='None', names=[ LocalizedTextFactory.build(name="fully specified name1", locale='en'), LocalizedTextFactory.build(name='fully specified name2', locale='en'), LocalizedTextFactory.build(name='fully specified name3', locale='fr'), ] ) ) self.assertEqual( concept.errors, dict(names=[OPENMRS_ONE_FULLY_SPECIFIED_NAME_PER_LOCALE + ': fully specified name2 (locale: en, preferred: no)']) )
def test_persist_new(self): source = SourceFactory(version=HEAD) concept = Concept.persist_new({ **factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c1', 'parent': source, 'names': [LocalizedTextFactory.build(locale='en', name='English', locale_preferred=True)] }) self.assertEqual(concept.errors, {}) self.assertIsNotNone(concept.id) self.assertEqual(concept.version, str(concept.id)) self.assertEqual(source.concepts_set.count(), 1) self.assertEqual(source.concepts.count(), 1) self.assertEqual( concept.uri, '/orgs/{}/sources/{}/concepts/{}/{}/'.format( source.organization.mnemonic, source.mnemonic, concept.mnemonic, concept.id ) )
def create(self, validated_data): concept = Concept.persist_new(data=validated_data, user=self.context.get('request').user) self._errors.update(concept.errors) return concept
def test_hierarchy(self): # pylint: disable=too-many-statements # Av1 parent_concept = ConceptFactory( names=[LocalizedTextFactory(locale='en', name='English', locale_preferred=True)]) self.assertEqual(parent_concept.versions.count(), 1) source = parent_concept.parent # Av1 -> None and Av2 -> Bv1 child_concept = Concept.persist_new({ **factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c1', 'parent': source, 'names': [LocalizedTextFactory.build(locale='en', name='English', locale_preferred=True)], 'parent_concept_urls': [parent_concept.uri] }) parent_concept_latest_version = parent_concept.get_latest_version() self.assertEqual(child_concept.errors, {}) self.assertIsNotNone(child_concept.id) self.assertEqual(parent_concept.versions.count(), 2) self.assertEqual(child_concept.versions.count(), 1) self.assertEqual(list(child_concept.parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(child_concept.child_concept_urls), []) self.assertEqual(list(parent_concept.child_concept_urls), [child_concept.uri]) self.assertEqual(list(parent_concept_latest_version.child_concept_urls), [child_concept.uri]) self.assertEqual(list(parent_concept_latest_version.prev_version.child_concept_urls), []) # Av1 -> None and Av2 -> Bv1, Bv2 and Bv2 -> Cv1 child_child_concept = Concept.persist_new({ **factory.build(dict, FACTORY_CLASS=ConceptFactory), 'mnemonic': 'c2', 'parent': source, 'names': [LocalizedTextFactory.build(locale='en', name='English', locale_preferred=True)], 'parent_concept_urls': [child_concept.uri] }) self.assertEqual(child_child_concept.errors, {}) self.assertIsNotNone(child_child_concept.id) self.assertEqual(parent_concept.versions.count(), 2) self.assertEqual(child_concept.versions.count(), 2) self.assertEqual(child_child_concept.versions.count(), 1) self.assertEqual(list(child_child_concept.parent_concept_urls), [child_concept.uri]) self.assertEqual(list(child_child_concept.get_latest_version().parent_concept_urls), [child_concept.uri]) self.assertEqual(list(child_child_concept.child_concept_urls), []) self.assertEqual(list(child_concept.child_concept_urls), [child_child_concept.uri]) self.assertEqual(list(child_concept.parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(child_concept.get_latest_version().child_concept_urls), [child_child_concept.uri]) self.assertEqual(list(child_concept.get_latest_version().parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(parent_concept.child_concept_urls), [child_concept.uri]) # Av1 -> None and Av2 -> Bv1,Bv2 -> Cv1 and Av3 -> Bv3,Cv2 Concept.create_new_version_for( instance=child_child_concept.clone(), data=dict( parent_concept_urls=[parent_concept.uri], names=[dict(locale='en', name='English', locale_preferred=True)] ), user=child_child_concept.created_by ) self.assertEqual(parent_concept.versions.count(), 3) self.assertEqual(child_concept.versions.count(), 3) self.assertEqual(child_child_concept.versions.count(), 2) child_child_latest_version = child_child_concept.get_latest_version() self.assertEqual(list(child_child_concept.parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(child_child_latest_version.parent_concept_urls), [parent_concept.uri]) self.assertEqual(list(child_child_latest_version.prev_version.parent_concept_urls), [child_concept.url]) parent_concept_latest_version = parent_concept.get_latest_version() self.assertListEqual( sorted(list(parent_concept.child_concept_urls)), sorted([child_concept.uri, child_child_concept.uri]) ) self.assertEqual( sorted(list(parent_concept_latest_version.child_concept_urls)), sorted([child_concept.uri, child_child_concept.uri]) ) self.assertEqual(list(parent_concept_latest_version.prev_version.child_concept_urls), [child_concept.url]) child_latest_version = child_concept.get_latest_version() self.assertEqual(list(child_concept.child_concept_urls), []) self.assertEqual(list(child_latest_version.child_concept_urls), []) self.assertEqual(list(child_latest_version.prev_version.child_concept_urls), [child_child_concept.uri]) # Av1 -> None and Av2 -> Bv1,Bv2 -> Cv1 and Av3 -> Bv3,Cv2 and Av4 -> Bv4 -> Cv3 Concept.create_new_version_for( instance=child_child_concept.clone(), data=dict( parent_concept_urls=[child_concept.uri], names=[dict(locale='en', name='English', locale_preferred=True)] ), user=child_child_concept.created_by ) self.assertEqual(parent_concept.versions.count(), 4) self.assertEqual(child_concept.versions.count(), 4) self.assertEqual(child_child_concept.versions.count(), 3) child_child_latest_version = child_child_concept.get_latest_version() self.assertEqual( list(child_child_concept.parent_concept_urls), [child_concept.uri]) self.assertEqual( list(child_child_latest_version.parent_concept_urls), [child_concept.uri]) self.assertEqual( list(child_child_latest_version.prev_version.parent_concept_urls), [parent_concept.url]) self.assertEqual( list(child_child_latest_version.prev_version.prev_version.parent_concept_urls), [child_concept.url]) child_latest_version = child_concept.get_latest_version() self.assertEqual(list(child_concept.child_concept_urls), [child_child_concept.uri]) self.assertEqual(list(child_latest_version.child_concept_urls), [child_child_concept.uri]) self.assertEqual( list(child_latest_version.prev_version.child_concept_urls), [] ) self.assertEqual( list(child_latest_version.prev_version.prev_version.child_concept_urls), [child_child_concept.uri] ) self.assertEqual( list(child_latest_version.prev_version.prev_version.prev_version.child_concept_urls), [] ) parent_concept_latest_version = parent_concept.get_latest_version() self.assertListEqual( sorted(list(parent_concept.child_concept_urls)), sorted([child_concept.uri]) ) self.assertEqual( sorted(list(parent_concept_latest_version.child_concept_urls)), sorted([child_concept.uri]) ) self.assertEqual( sorted(list(parent_concept_latest_version.prev_version.child_concept_urls)), sorted([child_concept.uri, child_child_concept.uri]) ) self.assertEqual( list(parent_concept_latest_version.prev_version.prev_version.child_concept_urls), [child_concept.uri] ) self.assertEqual( list(parent_concept_latest_version.prev_version.prev_version.prev_version.child_concept_urls), [] ) # Av1 -> None and Av2 -> Bv1,Bv2 -> Cv1 and Av3 -> Bv3,Cv2 and Av4 -> Bv4 -> Cv3 and Av4 -> Bv5 -> None and Cv4 Concept.create_new_version_for( instance=child_child_concept.clone(), data=dict( parent_concept_urls=[], names=[dict(locale='en', name='English', locale_preferred=True)] ), user=child_child_concept.created_by ) self.assertEqual(parent_concept.versions.count(), 4) self.assertEqual(child_concept.versions.count(), 5) self.assertEqual(child_child_concept.versions.count(), 4) child_child_latest_version = child_child_concept.get_latest_version() self.assertEqual( list(child_child_concept.parent_concept_urls), []) self.assertEqual( list(child_child_latest_version.parent_concept_urls), []) self.assertEqual( list(child_child_latest_version.prev_version.parent_concept_urls), [child_concept.uri]) self.assertEqual( list(child_child_latest_version.prev_version.prev_version.parent_concept_urls), [parent_concept.url]) self.assertEqual( list(child_child_latest_version.prev_version.prev_version.prev_version.parent_concept_urls), [child_concept.url] ) child_latest_version = child_concept.get_latest_version() self.assertEqual(list(child_concept.child_concept_urls), []) self.assertEqual(list(child_latest_version.child_concept_urls), []) self.assertEqual(list(child_latest_version.prev_version.child_concept_urls), [child_child_concept.uri]) self.assertEqual( list(child_latest_version.prev_version.prev_version.child_concept_urls), [] ) self.assertEqual( list(child_latest_version.prev_version.prev_version.prev_version.child_concept_urls), [child_child_concept.uri] ) self.assertEqual( list(child_latest_version.prev_version.prev_version.prev_version.prev_version.child_concept_urls), [] ) parent_concept_latest_version = parent_concept.get_latest_version() self.assertListEqual( sorted(list(parent_concept.child_concept_urls)), sorted([child_concept.uri]) ) self.assertEqual( sorted(list(parent_concept_latest_version.child_concept_urls)), sorted([child_concept.uri]) ) self.assertEqual( sorted(list(parent_concept_latest_version.prev_version.child_concept_urls)), sorted([child_concept.uri, child_child_concept.uri]) ) self.assertEqual( list(parent_concept_latest_version.prev_version.prev_version.child_concept_urls), [child_concept.uri] ) self.assertEqual( list(parent_concept_latest_version.prev_version.prev_version.prev_version.child_concept_urls), [] )