"""Tests for TrackParticpantHandlers.""" from mock import Mock, patch import pytest from switchboard_consumer.constants.exceptions import ( ParticipantHandlerError) from switchboard_consumer.constants.track_participant_roles import ( CLASSICAL_TRACK_ARTIST_CONTRIBUTOR_ROLE_MAPPING, CLASSICAL_TRACK_ARTIST_ROLE_MAPPING, TRACK_ARTIST_CONTRIBUTOR_ROLE_MAPPING, TRACK_ARTIST_ROLE_MAPPING ) from switchboard_consumer.formatters.artist \ import format_get_artist_id from switchboard_consumer.logic.participant.track_participant_handler \ import TrackParticipantHandler @patch('switchboard_consumer.utils.message.datetime') @patch('switchboard_consumer.utils.message.uuid.uuid4') @patch.object(TrackParticipantHandler, '_get_artist') @patch.object(TrackParticipantHandler, '_find_artists', return_value=[]) def test_process_track_participants( mock_find_artists, mock_get_artist, mock_uuid, mock_datetime, switchboard_track_item_with_contributor_and_artist, mock_logger, orchard_client, create_product_message, sony_product ): """Test processing track participants.""" uuid_value = '123456' mock_uuid.return_value = uuid_value datetime_value = '2019' mock_datetime.now.return_value = Mock(isoformat=lambda: datetime_value) mock_logger = Mock() track = switchboard_track_item_with_contributor_and_artist['track'] vendor_id = '1234' create_artist_results = [{ 'artistId': '123', 'artistName': track['displayArtists'][0]['participant']['name'], 'artistType': 'artist', 'vendorId': vendor_id }, { 'artistId': '124', 'artistName': track['contributors'][0]['participant']['name'], 'artistType': 'artist', 'vendorId': vendor_id }, { 'artistId': '125', 'artistName': track['contributors'][1]['participant']['name'], 'artistType': 'artist', 'vendorId': vendor_id }, ] expected_artist_mapping = [ track['displayArtists'][0]['participant']['ids'][0], { 'localId': 'AIID:123', 'system': 'ORCHARD' } ] expected_writer_mapping = [ track['contributors'][0]['participant']['ids'][0], { 'localId': 'AIID:124', 'system': 'ORCHARD' } ] expected_formatted_artist = { 'artistInfoId': int(create_artist_results[0]['artistId']), 'artistName': track['displayArtists'][0]['participant']['name'], 'artistType': 'performer' } expected_formatted_writer = { 'artistInfoId': int(create_artist_results[1]['artistId']), 'artistName': track['contributors'][0]['participant']['name'], 'artistType': 'writer' } orchard_client.create_artist = Mock(side_effect=create_artist_results) track_participant_handler = TrackParticipantHandler(sony_product, mock_logger, orchard_client, create_product_message, '1234', None) # Setup a wrap track_participant_handler._create_artist = \ Mock(wraps=track_participant_handler._create_artist) (processing_results, artists, writers) = \ track_participant_handler.process(track) # We have no existing mapping so get artist should not be called mock_get_artist.assert_not_called() track_participant_handler._create_artist.assert_called() assert len(processing_results) == 2 assert len(artists) == 1 assert len(writers) == 1 assert processing_results[0].get('ids') == expected_artist_mapping assert artists[0] == expected_formatted_artist assert processing_results[1].get('ids') == expected_writer_mapping assert writers[0] == expected_formatted_writer assert track_participant_handler.track_artist_role_mapping \ == TRACK_ARTIST_ROLE_MAPPING assert track_participant_handler.track_artist_contributor_role_mapping \ == TRACK_ARTIST_CONTRIBUTOR_ROLE_MAPPING @patch('switchboard_consumer.utils.message.datetime') @patch('switchboard_consumer.utils.message.uuid.uuid4') @patch.object(TrackParticipantHandler, '_get_artist') @patch.object(TrackParticipantHandler, '_find_artists', return_value=[]) def test_process_track_participants_compound( mock_find_artists, mock_get_artist, mock_uuid, mock_datetime, switchboard_track_item_with_compounds, mock_logger, orchard_client, create_product_message, sony_product ): """Test processing track participants with compound artist.""" uuid_value = '123456' mock_uuid.return_value = uuid_value datetime_value = '2019' mock_datetime.now.return_value = Mock(isoformat=lambda: datetime_value) mock_logger = Mock() track = switchboard_track_item_with_compounds['track'] vendor_id = '1234' create_artist_results = [ { 'artistId': '123', 'artistName': track ['displayArtists'][0]['participant']['members'] [0]['participant']['name'], 'artistType': 'artist', 'vendorId': vendor_id }, { 'artistId': '124', 'artistName': track ['displayArtists'][0]['participant']['members'] [1]['participant']['name'], 'artistType': 'artist', 'vendorId': vendor_id } ] expected_artist_1_mapping = [ track['displayArtists'][0]['participant']['members'][0] ['participant']['ids'][0], { 'localId': 'AIID:123', 'system': 'ORCHARD' } ] expected_artist_2_mapping = [ track['displayArtists'][0]['participant']['members'][1] ['participant']['ids'][0], { 'localId': 'AIID:124', 'system': 'ORCHARD' } ] expected_formatted_artist_1 = { 'artistInfoId': int(create_artist_results[0]['artistId']), 'artistName': create_artist_results[0]['artistName'], 'artistType': 'performer' } expected_formatted_artist_2 = { 'artistInfoId': int(create_artist_results[1]['artistId']), 'artistName': create_artist_results[1]['artistName'], 'artistType': 'featuring' } orchard_client.create_artist = Mock(side_effect=create_artist_results) track_participant_handler = TrackParticipantHandler(sony_product, mock_logger, orchard_client, create_product_message, '1234', None) # Setup a wrap track_participant_handler._create_artist = \ Mock(wraps=track_participant_handler._create_artist) (processing_results, artists, writers) = track_participant_handler.process(track) # We have no existing mapping so get artist should not be called mock_get_artist.assert_not_called() track_participant_handler._create_artist.assert_called() assert len(processing_results) == 2 assert len(artists) == 2 assert len(writers) == 0 assert processing_results[0].get('ids') == expected_artist_1_mapping assert artists[0] == expected_formatted_artist_1 assert processing_results[1].get('ids') == expected_artist_2_mapping assert artists[1] == expected_formatted_artist_2 @patch('switchboard_consumer.utils.message.datetime') @patch('switchboard_consumer.utils.message.uuid.uuid4') @patch.object(TrackParticipantHandler, '_get_artist') def test_process_track_participants_compound_and_mapping( mock_get_artist, mock_uuid, mock_datetime, switchboard_track_item_with_compounds, mock_logger, orchard_client, create_product_message, sony_product ): """Test processing track participants on compound artists with mapping.""" uuid_value = '123456' mock_uuid.return_value = uuid_value datetime_value = '2019' mock_datetime.now.return_value = Mock(isoformat=lambda: datetime_value) mock_logger = Mock() track = switchboard_track_item_with_compounds['track'] vendor_id = '1234' mock_get_artist.return_value = { 'vendorId': vendor_id } # Add some orchard mappings (track['displayArtists'][0]['participant']['members'][0] ['participant']['ids'].append( {'localId': 'AIID:123', 'system': 'ORCHARD'})) (track['displayArtists'][0]['participant']['members'][1] ['participant']['ids'].append( {'localId': 'AIID:124', 'system': 'ORCHARD'})) expected_formatted_artist_1 = { 'artistInfoId': format_get_artist_id( (track['displayArtists'][0]['participant'] ['members'][0] ['participant']['ids'][1]['localId'])), 'artistName': (track['displayArtists'][0]['participant'] ['members'][0] ['participant']['name']), 'artistType': 'performer' } expected_formatted_artist_2 = { 'artistInfoId': format_get_artist_id( (track['displayArtists'][0]['participant'] ['members'][1] ['participant']['ids'][1]['localId'] )), 'artistName': (track['displayArtists'][0]['participant'] ['members'][1] ['participant']['name']), 'artistType': 'featuring' } track_participant_handler = TrackParticipantHandler(sony_product, mock_logger, orchard_client, create_product_message, '1234', None) # Setup a wrap track_participant_handler._create_artist = Mock( wraps=track_participant_handler._create_artist) (processing_results, artists, writers) = track_participant_handler.process(track) mock_get_artist.assert_called() track_participant_handler._create_artist.assert_not_called() assert len(processing_results) == 0 assert len(artists) == 2 assert len(writers) == 0 assert artists[0] == expected_formatted_artist_1 assert artists[1] == expected_formatted_artist_2 @patch('switchboard_consumer.utils.message.datetime') @patch('switchboard_consumer.utils.message.uuid.uuid4') @patch.object(TrackParticipantHandler, '_get_artist') def test_process_track_participants_with_no_valid_display_artists( mock_get_artist, mock_uuid, mock_datetime, switchboard_track_item_with_invalid_display_artist, mock_logger, orchard_client, create_product_message, sony_product ): """Test processing track participants.""" uuid_value = '123456' mock_uuid.return_value = uuid_value datetime_value = '2019' mock_datetime.now.return_value = Mock(isoformat=lambda: datetime_value) mock_logger = Mock() track = switchboard_track_item_with_invalid_display_artist['track'] vendor_id = '1234' track_participant_handler = TrackParticipantHandler(sony_product, mock_logger, orchard_client, create_product_message, vendor_id, None) expected_error = ('Could not map any displayArtists to ' 'Orchard track_artists for track ISRC: USSM11307807') with pytest.raises(ParticipantHandlerError) as exception: (processing_results, artists, writers) = \ track_participant_handler.process(track) assert str(exception.value) == expected_error @patch('switchboard_consumer.utils.message.datetime') @patch('switchboard_consumer.utils.message.uuid.uuid4') @patch.object(TrackParticipantHandler, '_get_artist') def test_process_track_participants_with_no_valid_display_artists_members( mock_get_artist, mock_uuid, mock_datetime, switchboard_track_item_with_invalid_display_artist, mock_logger, orchard_client, create_product_message, sony_product ): """Test processing track participants.""" uuid_value = '123456' mock_uuid.return_value = uuid_value datetime_value = '2019' mock_datetime.now.return_value = Mock(isoformat=lambda: datetime_value) mock_logger = Mock() track = switchboard_track_item_with_invalid_display_artist['track'] vendor_id = '1234' track_participant_handler = TrackParticipantHandler(sony_product, mock_logger, orchard_client, create_product_message, vendor_id, None) expected_error = ('Could not map any displayArtists to ' 'Orchard track_artists for track ISRC: USSM11307807') with pytest.raises(ParticipantHandlerError) as exception: (processing_results, artists, writers) = \ track_participant_handler.process(track) assert str(exception.value) == expected_error @patch('switchboard_consumer.utils.message.datetime') @patch('switchboard_consumer.utils.message.uuid.uuid4') @patch.object(TrackParticipantHandler, '_get_artist') def test_classical_mapping_used_when_product_is_classical( mock_get_artist, mock_uuid, mock_datetime, mock_logger, orchard_client, create_product_message, sony_product ): """Test if role mappings are set to their classical version.""" uuid_value = '123456' mock_uuid.return_value = uuid_value datetime_value = '2019' mock_datetime.now.return_value = Mock(isoformat=lambda: datetime_value) mock_logger = Mock() # Make this sony_product map to the Classical Orchard genre sony_product['genres'] = [ { 'system': 'SONY', 'genreId': 496, 'subGenres': [] }, { 'system': 'ORCHARD', 'genreId': 12, 'subGenres': [] } ] vendor_id = '1234' track_participant_handler = TrackParticipantHandler(sony_product, mock_logger, orchard_client, create_product_message, vendor_id, None) assert track_participant_handler.is_classical assert track_participant_handler.track_artist_role_mapping \ == CLASSICAL_TRACK_ARTIST_ROLE_MAPPING assert track_participant_handler.track_artist_contributor_role_mapping \ == CLASSICAL_TRACK_ARTIST_CONTRIBUTOR_ROLE_MAPPING