"""Tests for put publishing obligation logic.""" from oto import response import pytest from ows_product_physical.constant import error from ows_product_physical.constant import field from ows_product_physical.logic import product_physical_tracks from ows_product_physical.models import ows_contracts, ows_royalties from ows_product_physical.models import ows_product from ows_product_physical.models import track as track_model def test_composition_obligation_with_publishers_is_valid_for_mech_admin(): """Verify answer is valid when 3rd party and has publishers.""" data = { field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'Y', field.PUBLISHER_NAMES: ['Pub 1'] } is_valid = product_physical_tracks._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=True) assert is_valid, ( 'When us_publishing_obligations is composition and ' 'has third-party publishers') @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_composition_obligation_non_third_party_is_valid(vendor_is_mech_admin): """Verify answer is valid when not 3rd party.""" data = { field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'N' } is_valid = product_physical_tracks._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert is_valid, ( 'When us_publishing_obligations is composition and ' "third-party publishers is 'N'") @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_composition_obligation_non_third_party_with_publsihers_is_valid( vendor_is_mech_admin): """Verify answer is valid when not 3rd party and has publishers.""" data = { field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'N', field.PUBLISHER_NAMES: ['Pub 1'] } is_valid = product_physical_tracks._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert is_valid, ( 'When us_publishing_obligations is composition and ' "third-party publishers is 'N' and publishers is specified") def test_composition_with_publishers_is_required_when_mech_admin(): """Verify publishers must be specified when 3rd party is 'Y'.""" data = { field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'Y' } is_valid = product_physical_tracks._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=True) assert not is_valid, ( 'When us_publishing_obligations is composition, ' 'has third-party publishers, and vendor is mech admin - ' 'the publisher_names field must be filled in') def test_composition_third_party_cannot_be_yes_when_not_mech_admin(): """Verify third party cannot be set to 'Y' when vendor not mech admin.""" data = { field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'Y' } is_valid = product_physical_tracks._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=False) assert not is_valid, ( 'When us_publishing_obligations is composition,' ' a vendor without mech admin access cannot answer ' 'yes to third party publishers question') @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_non_third_party_obligations_are_valid(vendor_is_mech_admin): """Verify non third-party obligation answer are valid by itself.""" for obligation_answer in field.NO_3RD_PARTY_ENUM: data = {field.US_PUBLISHING_OBLIGATION: obligation_answer} is_valid = ( product_physical_tracks._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin)) assert is_valid, ( 'When us_publishing_obligation is not set to ' 'composition and no other fields are filled in') @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_null_obligation_when_answers_are_valid(vendor_is_mech_admin): """Verify publishing obligation answer doesn't have to be filled in.""" for third_party_publisher in (None, 'N'): data = { field.US_PUBLISHING_OBLIGATION: None, field.THIRD_PARTY_PUBLISHER: third_party_publisher, field.PUBLISHER_NAMES: ['Some publisher'] } is_valid = ( product_physical_tracks._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin)) assert is_valid, 'When us_publishing_obligation is set to None' @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_null_obligation_when_answers_are_not_valid(vendor_is_mech_admin): """Verify publishing obligation answer can't have certain answers.""" data = { field.US_PUBLISHING_OBLIGATION: None, field.THIRD_PARTY_PUBLISHER: 'Y' } is_valid = product_physical_tracks._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert not is_valid, ( 'When us_publishing_obligation is set to None and ' "third-party publishers is set to 'Y'") @pytest.mark.parametrize('vendor_is_mech_admin', [True, False]) def test_answer_is_not_blank(vendor_is_mech_admin): """Verify blank answer for publishing obligation is invalid.""" data = {field.US_PUBLISHING_OBLIGATION: ''} is_valid = product_physical_tracks._is_valid_publishing_obligation_answers( data, vendor_is_mech_admin=vendor_is_mech_admin) assert not is_valid, 'Publishing obligation must be provided' def test__validate_track_publishing_obligations_data_valid(): """Test validation if update publishing obligations data is valid.""" valid_data = [ { 'publisher_names': ['Billy Bob', 'Sweet Candy'], 'track_id': 1, 'us_publishing_obligation': 'Composition', 'third_party_publisher': 'Y' }] result = product_physical_tracks._validate_track_publishing_obligations( valid_data, True) assert result def test__validate_track_publishing_obligations_data_invalid(): """Test validation if update publishing obligations data is invalid.""" invalid_data = [ { 'publisher_names': ['Billy Bob', 'Sweet Candy'], 'track_id': 1, 'us_publishing_obligation': 'PublicDomain', 'third_party_publisher': 'Y' }] result = product_physical_tracks._validate_track_publishing_obligations( invalid_data, True) assert not result assert result.errors['message'] == 'Invalid response for track_id 1' def test_update_publishing_obligations_success(mocker): """Test update_publishing_obligations success.""" product_id = 1 data = [{ 'track_id': 12345, field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'N' }] account_type = 'vendor' account_id = 'alw:23456' mocker.patch.object( ows_product, 'get_product', return_value=response.Response( {'upc': 12345}), autospec=True) mocker.patch.object( product_physical_tracks, '_is_mech_admin', return_value=response.Response( message={'mechadmin_digital': False, 'mechadmin_physical': True}), autospec=True) mocker.patch.object( track_model, 'get_tracks', return_value=response.Response(message={'items': ['Test Track']})) mocker.patch.object( product_physical_tracks, '_validate_track_publishing_obligations', return_value=response.Response(), autospec=True) mocker.patch.object( track_model, 'bulk_update_publishing_obligations', return_value=response.Response(), autospec=True) mocker.patch.object( track_model, 'get_publishing_obligations', return_value=response.Response(), autospec=True) result = product_physical_tracks.update_publishing_obligations( product_id, data, account_type, account_id) assert ows_product.get_product.called assert product_physical_tracks._is_mech_admin.called assert ( product_physical_tracks._validate_track_publishing_obligations.called) assert track_model.bulk_update_publishing_obligations.called assert track_model.get_publishing_obligations.called assert result def test_update_publishing_obligations_get_product_failure(mocker): """Test update_publishing_obligations if get_product fails.""" product_id = 1 error_message = 'error fetching product' data = [{ 'track_id': 12345, field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'N' }] account_type = 'vendor' account_id = 'alw:23456' mocker.patch.object( ows_product, 'get_product', return_value=response.create_error_response( code=error.INTERNAL_ERROR, message=error_message, status=500), autospec=True) mocker.patch.object(product_physical_tracks, '_is_mech_admin') result = product_physical_tracks.update_publishing_obligations( product_id, data, account_type, account_id) assert result.status == 500 assert result.errors['message'] == error_message assert not product_physical_tracks._is_mech_admin.called def test_update_publishing_obligations_is_mech_admin_fails(mocker): """Test update_publishing_obligations is mech admin failure.""" product_id = 1 data = [{ 'track_id': 12345, field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'N' }] account_type = 'vendor' account_id = 'alw:23456' mocker.patch.object( ows_product, 'get_product', return_value=response.Response( {'upc': 12345}), autospec=True) mocker.patch.object( track_model, 'get_tracks', return_value=response.Response(message={'items': ['Test Track']})) mocker.patch.object( product_physical_tracks, '_is_mech_admin', return_value=response.create_error_response( code=error.OWS_CONTRACTS_ERROR_CODE, message='ows contracts test error message'), autospec=True) mocker.patch.object( product_physical_tracks, '_validate_track_publishing_obligations') result = product_physical_tracks.update_publishing_obligations( product_id, data, account_type, account_id) assert ows_product.get_product.called assert product_physical_tracks._is_mech_admin.called assert not ( product_physical_tracks._validate_track_publishing_obligations.called) assert not result assert result.errors['message'] == 'ows contracts test error message' def test_update_publishing_obligations_validation_fails(mocker): """Test update_publishing_obligations is valid answers returns False.""" product_id = 1 data = [{ 'track_id': 12345, field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'N' }] account_type = 'vendor' account_id = 'alw:23456' mocker.patch.object( ows_product, 'get_product', return_value=response.Response( {'upc': 12345}), autospec=True) mocker.patch.object( track_model, 'get_tracks', return_value=response.Response(message={'items': ['Test Track']})) mocker.patch.object( product_physical_tracks, '_is_mech_admin', return_value=response.Response( message={'mechadmin_digital': False, 'mechadmin_physical': True}), autospec=True) mocker.patch.object( product_physical_tracks, '_validate_track_publishing_obligations', return_value=response.create_error_response( message='Invalid response for track_id 12345', code=error.VALIDATION_ERROR), autospec=True) mocker.patch.object( track_model, 'bulk_update_publishing_obligations') result = product_physical_tracks.update_publishing_obligations( product_id, data, account_type, account_id) assert ows_product.get_product.called assert product_physical_tracks._is_mech_admin.called assert ( product_physical_tracks._validate_track_publishing_obligations.called) assert not track_model.bulk_update_publishing_obligations.called assert not result assert result.errors['message'] == 'Invalid response for track_id 12345' def test_update_publishing_obligations_failure(mocker): """Test update_publishing_obligations success.""" product_id = 1 data = [{ 'track_id': 12345, field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'N' }] account_type = 'vendor' account_id = 'alw:23456' mocker.patch.object( ows_product, 'get_product', return_value=response.Response( {'upc': 12345}), autospec=True) mocker.patch.object( track_model, 'get_tracks', return_value=response.Response(message={'items': ['Test Track']})) mocker.patch.object( product_physical_tracks, '_is_mech_admin', return_value=response.Response( message={'mechadmin_digital': False, 'mechadmin_physical': True}), autospec=True) mocker.patch.object( product_physical_tracks, '_validate_track_publishing_obligations', return_value=response.Response(), autospec=True) mocker.patch.object( track_model, 'bulk_update_publishing_obligations', return_value=response.create_fatal_response(), autospec=True) mocker.patch.object(track_model, 'get_publishing_obligations') result = product_physical_tracks.update_publishing_obligations( product_id, data, account_type, account_id) assert ows_product.get_product.called assert product_physical_tracks._is_mech_admin.called assert ( product_physical_tracks._validate_track_publishing_obligations.called) assert track_model.bulk_update_publishing_obligations.called assert not track_model.get_publishing_obligations.called assert not result def test_update_publishing_obligations_tracks_are_not_found(mocker): """Test update_publishing_obligations success.""" product_id = 1 data = [{ 'track_id': 12345, field.US_PUBLISHING_OBLIGATION: field.COMPOSITION, field.THIRD_PARTY_PUBLISHER: 'N' }] account_type = 'vendor' account_id = 'alw:23456' mocker.patch.object( ows_product, 'get_product', return_value=response.Response( {'upc': 12345}), autospec=True) mocker.patch.object( track_model, 'get_tracks', return_value=response.Response(message={'items': []})) mocker.patch.object( product_physical_tracks, '_is_mech_admin', return_value=response.Response( message={'is_mech_admin': True}), autospec=True) mocker.patch.object(track_model, 'get_publishing_obligations') result = product_physical_tracks.update_publishing_obligations( product_id, data, account_type, account_id) assert ows_product.get_product.called assert not product_physical_tracks._is_mech_admin.called assert result.status == 404 assert result.errors['code'] == ( error.PUBLISHING_OBLIGATION_NOT_FOUND_NO_TRACK_CODE) def test__is_mech_admin(mocker): """Test checking if the account is mech admin.""" account_type = 'vendor' account_id = '123' mock_mechadmin = {'mechadmin_physical': True, 'mechadmin_digital': False} mock_vendor_not_migrated = {'vendor_id': '123', 'migrated_to_abacus': False} mock_vendor_migrated = {'vendor_id': '123', 'migrated_to_abacus': True} # Test for an account not migrated to Abacus mocker.patch.object( product_physical_tracks, 'get_vendor', return_value=response.Response(message=mock_vendor_not_migrated)) mocker.patch.object( ows_contracts, 'is_mech_admin', return_value=response.Response(message=mock_mechadmin)) res = product_physical_tracks._is_mech_admin(account_type, account_id) product_physical_tracks.get_vendor.assert_called_once_with( account_type, account_id) ows_contracts.is_mech_admin.assert_called_once_with(account_type, account_id) assert res.status == 200 assert res.message.get('mechadmin_physical') is True # Test for an account migrated to Abacus mocker.patch.object( product_physical_tracks, 'get_vendor', return_value=response.Response(message=mock_vendor_migrated)) mocker.patch.object( ows_royalties, 'is_abacus_account_mech_admin', return_value=response.Response(message=mock_mechadmin)) res = product_physical_tracks._is_mech_admin(account_type, account_id) product_physical_tracks.get_vendor.assert_called_once_with( account_type, account_id) ows_royalties.is_abacus_account_mech_admin.assert_called_once_with( account_id) assert res.status == 200 assert res.message.get('mechadmin_physical') is True # Test when failing to fetch the vendor details mocker.patch.object( product_physical_tracks, 'get_vendor', return_value=response.Response(status=500)) res = product_physical_tracks._is_mech_admin(account_type, account_id) product_physical_tracks.get_vendor.assert_called_once_with( account_type, account_id) assert res.status == 500