"""Unit tests for create_tracks lambda.""" from unittest.mock import patch from common.schemas.state_machine_schema import StateMachineSchema from src.constants.queries import GET_TRACKS_BY_UPC, SAVE_TRACKS import src.index as index @patch('src.index.get_art_relations_tracks') @patch('src.index.create_tracks') @patch('src.index.enrich_track_tuids') @patch('src.index.update_track_sequence_numbers') def test_handler( mock_update_track_sequence_numbers, mock_enrich_track_tuids, mock_create_tracks, mock_get_art_relations_tracks, context_event): """Test the main handler creates tracks when no existing tracks found.""" mock_get_art_relations_tracks.return_value = [] created_tracks = [{'isrc': 'QZCDB2000003', 'tuid': '45679'}] mock_create_tracks.return_value = created_tracks index.handler(context_event, None) mock_get_art_relations_tracks.assert_called_once_with('231232563123') mock_create_tracks.assert_called_once() args, _ = mock_create_tracks.call_args assert args[0] == 234324 assert len(args[1]) == 1 assert args[1][0].isrc == 'QZCDB2000003' mock_enrich_track_tuids.assert_called_once() mock_update_track_sequence_numbers.assert_called_once() @patch('src.index.get_art_relations_tracks') @patch('src.index.create_tracks') @patch('src.index.delete_tracks') @patch('src.index.enrich_track_tuids') @patch('src.index.update_track_sequence_numbers') def test_handler_delete_track( mock_update_track_sequence_numbers, mock_enrich_track_tuids, mock_delete_tracks, mock_create_tracks, mock_get_art_relations_tracks, context_event): """Test the main handler creates tracks when no existing tracks found.""" mock_get_art_relations_tracks.return_value = [ {'isrc': 'isrc1', 'tuid': '1'}, {'isrc': 'isrc2', 'tuid': '2'}, {'isrc': 'isrc3', 'tuid': '3'}] context_tracks = [{'isrc': 'isrc1'}] context_event['tracks'] = context_tracks index.handler(context_event, None) args, _ = mock_delete_tracks.call_args assert args[1] == [2, 3] @patch('src.index.get_art_relations_tracks') @patch('src.index.create_tracks') @patch('src.index.delete_tracks') @patch('src.index.update_track_sequence_numbers') def test_handler_delete_and_create_track( mock_update_track_sequence_numbers, mock_delete_tracks, mock_create_tracks, mock_get_art_relations_tracks, context_event): """Test the main handler creates tracks when no existing tracks found.""" mock_get_art_relations_tracks.return_value = [ {'isrc': 'isrc2', 'tuid': '2'}, {'isrc': 'isrc3', 'tuid': '3'}, {'isrc': 'isrc6', 'tuid': '6'}, {'isrc': 'isrc1', 'tuid': '1'}, ] mock_create_tracks.return_value = [ {'isrc': 'isrc4', 'tuid': '4'}, {'isrc': 'isrc5', 'tuid': '5'}, ] context_tracks = [ {'isrc': 'isrc4'}, {'isrc': 'isrc5'}, {'isrc': 'isrc1'}, ] context_event['tracks'] = context_tracks result = index.handler(context_event, None) args, _ = mock_delete_tracks.call_args assert args[1] == [2, 3, 6] args, _ = mock_create_tracks.call_args assert args[0] == 234324 assert len(args[1]) == 2 assert args[1][0].isrc == 'isrc4' assert args[1][1].isrc == 'isrc5' assert result['deleted_tracks'] == [2, 3, 6] assert result['tracks'][0]['tuid'] == 4 assert result['tracks'][1]['tuid'] == 5 assert result['tracks'][2]['tuid'] == 1 @patch('src.index.graphql_gateway.execute') def test_get_art_relations_tracks(mock_execute, get_tracks_response): """Test get_art_relations_tracks returns tracks from product.""" mock_execute.return_value = get_tracks_response result = index.get_art_relations_tracks('231232563123') assert result == get_tracks_response['data']['productByUpc']['tracks'] mock_execute.assert_called_once_with( GET_TRACKS_BY_UPC, {'upc': '231232563123'} ) @patch('src.index.graphql_gateway.execute') def test_get_art_relations_tracks_no_product(mock_execute, get_tracks_empty_response): """Test get_art_relations_tracks returns empty list when no product.""" mock_execute.return_value = get_tracks_empty_response result = index.get_art_relations_tracks('000000000000') assert result == [] @patch('src.index.graphql_gateway.execute') def test_create_tracks(mock_execute, context_event, save_tracks_response): """Test create_tracks sends correct payload and returns result.""" mock_execute.return_value = save_tracks_response sm_context = StateMachineSchema().load(context_event) tracks_to_create = [ t for t in sm_context.tracks if not t.tuid ] product_id = 234324 expected_payload = { 'data': { 'create': { 'productId': product_id, 'tracks': [ { 'isrc': 'QZCDB2000003', 'trackName': 'Track Three', 'volumeNumber': 1, 'explicit': 'E' } ] } } } result = index.create_tracks(product_id, tracks_to_create) assert result == save_tracks_response['data']['saveTracks'] mock_execute.assert_called_once_with(SAVE_TRACKS, expected_payload) @patch('src.index.graphql_gateway.execute') def test_create_tracks_explicit_none_defaults_to_n( mock_execute, context_event, save_tracks_response): """Test create_tracks defaults explicit to 'N' when value is None.""" mock_execute.return_value = save_tracks_response sm_context = StateMachineSchema().load(context_event) tracks_to_create = [ t for t in sm_context.tracks if not t.tuid ] tracks_to_create[0].explicit = None product_id = 234324 index.create_tracks(product_id, tracks_to_create) args, _ = mock_execute.call_args sent_track = args[1]['data']['create']['tracks'][0] assert sent_track['explicit'] == 'N' def test_create_tracks_skipped_no_tracks(): """Test create_tracks is skipped when tracks list is empty.""" with patch('src.index.graphql_gateway.execute') as mock_execute: result = index.create_tracks(234324, []) mock_execute.assert_not_called() assert result is None def test_delete_tracks_skipped_no_tracks(): """Test delete_tracks is skipped when tracks list is empty.""" with patch('src.index.graphql_gateway.execute') as mock_execute: index.delete_tracks(234324, []) mock_execute.assert_not_called() def test_delete_tracks(): """Test delete_tracks delete all provided tracks.""" with patch('src.index.graphql_gateway.execute') as mock_execute: index.delete_tracks(234324, [77, 88, 99]) expected_payload = { 'data': {'delete': {'productId': 234324, 'tracks': [77, 88, 99]}}} args, _ = mock_execute.call_args assert args[1] == expected_payload def test_enrich_track_tuids(context_event): """Test enrich_track_tuids populates tuid on context tracks.""" sm_context = StateMachineSchema().load(context_event) for track in sm_context.tracks: track.tuid = None new_tracks = [ {'isrc': 'QZCDB2000001', 'tuid': '45677'}, {'isrc': 'QZCDB2000002', 'tuid': '45678'}, {'isrc': 'QZCDB2000003', 'tuid': '45679'}, ] index.enrich_track_tuids(sm_context, new_tracks) for track in sm_context.tracks: assert track.tuid is not None assert isinstance(track.tuid, int) def test_enrich_track_tuids_skipped_no_new_tracks(context_event): """Test enrich_track_tuids is skipped when new_tracks is falsy.""" sm_context = StateMachineSchema().load(context_event) original_tuids = [t.tuid for t in sm_context.tracks] index.enrich_track_tuids(sm_context, None) for i, track in enumerate(sm_context.tracks): assert track.tuid == original_tuids[i] @patch('src.index.graphql_gateway.execute') def test_update_track_sequence_numbers(mock_execute, context_event): """Test update_track_sequence_numbers sends correct payload.""" sm_context = StateMachineSchema().load(context_event) # set tuid on the track that was None sm_context.tracks[2].tuid = 45679 expected_payload = { 'data': { 'updatePosition': { 'productId': 234324, 'tracks': [ {'trackNumber': 1, 'volumeNumber': 1, 'tuid': 45677}, {'trackNumber': 2, 'volumeNumber': 1, 'tuid': 45678}, {'trackNumber': 3, 'volumeNumber': 1, 'tuid': 45679}, ] } } } index.update_track_sequence_numbers(sm_context) mock_execute.assert_called_once_with(SAVE_TRACKS, expected_payload)