|
28 | 28 | from core.concepts.documents import ConceptDocument |
29 | 29 | from core.concepts.models import Concept |
30 | 30 | from core.concepts.search import ConceptFuzzySearch |
31 | | -from core.concepts.serializers import ConceptListSerializer, ConceptDetailSerializer |
| 31 | +from core.concepts.serializers import ConceptListSerializer, ConceptDetailSerializer, ConceptAbstractSerializer |
32 | 32 | from core.concepts.tests.factories import ConceptFactory, ConceptNameFactory, ConceptDescriptionFactory |
33 | 33 | from core.concepts.views import MetadataToConceptsListView |
34 | 34 | from core.integration_tests.test_utils import SourceChildListQueryCountMixin |
@@ -4628,3 +4628,79 @@ def test_post_429_refused_by_capacity_limit(self, reranker_mock): |
4628 | 4628 | self.assertEqual(response.status_code, 429) |
4629 | 4629 | self.assertEqual(response.data['error_code'], 'capacity_exceeded') |
4630 | 4630 | reranker_mock.assert_not_called() |
| 4631 | + |
| 4632 | + |
| 4633 | +class ConceptListIncludeMappingsTest(OCLAPITestCase): |
| 4634 | + def setUp(self): |
| 4635 | + super().setUp() |
| 4636 | + self.source = OrganizationSourceFactory() |
| 4637 | + self.other_source = OrganizationSourceFactory() |
| 4638 | + self.concepts = [ConceptFactory(parent=self.source) for _ in range(3)] |
| 4639 | + self.other_concept = ConceptFactory(parent=self.other_source) |
| 4640 | + self.mappings = {} |
| 4641 | + for concept in self.concepts: |
| 4642 | + self.mappings[concept.mnemonic] = { |
| 4643 | + MappingFactory( |
| 4644 | + parent=self.source, from_concept=concept, to_concept=self.concepts[0], map_type=f'type{index}' |
| 4645 | + ).id for index in range(2) |
| 4646 | + } |
| 4647 | + self.mappings[self.other_concept.mnemonic] = {MappingFactory( |
| 4648 | + parent=self.other_source, from_concept=self.other_concept, to_concept=self.other_concept).id} |
| 4649 | + |
| 4650 | + def mappings_by_concept(self, url): |
| 4651 | + response = self.client.get(url + ('&' if '?' in url else '?') + 'verbose=true&includeMappings=true') |
| 4652 | + self.assertEqual(response.status_code, 200) |
| 4653 | + return {row['id']: sorted(mapping['uuid'] for mapping in row['mappings']) for row in response.data} |
| 4654 | + |
| 4655 | + def assert_same_with_and_without_batching(self, url, expected=None): |
| 4656 | + batched = self.mappings_by_concept(url) |
| 4657 | + with patch.object(ConceptAbstractSerializer, 'preload_page', lambda *args: None): |
| 4658 | + per_concept = self.mappings_by_concept(url) |
| 4659 | + self.assertEqual(batched, per_concept) |
| 4660 | + if expected is not None: |
| 4661 | + self.assertEqual( |
| 4662 | + batched, {mnemonic: sorted(str(_id) for _id in ids) for mnemonic, ids in expected.items()}) |
| 4663 | + |
| 4664 | + def test_source_head_list(self): |
| 4665 | + self.assert_same_with_and_without_batching( |
| 4666 | + self.source.uri + 'concepts/', {c.mnemonic: self.mappings[c.mnemonic] for c in self.concepts}) |
| 4667 | + |
| 4668 | + def test_global_list_across_sources(self): |
| 4669 | + batched = self.mappings_by_concept('/concepts/') |
| 4670 | + self.assertEqual(len(batched), 4) |
| 4671 | + self.assert_same_with_and_without_batching('/concepts/', { |
| 4672 | + mnemonic: ids for mnemonic, ids in self.mappings.items()}) |
| 4673 | + |
| 4674 | + def test_source_version_list(self): |
| 4675 | + version = OrganizationSourceFactory( |
| 4676 | + organization=self.source.organization, mnemonic=self.source.mnemonic, version='v1') |
| 4677 | + for concept in self.concepts: |
| 4678 | + version.concepts.add(concept.get_latest_version()) |
| 4679 | + self.assert_same_with_and_without_batching(version.uri + 'concepts/') |
| 4680 | + self.assertTrue(any(self.mappings_by_concept(version.uri + 'concepts/').values())) |
| 4681 | + |
| 4682 | + def test_concept_versions_list(self): |
| 4683 | + self.assert_same_with_and_without_batching( |
| 4684 | + self.concepts[1].versions_url, {self.concepts[1].mnemonic: self.mappings[self.concepts[1].mnemonic]}) |
| 4685 | + |
| 4686 | + def test_collection_list_ignores_mappings_outside_expansion(self): |
| 4687 | + collection = OrganizationCollectionFactory() |
| 4688 | + expansion = ExpansionFactory(collection_version=collection) |
| 4689 | + collection.expansion_uri = expansion.uri |
| 4690 | + collection.save() |
| 4691 | + concept = self.concepts[0] |
| 4692 | + kept = Mapping.objects.filter(parent=self.source, from_concept=concept).first() |
| 4693 | + expansion.concepts.add(concept.get_latest_version()) |
| 4694 | + expansion.mappings.add(kept) |
| 4695 | + |
| 4696 | + url = collection.uri + 'HEAD/concepts/' |
| 4697 | + self.assert_same_with_and_without_batching(url) |
| 4698 | + shown = {uuid for uuids in self.mappings_by_concept(url).values() for uuid in uuids} |
| 4699 | + self.assertLessEqual(shown, {str(kept.id)}) |
| 4700 | + |
| 4701 | + def test_inverse_mappings_are_unchanged(self): |
| 4702 | + url = self.source.uri + 'concepts/?verbose=true&includeInverseMappings=true' |
| 4703 | + batched = self.client.get(url).data |
| 4704 | + with patch.object(ConceptAbstractSerializer, 'preload_page', lambda *args: None): |
| 4705 | + per_concept = self.client.get(url).data |
| 4706 | + self.assertEqual(batched, per_concept) |
0 commit comments