diff --git a/pyproject.toml b/pyproject.toml index e053441..2ed432f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,4 +57,7 @@ python-common = { index = "gitlab" } [[tool.uv.index]] name = "gitlab" -url = "https://git.o-c.space/api/v4/projects/689/packages/pypi/simple" \ No newline at end of file +url = "https://git.o-c.space/api/v4/projects/689/packages/pypi/simple" + +[tool.pytest.ini_options] +pythonpath = ["."] diff --git a/tests/unit/datacosmos/stac/collection/collection_client/test_create_collection.py b/tests/unit/datacosmos/stac/collection/collection_client/test_create_collection.py new file mode 100644 index 0000000..fb7caae --- /dev/null +++ b/tests/unit/datacosmos/stac/collection/collection_client/test_create_collection.py @@ -0,0 +1,63 @@ +from unittest.mock import MagicMock, patch + +from pystac import Collection, Extent, SpatialExtent, TemporalExtent +from pystac.utils import str_to_datetime + +from config.config import Config +from config.models.m2m_authentication_config import M2MAuthenticationConfig +from datacosmos.datacosmos_client import DatacosmosClient +from datacosmos.stac.collection.collection_client import CollectionClient + + +@patch("requests_oauthlib.OAuth2Session.fetch_token") +@patch.object(DatacosmosClient, "post") +@patch("datacosmos.stac.collection.collection_client.check_api_response") +def test_create_collection(mock_check_api_response, mock_post, mock_fetch_token): + """Test creating a STAC collection.""" + + mock_fetch_token.return_value = {"access_token": "mock-token", "expires_in": 3600} + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_post.return_value = mock_response + mock_check_api_response.return_value = None + + collection = Collection( + id="test-collection", + description="A test STAC collection", + extent=Extent( + SpatialExtent([[-180.0, -90.0, 180.0, 90.0]]), + TemporalExtent( + [ + [ + str_to_datetime("2020-01-01T00:00:00Z"), + str_to_datetime("2023-12-31T23:59:59Z"), + ] + ] + ), + ), + license="proprietary", + stac_extensions=[], + ) + + config = Config( + authentication=M2MAuthenticationConfig( + type="m2m", + client_id="test-client-id", + client_secret="test-client-secret", + token_url="https://mock.token.url/oauth/token", + audience="https://mock.audience", + ) + ) + + client = DatacosmosClient(config=config) + collection_client = CollectionClient(client) + + collection_client.create_collection(collection) + + mock_post.assert_called_once_with( + client.config.stac.as_domain_url().with_suffix("/collections"), + json=collection.to_dict(), + ) + + mock_check_api_response.assert_called_once_with(mock_response) diff --git a/tests/unit/datacosmos/stac/collection/collection_client/test_delete_collection.py b/tests/unit/datacosmos/stac/collection/collection_client/test_delete_collection.py new file mode 100644 index 0000000..9f7c93e --- /dev/null +++ b/tests/unit/datacosmos/stac/collection/collection_client/test_delete_collection.py @@ -0,0 +1,44 @@ +from unittest.mock import MagicMock, patch + +from config.config import Config +from config.models.m2m_authentication_config import M2MAuthenticationConfig +from datacosmos.datacosmos_client import DatacosmosClient +from datacosmos.stac.collection.collection_client import CollectionClient + + +@patch("requests_oauthlib.OAuth2Session.fetch_token") +@patch.object(DatacosmosClient, "delete") +@patch("datacosmos.stac.collection.collection_client.check_api_response") +def test_delete_collection(mock_check_api_response, mock_delete, mock_fetch_token): + """Test deleting a STAC collection.""" + + mock_fetch_token.return_value = {"access_token": "mock-token", "expires_in": 3600} + + mock_response = MagicMock() + mock_response.status_code = 204 + mock_delete.return_value = mock_response + mock_check_api_response.return_value = None + + config = Config( + authentication=M2MAuthenticationConfig( + type="m2m", + client_id="test-client-id", + client_secret="test-client-secret", + token_url="https://mock.token.url/oauth/token", + audience="https://mock.audience", + ) + ) + + client = DatacosmosClient(config=config) + collection_client = CollectionClient(client) + + collection_client.delete_collection("test-collection") + + mock_delete.assert_called_once_with( + client.config.stac.as_domain_url().with_suffix("/collections/test-collection") + ) + + mock_check_api_response.assert_called_once_with(mock_response) + mock_delete.assert_called_with( + collection_client.base_url.with_suffix("/collections/test-collection") + ) diff --git a/tests/unit/datacosmos/stac/collection/collection_client/test_fetch_collection.py b/tests/unit/datacosmos/stac/collection/collection_client/test_fetch_collection.py new file mode 100644 index 0000000..3daa667 --- /dev/null +++ b/tests/unit/datacosmos/stac/collection/collection_client/test_fetch_collection.py @@ -0,0 +1,73 @@ +from unittest.mock import MagicMock, patch + +from pystac import Collection +from pystac.utils import datetime_to_str + +from config.config import Config +from config.models.m2m_authentication_config import M2MAuthenticationConfig +from datacosmos.datacosmos_client import DatacosmosClient +from datacosmos.stac.collection.collection_client import CollectionClient + + +@patch("requests_oauthlib.OAuth2Session.fetch_token") +@patch.object(DatacosmosClient, "get") +@patch("datacosmos.stac.collection.collection_client.check_api_response") +def test_fetch_collection(mock_check_api_response, mock_get, mock_fetch_token): + """Test fetching a single STAC collection by ID.""" + + mock_fetch_token.return_value = {"access_token": "mock-token", "expires_in": 3600} + + mock_response = MagicMock() + mock_response.json.return_value = { + "type": "Collection", + "id": "test-collection", + "stac_version": "1.1.0", + "description": "A test STAC collection", + "license": "proprietary", + "extent": { + "spatial": {"bbox": [[-180.0, -90.0, 180.0, 90.0]]}, + "temporal": { + "interval": [["2020-01-01T00:00:00Z", "2023-12-31T23:59:59Z"]] + }, + }, + "links": [], + "stac_extensions": [], + } + mock_response.status_code = 200 + mock_get.return_value = mock_response + mock_check_api_response.return_value = None + + config = Config( + authentication=M2MAuthenticationConfig( + type="m2m", + client_id="test-client-id", + client_secret="test-client-secret", + token_url="https://mock.token.url/oauth/token", + audience="https://mock.audience", + ) + ) + + client = DatacosmosClient(config=config) + collection_client = CollectionClient(client) + + collection = collection_client.fetch_collection("test-collection") + + assert isinstance(collection, Collection) + assert collection.id == "test-collection" + assert collection.description == "A test STAC collection" + assert collection.license == "proprietary" + assert collection.extent.spatial.bboxes == [[-180.0, -90.0, 180.0, 90.0]] + + actual_temporal_intervals = [ + [datetime_to_str(interval[0]), datetime_to_str(interval[1])] + for interval in collection.extent.temporal.intervals + ] + expected_temporal_intervals = [["2020-01-01T00:00:00Z", "2023-12-31T23:59:59Z"]] + + assert actual_temporal_intervals == expected_temporal_intervals + + mock_get.assert_called_once() + mock_check_api_response.assert_called_once_with(mock_response) + mock_get.assert_called_with( + collection_client.base_url.with_suffix("/collections/test-collection") + ) diff --git a/tests/unit/datacosmos/stac/collection/collection_client/test_update_collection.py b/tests/unit/datacosmos/stac/collection/collection_client/test_update_collection.py new file mode 100644 index 0000000..3994620 --- /dev/null +++ b/tests/unit/datacosmos/stac/collection/collection_client/test_update_collection.py @@ -0,0 +1,54 @@ +from unittest.mock import MagicMock, patch + +from config.config import Config +from config.models.m2m_authentication_config import M2MAuthenticationConfig +from datacosmos.datacosmos_client import DatacosmosClient +from datacosmos.stac.collection.collection_client import CollectionClient +from datacosmos.stac.collection.models.collection_update import CollectionUpdate + + +@patch("requests_oauthlib.OAuth2Session.fetch_token") +@patch.object(DatacosmosClient, "patch") +@patch("datacosmos.stac.collection.collection_client.check_api_response") +def test_update_collection(mock_check_api_response, mock_patch, mock_fetch_token): + """Test updating a STAC collection.""" + + mock_fetch_token.return_value = {"access_token": "mock-token", "expires_in": 3600} + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_patch.return_value = mock_response + mock_check_api_response.return_value = None + + update_data = CollectionUpdate( + title="Updated Collection Title", + description="Updated description", + keywords=["updated", "collection"], + license="proprietary", + ) + + config = Config( + authentication=M2MAuthenticationConfig( + type="m2m", + client_id="test-client-id", + client_secret="test-client-secret", + token_url="https://mock.token.url/oauth/token", + audience="https://mock.audience", + ) + ) + + client = DatacosmosClient(config=config) + collection_client = CollectionClient(client) + + collection_client.update_collection("test-collection", update_data) + + mock_patch.assert_called_once_with( + client.config.stac.as_domain_url().with_suffix("/collections/test-collection"), + json=update_data.model_dump(by_alias=True, exclude_none=True), + ) + + mock_check_api_response.assert_called_once_with(mock_response) + mock_patch.assert_called_with( + collection_client.base_url.with_suffix("/collections/test-collection"), + json=update_data.model_dump(by_alias=True, exclude_none=True), + )