"""Tests for physical product logic.""" from unittest.mock import MagicMock from oto import response from ows_product_physical.constant import error from ows_product_physical.constant import validation as validation_constants from ows_product_physical.logic import ownership from ows_product_physical.logic import product_physical from ows_product_physical.logic import product_physical_tracks from ows_product_physical.models import track as track_model def test_update_tracks_success( monkeypatch, valid_get_header, valid_put_product_tracks_data): """Test update tracks success.""" mock_product = { 'product_id': 42, 'upc': 555566667777} monkeypatch.setattr( product_physical, 'fetch_by_id', value=MagicMock( return_value=response.Response(message=mock_product))) monkeypatch.setattr( track_model, 'process_tracks', value=MagicMock( return_value=response.Response(status=201))) monkeypatch.setattr( track_model, 'get_tracks', value=MagicMock( return_value=response.Response())) monkeypatch.setattr( ownership, 'check_track_ownership', value=MagicMock( return_value=response.Response(status=200))) account_type = valid_get_header['Grass-Account-Type'] account_id = valid_get_header['Grass-Account-Id'] result = product_physical_tracks.update_tracks( 42, valid_put_product_tracks_data.get('items'), account_type, account_id) assert result.status == 201 assert product_physical.fetch_by_id.called assert track_model.process_tracks.called assert track_model.process_tracks.call_args[0][0] == 42 assert track_model.process_tracks.call_args[0][1] == 555566667777 def test_update_tracks_validation_success( monkeypatch, valid_get_header, valid_put_product_tracks_data): """Test that valid ADD/EDIT/DELETE validations allow update_tracks().""" mock_product = { 'product_id': 42, 'upc': 555566667777} monkeypatch.setattr( product_physical, 'fetch_by_id', value=MagicMock( return_value=response.Response(message=mock_product))) monkeypatch.setattr( track_model, 'process_tracks', value=MagicMock( return_value=response.Response(status=201))) monkeypatch.setattr( track_model, 'get_tracks', value=MagicMock( return_value=response.Response(status=200))) monkeypatch.setattr( ownership, 'check_track_ownership', value=MagicMock( return_value=response.Response(status=200))) account_type = valid_get_header['Grass-Account-Type'] account_id = valid_get_header['Grass-Account-Id'] mutated_tracks = valid_put_product_tracks_data.get('items') # update state for track 2 mutated_tracks[1]['track_id'] = 5555 # delete state for track 3 mutated_tracks[2] = { 'is_deleted': 'Y', 'track_id': 5556} result = product_physical_tracks.update_tracks( 42, mutated_tracks, account_type, account_id) assert result.status == 201 assert product_physical.fetch_by_id.called assert track_model.process_tracks.called assert track_model.process_tracks.call_args[0][0] == 42 assert track_model.process_tracks.call_args[0][1] == 555566667777 def test_update_tracks_fetch_product_by_id_fail(monkeypatch, valid_get_header): """Test update tracks fail when product fetch fails.""" monkeypatch.setattr( product_physical, 'fetch_by_id', value=MagicMock( return_value=response.create_error_response( code=400, message='whatever'))) monkeypatch.setattr( track_model, 'process_tracks', value=MagicMock( return_value=response.Response())) account_type = valid_get_header['Grass-Account-Type'] account_id = valid_get_header['Grass-Account-Id'] result = product_physical_tracks.update_tracks( 1234, 'whatever', account_type, account_id) assert result.status == 400 assert product_physical.fetch_by_id.called assert not track_model.process_tracks.called def test_update_tracks_validation_errors_mirror_track_list( monkeypatch, db_fixture, valid_get_header, valid_put_product_tracks_data): """Test update tracks fail when product fetch fails.""" mock_product = { 'product_id': 42, 'upc': 555566667777} monkeypatch.setattr( product_physical, 'fetch_by_id', value=MagicMock( return_value=response.Response(message=mock_product))) account_type = valid_get_header['Grass-Account-Type'] account_id = valid_get_header['Grass-Account-Id'] mutated_tracks = valid_put_product_tracks_data.get('items') mutated_tracks[0].pop('track_name') result = product_physical_tracks.update_tracks( 42, mutated_tracks, account_type, account_id) assert result.status == 400 assert result.errors.get('code') == error.VALIDATION_ERROR assert len( result.errors.get( 'message').get('tracks')) == len(mutated_tracks) def test_update_tracks_validation_errors_at_same_index( monkeypatch, db_fixture, valid_get_header, valid_put_product_tracks_data): """The tracks with errors should be in same location as request payload.""" mock_product = { 'product_id': 42, 'upc': 555566667777} monkeypatch.setattr( product_physical, 'fetch_by_id', value=MagicMock( return_value=response.Response(message=mock_product))) monkeypatch.setattr( track_model, 'get_tracks', value=MagicMock( return_value=response.Response())) monkeypatch.setattr( ownership, 'check_track_ownership', value=MagicMock( return_value=response.Response(status=200))) account_type = valid_get_header['Grass-Account-Type'] account_id = valid_get_header['Grass-Account-Id'] mutated_tracks = valid_put_product_tracks_data.get('items') mutated_tracks[0].pop('track_name') mutated_tracks[3].pop('performer') mutated_tracks[5]['is_deleted'] = 'Y' mutated_tracks[5]['track_id'] = 12345 result = product_physical_tracks.update_tracks( 42, mutated_tracks, account_type, account_id) track_errors = result.errors.get('message').get('tracks') assert result.status == 400 assert result.errors.get('code') == error.VALIDATION_ERROR assert track_errors[0] assert track_errors[0]['track_name'] assert track_errors[1] is None assert track_errors[2] is None assert track_errors[3] assert track_errors[3]['performer'] assert track_errors[4] is None assert track_errors[5]['additionalProperties'] def test_update_tracks_validation_errors_contains_both_indexes( monkeypatch, db_fixture, valid_get_header, valid_put_product_tracks_data): """Test that both global and tracks indexes exist on validation error.""" mock_product = { 'product_id': 42, 'upc': 555566667777} monkeypatch.setattr( product_physical, 'fetch_by_id', value=MagicMock( return_value=response.Response(message=mock_product))) account_type = valid_get_header['Grass-Account-Type'] account_id = valid_get_header['Grass-Account-Id'] mutated_tracks = valid_put_product_tracks_data.get('items') mutated_tracks[0].pop('track_name') result = product_physical_tracks.update_tracks( 42, mutated_tracks, account_type, account_id) assert 'global' in result.errors.get('message') assert 'tracks' in result.errors.get('message') assert 'track_name' in result.errors.get( 'message').get('tracks')[0] def test_update_tracks_db_state_error_contains_both_indexes( monkeypatch, db_fixture, valid_get_header, valid_put_product_tracks_data): """Test that both global and tracks indexes exist on db state error.""" mock_product = { 'product_id': 42, 'upc': 555566667777} monkeypatch.setattr( product_physical, 'fetch_by_id', value=MagicMock( return_value=response.Response(message=mock_product))) account_type = valid_get_header['Grass-Account-Type'] account_id = valid_get_header['Grass-Account-Id'] mutated_tracks = valid_put_product_tracks_data.get('items') mutated_tracks[5]['isrc'] = mutated_tracks[0]['isrc'] result = product_physical_tracks.update_tracks( 42, mutated_tracks, account_type, account_id) assert 'tracks' in result.errors.get('message') assert 'global' in result.errors.get('message') assert result.errors.get( 'message').get('global') == validation_constants.ISRC_UNIQUE_MSG