"""Tests for Sound Recording metadata logic.""" from datetime import datetime from unittest.mock import patch import pytest from oto import response as oto_response from analytics.logic import sound_recording_metadata from analytics.schemas.sound_recording_metadata import SoundRecordingMetadataSchema ISRC = "GBUM71105426" LABEL_ID = 7123 ARTIST_NAME = "Lil Jon" PRODUCT_ID_1 = 1231 PRODUCT_ID_2 = 1232 PRODUCT_ID_3 = 1233 PRODUCT_1 = { "release_id": PRODUCT_ID_1, "is_deleted": True, "release_date": "2020-01-01", "sales_start_date": "2020-01-01", "release_artist": ARTIST_NAME, } PRODUCT_1_DATE = datetime(2020, 1, 1).date() PRODUCT_2 = { "release_id": PRODUCT_ID_2, "is_deleted": False, "release_date": "2020-01-02", "sales_start_date": "2020-01-02", "release_artist": ARTIST_NAME, } PRODUCT_2_DATE = datetime(2020, 1, 2).date() PRODUCT_3 = { "release_id": PRODUCT_ID_3, "is_deleted": False, "release_date": "2020-01-03", "sales_start_date": "2020-01-03", "release_artist": ARTIST_NAME, } PRODUCT_3_DATE = datetime(2020, 1, 3).date() TRACK_1 = { "isrc": ISRC, "track_name": "track 1", "label_id": LABEL_ID, "subaccount_id": None, "first_id": f"product:{PRODUCT_ID_1}", "product": PRODUCT_1, "artists": [{"artist_name": ARTIST_NAME, "type": "performer"}], } TRACK_2 = { "isrc": ISRC, "track_name": "track 2", "label_id": LABEL_ID, "subaccount_id": None, "first_id": f"product:{PRODUCT_ID_2}", "product": PRODUCT_2, "artists": [{"artist_name": ARTIST_NAME, "type": "performer"}], } TRACK_3 = { "isrc": ISRC, "track_name": "track 3", "label_id": LABEL_ID, "subaccount_id": None, "first_id": f"product:{PRODUCT_ID_3}", "product": PRODUCT_3, "artists": [{"artist_name": ARTIST_NAME, "type": "performer"}], } QUERY_RESPONSE_MIXED = [TRACK_1, TRACK_2, TRACK_3] 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_range_key_mixed(): """Mock dynamo.query_by_range_key with a mix of deleted/active tracks.""" with patch( "analytics.logic.sound_recording_metadata.dynamo.query_by_range_key" ) as query: query.return_value = QUERY_RESPONSE_MIXED yield query @pytest.fixture() def mock_query_by_range_key_deleted(): """Mock dynamo.query_by_range_key with only deleted tracks.""" with patch( "analytics.logic.sound_recording_metadata.dynamo.query_by_range_key" ) as query: query.return_value = [TRACK_1] 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 TestGetSoundRecordingMetadata: """Test get_sound_recording_metadata.""" def test_returns_latest_non_deleted(self, mock_query_by_range_key_mixed): """Latest non-deleted product is returned (deleted PRODUCT_1 dropped).""" result = sound_recording_metadata.get_sound_recording_metadata( {"isrc": ISRC, "include_deleted": False}, PERMISSIONS_ARTIST ) assert isinstance(result, oto_response.Response) assert result.status == 200 # Latest non-deleted product is PRODUCT_3 assert result.message["isrc"] == ISRC assert result.message["name"] == "track 3" # Only the two non-deleted products survive assert len(result.message["products"]) == 2 def test_include_deleted(self, mock_query_by_range_key_deleted): """When include_deleted=True, deleted products are included.""" result = sound_recording_metadata.get_sound_recording_metadata( {"isrc": ISRC, "include_deleted": True}, PERMISSIONS_ARTIST ) assert result.status == 200 assert len(result.message["products"]) == 1 def test_not_found(self, mock_query_by_range_key_mixed): """Returns 404 when no items match.""" mock_query_by_range_key_mixed.return_value = [] result = sound_recording_metadata.get_sound_recording_metadata( {"isrc": ISRC, "include_deleted": False}, PERMISSIONS_ARTIST ) assert result.status == 404 def test_dynamo_called_with_translated_permissions( self, mock_query_by_range_key_mixed ): """Dynamo receives old-style permissions_filter (not permission_* keys).""" sound_recording_metadata.get_sound_recording_metadata( {"isrc": ISRC, "include_deleted": False}, PERMISSIONS_LABEL ) _, kwargs = mock_query_by_range_key_mixed.call_args assert kwargs["permissions_filter"] == { "artist_ids": None, "subaccount_ids": None, "label_ids": [LABEL_ID], } def test_label_message_matches_schema(self, mock_query_by_range_key_mixed): """Final response equals SoundRecordingMetadataSchema.normalize output.""" result = sound_recording_metadata.get_sound_recording_metadata( {"isrc": ISRC, "include_deleted": False}, PERMISSIONS_LABEL ) # Reconstruct the expected payload by running normalize against the # patched data the logic would have produced. expected_message = SoundRecordingMetadataSchema.normalize( { "isrc": ISRC, "track_name": "track 3", "first_id": f"product:{PRODUCT_ID_3}", "label_id": LABEL_ID, "subaccount_id": None, "artist_name": ARTIST_NAME, "artists": [{"artist_name": ARTIST_NAME, "type": "performer"}], "product": { **PRODUCT_3, "release_date": PRODUCT_3_DATE, "sales_start_date": PRODUCT_3_DATE, "artists": [{"artist_name": ARTIST_NAME, "type": "performer"}], }, "products": [ { **PRODUCT_3, "release_date": PRODUCT_3_DATE, "sales_start_date": PRODUCT_3_DATE, "artists": [{"artist_name": ARTIST_NAME, "type": "performer"}], }, { **PRODUCT_2, "release_date": PRODUCT_2_DATE, "sales_start_date": PRODUCT_2_DATE, "artists": [{"artist_name": ARTIST_NAME, "type": "performer"}], }, ], }, { "label_ids": [LABEL_ID], "subaccount_ids": None, "artist_ids": None, }, ) assert result.message == expected_message