"""Tests for product_metadata logic.""" from unittest.mock import patch import pytest from oto import response as oto_response from analytics.connectors.dynamo import RANGE_KEY from analytics.logic import product_metadata from analytics.schemas import product_metadata as schema PRODUCT_ID = 1234 LABEL_ID = 7123 SUBACCOUNT_ID = 456789 TRACK_ISRC_1 = "NOO1" TRACK_ISRC_2 = "NOO2" ARTIST_NAME = "Lil Jon" FIRST_ID = f"product:{PRODUCT_ID}" SECOND_ID_1 = f"isrc:{TRACK_ISRC_1}" SECOND_ID_2 = f"isrc:{TRACK_ISRC_2}" POS1 = {"track_number": 1, "track_cd": 1, "track_type": "music"} POS2 = {"track_number": 2, "track_cd": 1, "track_type": "music"} QUERY_RESPONSE_BY_HASH_KEY = [ { RANGE_KEY: FIRST_ID, "artist_name": ARTIST_NAME, "label_id": LABEL_ID, "subaccount_id": None, }, { RANGE_KEY: SECOND_ID_1, "track_name": "track 1", "isrc": TRACK_ISRC_1, "label_id": LABEL_ID, "subaccount_id": None, **POS1, }, { RANGE_KEY: SECOND_ID_2, "track_name": "track 2", "isrc": TRACK_ISRC_2, "label_id": LABEL_ID, "subaccount_id": None, **POS2, }, ] PERMISSIONS_LABEL = { "permission_label_ids": [LABEL_ID], "permission_subaccount_ids": None, "permission_artist_ids": None, "permission_label_participant_ids": None, "permission_feed_ids": [1, 2], } PERMISSIONS_ARTIST = { "permission_label_ids": None, "permission_subaccount_ids": None, "permission_artist_ids": [1, 2, 3], "permission_label_participant_ids": None, "permission_feed_ids": [1, 2], } @pytest.fixture() def mock_query_by_hash_key(): """Mock dynamo.query_by_hash_key.""" with patch("analytics.logic.product_metadata.dynamo.query_by_hash_key") as query: query.return_value = QUERY_RESPONSE_BY_HASH_KEY yield query @pytest.fixture(autouse=True) def no_cache(): """Mock out caching of response.""" with patch("analytics.connectors.redis.client.get") as get: get.return_value = None yield get class TestGetProductMetadata: """Test get_product_metadata logic.""" def test_success(self, mock_query_by_hash_key): """Returns Response object with normalized metadata.""" result = product_metadata.get_product_metadata( {"product_id": PRODUCT_ID}, PERMISSIONS_LABEL ) assert isinstance(result, oto_response.Response) assert result.status == 200 assert result.message["product_id"] == str(PRODUCT_ID) assert result.message["label_id"] == LABEL_ID assert len(result.message["tracks"]) == 2 def test_not_found(self, mock_query_by_hash_key): """Returns 404 when no items match.""" mock_query_by_hash_key.return_value = [] result = product_metadata.get_product_metadata( {"product_id": PRODUCT_ID}, PERMISSIONS_LABEL ) assert result.status == 404 def test_product_id_mismatch(self, mock_query_by_hash_key): """Returns 404 when product key not present in items.""" result = product_metadata.get_product_metadata( {"product_id": PRODUCT_ID + 1}, PERMISSIONS_LABEL ) assert result.status == 404 def test_subaccount(self, mock_query_by_hash_key): """Subaccount permissions are passed through to schema context.""" items_with_subaccount = [ {**QUERY_RESPONSE_BY_HASH_KEY[0], "subaccount_id": SUBACCOUNT_ID}, *QUERY_RESPONSE_BY_HASH_KEY[1:], ] mock_query_by_hash_key.return_value = items_with_subaccount permissions_subaccount = { **PERMISSIONS_LABEL, "permission_subaccount_ids": [SUBACCOUNT_ID], } result = product_metadata.get_product_metadata( {"product_id": PRODUCT_ID}, permissions_subaccount ) assert result.status == 200 assert result.message == schema.ProductMetadataSchema.normalize( { "product_id": PRODUCT_ID, "label_id": LABEL_ID, "subaccount_id": SUBACCOUNT_ID, "tracks": result.message["tracks"], "artist_name": ARTIST_NAME, "artists": [{"artist_name": ARTIST_NAME, "type": "performer"}], RANGE_KEY: FIRST_ID, }, { "label_ids": [LABEL_ID], "subaccount_ids": [SUBACCOUNT_ID], "artist_ids": None, }, ) def test_dynamo_called_with_translated_permissions(self, mock_query_by_hash_key): """Dynamo receives old-style permissions_filter (not permission_* keys).""" product_metadata.get_product_metadata( {"product_id": PRODUCT_ID}, PERMISSIONS_ARTIST ) _, kwargs = mock_query_by_hash_key.call_args assert kwargs["permissions_filter"] == { "artist_ids": [1, 2, 3], "subaccount_ids": None, "label_ids": None, }