"""Unit tests for format_product logic.""" from src.logic import format_product # --- Helpers --- def _minimal_product(**overrides: object) -> dict: base: dict = { "product_id": 1, "product_name": "Test Album", "format": "Album", "artists": [], "product_localizations": [], "tracks": [], } base.update(overrides) return base def _minimal_track(**overrides: object) -> dict: base: dict = { "trackNumber": 1, "volumeNumber": 1, "trackName": "Test Track", "primaryArtists": [], "writers": [], "performers": [], "localizations": [], } base.update(overrides) return base # --- Release-level field tests --- def test_product_id_mapped_to_release_id() -> None: """product_id is mapped to release_id in the output.""" result = format_product.process_product(_minimal_product(product_id=9999)) assert result["release_id"] == 9999 def test_product_name_mapped_to_title() -> None: """product_name is mapped to title in the output.""" result = format_product.process_product(_minimal_product(product_name="My Album")) assert result["title"] == "My Album" def test_subgenre_flattened() -> None: """Nested subgenre/genre objects are flattened to string fields.""" raw = _minimal_product( subgenre={ "id": 23, "name": "Ambient", "genre": {"id": 2, "name": "Electronic"}, } ) result = format_product.process_product(raw) assert result["genre"] == "Electronic" assert result["subgenre"] == "Ambient" def test_strips_internal_release_fields(mock_product_metadata: dict) -> None: """Internal and system fields are absent from the output.""" result = format_product.process_product(mock_product_metadata) stripped = [ "product_code", "delivered_version", "bulk_session", "image_location", "sale_start_date", "preorder_date", "previewable", "label", "label_participations", "album_pricing_tier", "track_pricing_tier", "release_schedule", "release_correction", "review_history", "validation", "special_instructions", ] for field in stripped: assert field not in result, f"Expected {field!r} to be stripped" def test_release_artist_id_stripped() -> None: """ArtistId is not present in output release_artists.""" raw = _minimal_product( artists=[ { "artistId": "123", "artistName": "Moist", "artistType": "primary_artist", } ] ) result = format_product.process_product(raw) artist = result["release_artists"][0] assert "artist_id" not in artist assert artist["artist_name"] == "Moist" assert artist["artist_type"] == "primary_artist" # --- Track-level field tests --- def test_strips_internal_track_fields(mock_product_metadata: dict) -> None: """Internal track fields are absent from output tracks.""" result = format_product.process_product(mock_product_metadata) track = result["tracks"][0] stripped = [ "isrc", "isrc_info", "tuid", "offer_type", "ownership_rights", "p_info", "preview_start_time", "instant_grats", "focus_track", "audio_attributes", "rights_attributes", "validation", "label_sound_recording", "participations", ] for field in stripped: assert field not in track, f"Expected {field!r} to be stripped" def test_track_name_mapped_to_title() -> None: """TrackName is mapped to title on the output track.""" raw = _minimal_product(tracks=[_minimal_track(trackName="My Song")]) result = format_product.process_product(raw) assert result["tracks"][0]["title"] == "My Song" # --- artists_by_type grouping --- def test_primary_artists_grouped_by_type() -> None: """PrimaryArtists grouped by type; 'performer' renamed to 'primary_artist'.""" track = _minimal_track( primaryArtists=[ {"artistName": "Moist", "artistType": "performer"}, {"artistName": "Lisa Pedersen", "artistType": "featuring"}, {"artistName": "David Elfström Lilja", "artistType": "producer"}, {"artistName": "Komatrohn", "artistType": "remixer"}, ] ) result = format_product.process_product(_minimal_product(tracks=[track])) by_type = result["tracks"][0]["artists_by_type"] assert by_type["primary_artist"] == ["Moist"] assert "performer" not in by_type assert by_type["featuring"] == ["Lisa Pedersen"] assert by_type["producer"] == ["David Elfström Lilja"] assert by_type["remixer"] == ["Komatrohn"] def test_artists_by_type_empty_when_no_primary_artists() -> None: """artists_by_type is empty dict when primaryArtists is empty.""" result = format_product.process_product(_minimal_product(tracks=[_minimal_track()])) assert result["tracks"][0]["artists_by_type"] == {} def test_primary_artists_with_missing_name_are_skipped() -> None: """Artists with a null or empty name are excluded from artists_by_type.""" track = _minimal_track( primaryArtists=[ {"artistName": None, "artistType": "performer"}, {"artistName": "", "artistType": "featuring"}, {"artistName": "Moist", "artistType": "performer"}, ] ) result = format_product.process_product(_minimal_product(tracks=[track])) by_type = result["tracks"][0]["artists_by_type"] assert by_type == {"primary_artist": ["Moist"]} # --- has_lyrics --- def test_has_lyrics_false_for_empty_string() -> None: """Empty string lyrics → has_lyrics is False.""" raw = _minimal_product(tracks=[_minimal_track(lyrics="")]) assert format_product.process_product(raw)["tracks"][0]["has_lyrics"] is False def test_has_lyrics_false_for_null() -> None: """Null lyrics → has_lyrics is False.""" raw = _minimal_product(tracks=[_minimal_track(lyrics=None)]) assert format_product.process_product(raw)["tracks"][0]["has_lyrics"] is False def test_has_lyrics_false_for_none_string() -> None: """String 'None' lyrics → has_lyrics is False.""" raw = _minimal_product(tracks=[_minimal_track(lyrics="None")]) assert format_product.process_product(raw)["tracks"][0]["has_lyrics"] is False def test_has_lyrics_true_when_present() -> None: """Non-empty lyrics string → has_lyrics is True.""" raw = _minimal_product(tracks=[_minimal_track(lyrics="La la la")]) assert format_product.process_product(raw)["tracks"][0]["has_lyrics"] is True # --- Writers --- def test_writer_fields_normalized() -> None: """trackWriterName/trackWriterType are normalized to name/type.""" track = _minimal_track( writers=[{"trackWriterName": "Midge Ure", "trackWriterType": "writer"}] ) result = format_product.process_product(_minimal_product(tracks=[track])) writer = result["tracks"][0]["writers"][0] assert writer["name"] == "Midge Ure" assert writer["type"] == "writer" assert "track_writer_name" not in writer # --- Performers --- def test_performer_output_has_name_and_role_only() -> None: """Performer output contains only name and role; roleId and type stripped.""" track = _minimal_track( performers=[ { "name": "Lisa Pedersen", "roleId": 89, "role": "Vocals - Lead Vocals", "type": "primary", } ] ) result = format_product.process_product(_minimal_product(tracks=[track])) performer = result["tracks"][0]["performers"][0] assert performer == {"name": "Lisa Pedersen", "role": "Vocals - Lead Vocals"}