Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: business layer tests for update collection #3524

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions backend/layers/business/business.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dataclasses import dataclass
from typing import Iterable, Optional
from typing import Iterable, List, Optional

from backend.layers.common.entities import CollectionId, CollectionMetadata, CollectionVersion, CollectionVersionId, DatasetArtifact, DatasetId, DatasetStatus, DatasetVersion, DatasetVersionId
from backend.layers.common.entities import CollectionId, CollectionMetadata, CollectionVersion, CollectionVersionId, DatasetArtifact, DatasetId, DatasetStatus, DatasetVersion, DatasetVersionId, Link
from backend.layers.persistence.persistence import DatabaseProviderInterface
from backend.layers.thirdparty.crossref_provider import CrossrefProviderInterface
from backend.layers.thirdparty.step_function_provider import StepFunctionProviderInterface
Expand All @@ -20,6 +20,19 @@ class DatasetArtifactDownloadData:
file_size: int
presigned_url: str

@dataclass
class CollectionMetadataUpdate:
"""
This class can be used to issue an update to the collection metadata.
Since we support partial updates, i.e. missing fields will be ignored,
all the fields are marked an optional
"""
name: Optional[str]
description: Optional[str]
contact_name: Optional[str]
contact_email: Optional[str]
links: Optional[List[Link]]

class BusinessLogicInterface:

# Get_collections
Expand Down Expand Up @@ -80,7 +93,7 @@ def delete_collection(self, collection_id: CollectionId) -> None:
# Can either return nothing or the metadata of the updated collection

# TODO: body should be a dataclass?
def update_collection_version(self, version_id: CollectionVersionId, body: dict) -> None:
def update_collection_version(self, version_id: CollectionVersionId, body: CollectionMetadataUpdate) -> None:
pass

# Create_collection_version
Expand Down
2 changes: 1 addition & 1 deletion backend/layers/common/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class CollectionMetadata:
description: str
contact_name: str
contact_email: str
links: List[Link] # TODO: use a dataclass
links: List[Link]


@dataclass
Expand Down
116 changes: 78 additions & 38 deletions tests/unit/backend/layers/business/test_business.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from backend.layers.thirdparty.step_function_provider import StepFunctionProviderInterface

from backend.corpora.common.providers.crossref_provider import CrossrefException
from backend.layers.business.business import BusinessLogic, CollectionQueryFilter, DatasetArtifactDownloadData
from backend.layers.business.business import BusinessLogic, CollectionMetadataUpdate, CollectionQueryFilter, DatasetArtifactDownloadData
from backend.layers.business.exceptions import CollectionUpdateException, InvalidLinkException, \
CollectionCreationException, DatasetIngestException, CollectionPublishException
from backend.layers.common.entities import CollectionMetadata, CollectionVersion, DatasetArtifact, DatasetMetadata, DatasetStatus, DatasetVersionId, Link
Expand Down Expand Up @@ -310,29 +310,65 @@ def test_update_collection_ok(self):
A collection version should be updated when using `update_collection`
"""
version = self.initialize_unpublished_collection()
body = {
"name": "new collection name",
"description": "new collection description",
"contact_name": "new contact name",
"contact_email": "new_email@czi.com",
}

body = CollectionMetadataUpdate(
name="new collection name",
description="new collection description",
contact_name="new contact name",
contact_email="new_email@czi.com",
links=[Link("test link 2", "other", "http://example.com/other")],
)

self.business_logic.update_collection_version(version.version_id, body)

updated_version = self.database_provider.get_collection_version(version.version_id)
self.assertEqual(updated_version.metadata.name, body.name)
self.assertEqual(updated_version.metadata.description, body.description)
self.assertEqual(updated_version.metadata.contact_name, body.contact_name)
self.assertEqual(updated_version.metadata.contact_email, body.contact_email)
self.assertEqual(updated_version.metadata.links, body.links)

def test_update_collection_partial_ok(self):
"""
`update_collection` should support partial updates: if only a subset of the fields are specified,
the previous field should not be modified
"""
version = self.initialize_unpublished_collection()

body = CollectionMetadataUpdate(
name="new collection name",
description="new collection description",
contact_name=None,
contact_email=None,
links=None,
)

self.business_logic.update_collection_version(version.version_id, body)

updated_version = self.database_provider.get_collection_version(version.version_id)
self.assertEqual(updated_version.metadata.name, body["name"])
self.assertEqual(updated_version.metadata.description, body["description"])
self.assertEqual(updated_version.metadata.contact_name, body["contact_name"])
self.assertEqual(updated_version.metadata.contact_email, body["contact_email"])

# These two fields should be updated
self.assertEqual(updated_version.metadata.name, body.name)
self.assertEqual(updated_version.metadata.description, body.description)

# These three fields should remain the same
self.assertEqual(updated_version.metadata.contact_name, version.metadata.contact_name)
self.assertEqual(updated_version.metadata.contact_email, version.metadata.contact_email)
self.assertEqual(updated_version.metadata.links, version.metadata.links)


def test_update_collection_wrong_params_fail(self):
"""
Updating a collection with a payload with missing fields should fail
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this appears to describe the opposite feature of the test directly above

"""
version = self.initialize_unpublished_collection()
body = {
"name": "new collection name",
}
body = CollectionMetadataUpdate(
name="new collection name",
description="new collection description",
contact_name=None,
contact_email=None,
links=None,
)

with self.assertRaises(CollectionUpdateException) as ex:
self.business_logic.update_collection_version(version.version_id, body)
Expand All @@ -343,17 +379,20 @@ def test_update_collection_wrong_params_fail(self):
{"name": "contact_email", "reason": "Cannot be blank."},
])

# TODO: I would recommend adding more validation logic testing (see existing TestVerifyCollection)
# in a separate unit test case later

def test_update_published_collection_fail(self):
"""
Updating a collection version that is published should fail
"""
version = self.initialize_published_collection()
body = CollectionMetadataUpdate(
name="new collection name",
description="new collection description",
contact_name="new contact name",
contact_email="new_email@czi.com",
)

with self.assertRaises(CollectionUpdateException):
self.business_logic.update_collection_version(version.version_id, {"name": "test"})
self.business_logic.update_collection_version(version.version_id, body)

def test_update_collection_same_doi(self):
"""
Expand All @@ -370,13 +409,13 @@ def test_update_collection_same_doi(self):
self.crossref_provider.fetch_metadata.assert_called_once()
self.crossref_provider.fetch_metadata.reset_mock()

body = {
"name": "new collection name",
"description": "new collection description",
"contact_name": "new contact name",
"contact_email": "new_email@czi.com",
"links": links
}
body = CollectionMetadataUpdate(
name=None,
description=None,
contact_name=None,
contact_email=None,
links=links,
)

self.business_logic.update_collection_version(version.version_id, body)

Expand All @@ -398,13 +437,13 @@ def test_update_collection_change_doi(self):
self.crossref_provider.fetch_metadata.assert_called_once()
self.crossref_provider.fetch_metadata.reset_mock()

body = {
"name": "new collection name",
"description": "new collection description",
"contact_name": "new contact name",
"contact_email": "new_email@czi.com",
"links": [Link("new test doi", "DOI", "http://new.test.doi")]
}
body = CollectionMetadataUpdate(
name=None,
description=None,
contact_name=None,
contact_email=None,
links=[Link("new test doi", "DOI", "http://new.test.doi")],
)

expected_updated_publisher_metadata = {"authors": ["New Test Author"]}
self.crossref_provider.fetch_metadata = Mock(return_value=expected_updated_publisher_metadata)
Expand Down Expand Up @@ -703,12 +742,13 @@ def test_publish_version_with_updated_metadata_ok(self):
published_collection = self.initialize_published_collection()
new_version = self.business_logic.create_collection_version(published_collection.collection_id)

body = {
"name": "new collection name",
"description": "new collection description",
"contact_name": "new contact name",
"contact_email": "new_email@czi.com",
}
body = CollectionMetadataUpdate(
name="new collection name",
description="new collection description",
contact_name="new contact name",
contact_email="new_email@czi.com",
links=None,
)

self.business_logic.update_collection_version(new_version.version_id, body)
self.business_logic.publish_collection_version(new_version.version_id)
Expand Down