"""Unit tests for the audio product model.""" import datetime from unittest.mock import MagicMock from oto import response import pytest from product_digital import features from product_digital.connectors import mysql from product_digital.models import audio_product from product_digital.models import mkt_priority from product_digital.models import ows_assets from product_digital.models import ows_product_review from product_digital.models import ows_product_workflow from product_digital.models import ows_timed_release from product_digital.models import ows_track from product_digital.models import release from product_digital.models import release_approval_queue from product_digital.models import release_artist from product_digital.models import release_grid from product_digital.models import release_logging from product_digital.models import release_manual_adjustment from product_digital.models import release_status from product_digital.models import release_subgenre from product_digital.models import release_subtitles from product_digital.models import track from tests.factories import catalog_transfer as catalog_transfer_factory from tests.testutils import db @pytest.fixture def product_id(): """Create a fake product id for testing.""" return 1234 @pytest.fixture def upc(): """Return a fake upc.""" return '123456789012' @pytest.fixture def preorder_date(): """Return a fake preorder date.""" return datetime.date(2016, 12, 12) @pytest.fixture def release_date(): """Return a fake release date.""" return datetime.date(2016, 12, 13) @pytest.fixture def sale_start_date(): """Return a fake sale start date.""" return datetime.date(2016, 12, 14) @pytest.fixture def subaccount_id(): """Return a fake subaccount id.""" return '999' @pytest.fixture def product_props(preorder_date, release_date, sale_start_date): """Return a base set of product properties.""" return { 'artist_id': 7923, 'description': 'New description here', 'delivered_version': 'Live at Wembley', 'format': 'Single', 'genre_id': 13, 'c_line': '2016 This is important info', 'imprint': 'A new and fantastic label', 'manufacturer_upc': '123456789012', 'meta_language': 'SUX', 'p_line': '2020 PLINE', 'preorder_date': preorder_date, 'previewable': 'yes', 'product_name': '36 Chambers: Enter The Digital Clan', 'product_code': 'DIGI4LYFE', 'release_date': release_date, 'sale_start_date': sale_start_date, 'special_instructions': 'New instructions', 'version': 'Extremely Explicit Version' } @pytest.fixture def subaccount_product_props(subaccount_id): """Return a base set of product properties.""" return { 'artist_id': 7923, 'format': 'Single', 'product_name': 'Two Originals of Jack Rose', 'product_code': 'TWOROSE', 'version': 'Extremely Explicit Version', 'subaccount_id': int(subaccount_id)} @pytest.fixture def release_payload(preorder_date, product_id, release_date, sale_start_date, upc): """Return a fake response payload from the release model.""" return { 'release_id': product_id, 'artist_id': 7923, 'c_line': '2016 This is important info', 'delivered_version': 'Live at Wembley', 'description': 'New description here', 'distribution_format_id': 1, 'format': 'Single', 'genre_id': 13, 'itunes_previewable': 'yes', 'label': 'A new and fantastic label', 'manufacturer_upc': '123456789012', 'meta_language': 'SUX', 'p_line': '2020 PLINE', 'preorder_date': preorder_date, 'product_code': 'DIGI4LYFE', 'product_type_id': 1, 'project_id': 5678, 'release_date': release_date, 'release_name': '36 Chambers: Enter The Digital Clan', 'release_status': 'label_processing', 'sale_start_date': sale_start_date, 'special_instructions': 'New instructions', 'upc': upc, 'display_upc': '111111111111', 'vendor_catalog_number': 'DigProdNumber1', 'version': None} @pytest.fixture def delivered_release_payload(preorder_date, product_id, release_date, sale_start_date, upc): """Return a fake response payload from the release model.""" return { 'release_id': product_id, 'artist_id': 7923, 'c_line': '2016 This is important info', 'description': 'New description here', 'distribution_format_id': 1, 'format': 'Single', 'genre_id': 13, 'itunes_previewable': 'yes', 'label': 'A new and fantastic label', 'manufacturer_upc': '123456789012', 'meta_language': 'SUX', 'preorder_date': preorder_date, 'product_code': 'DIGI4LYFE', 'product_type_id': 1, 'project_id': 5678, 'release_date': release_date, 'release_name': '36 Chambers: Enter The Digital Clan', 'release_status': 'in_content', 'sale_start_date': sale_start_date, 'special_instructions': 'New instructions', 'upc': upc, 'display_upc': '111111111111', 'vendor_catalog_number': 'DigProdNumber1', 'version': None } @pytest.fixture def submitted_release_payload(preorder_date, product_id, release_date, sale_start_date, upc): """Return a fake response payload from the release model.""" return { 'release_id': product_id, 'artist_id': 7923, 'c_line': '2016 This is important info', 'description': 'New description here', 'distribution_format_id': 1, 'format': 'Single', 'genre_id': 13, 'itunes_previewable': 'yes', 'label': 'A new and fantastic label', 'manufacturer_upc': '123456789012', 'meta_language': 'SUX', 'p_line': '2020 PLINE', 'preorder_date': preorder_date, 'product_code': 'DIGI4LYFE', 'product_type_id': 1, 'project_id': 5678, 'release_date': release_date, 'release_name': '36 Chambers: Enter The Digital Clan', 'release_status': 'transfer_to_content', 'sale_start_date': sale_start_date, 'special_instructions': 'New instructions', 'upc': upc, 'display_upc': '111111111111', 'vendor_catalog_number': 'DigProdNumber1', 'version': None } @pytest.fixture def expected_product_message(release_payload): """Given the release_payload, this is the product response message.""" return { 'artist_id': release_payload['artist_id'], 'description': release_payload['description'], 'delivered_version': release_payload['delivered_version'], 'distribution_format_id': release_payload['distribution_format_id'], 'format': release_payload['format'], 'genre_id': release_payload['genre_id'], 'c_line': release_payload['c_line'], 'imprint': release_payload['label'], 'manufacturer_upc': release_payload['manufacturer_upc'], 'meta_language': release_payload['meta_language'], 'p_line': release_payload['p_line'], 'previewable': release_payload['itunes_previewable'], 'preorder_date': release_payload['preorder_date'], 'product_artists': [], 'product_code': release_payload['product_code'], 'product_name': release_payload['release_name'], 'product_type_id': release_payload['product_type_id'], 'project_id': release_payload['project_id'], 'product_id': release_payload['release_id'], 'release_date': release_payload['release_date'], 'release_status': 'label_processing', 'is_error_correction_and_action_required': False, 'sale_start_date': release_payload['sale_start_date'], 'special_instructions': release_payload['special_instructions'], 'subaccount_id': None, 'subgenre_id': None, 'upc': release_payload['display_upc'], 'vendor_catalog_number': release_payload['vendor_catalog_number'], 'version': release_payload['version'], 'not_for_distribution': None, } @pytest.fixture def cr_ff_disabled(mocker): """Given the release_payload, this is the product response message.""" mocker.patch.object( features, 'is_rejections_from_content_review_enabled', return_value=False) @db.test_schema def test_update_release_saved( mocker, preorder_date, product_id, product_props, release_date, release_payload, sale_start_date, cr_ff_disabled, test_request_context, mock_ows_project_get_project ): """Test response contents when update is successful.""" expected_release_props = { 'artist_id': 7923, 'c_line': '2016 This is important info', 'delivered_version': 'Live at Wembley', 'description': 'New description here', 'release_format': 'Single', 'genre_id': 13, 'itunes_previewable': 'yes', 'label': 'A new and fantastic label', 'manufacturer_upc': '123456789012', 'meta_language': 'SUX', 'p_line': '2020 PLINE', 'preorder_date': preorder_date, 'release_date': release_date, 'release_name': '36 Chambers: Enter The Digital Clan', 'product_code': 'DIGI4LYFE', 'sale_start_date': sale_start_date, 'special_instructions': 'New instructions', 'version': 'Extremely Explicit Version'} release_response = response.Response(message=release_payload) mocker.patch.object(release, 'update', return_value=release_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) audio_product.update(product_id, product_props) release.update.assert_called_with( product_id, expected_release_props, '') @db.test_schema def test_create_release_saved_for_subaccount( mocker, subaccount_product_props, release_payload, cr_ff_disabled): """Test that subaccount information is included on create.""" expected_release_props = { 'artist_id': 7923, 'release_format': 'Single', 'release_name': 'Two Originals of Jack Rose', 'product_code': 'TWOROSE', 'version': 'Extremely Explicit Version', 'subaccount_id': 999} release_response = response.Response(message=release_payload) mocker.patch.object(release, 'create', return_value=release_response) audio_product.create(subaccount_product_props) release.create.assert_called_with(expected_release_props) @db.test_schema def test_update_release_saved_with_vendor_release_identifier( mocker, preorder_date, product_id, product_props, release_date, release_payload, sale_start_date, cr_ff_disabled, mock_ows_project_get_project): """Test response contents when update is successful.""" vendor_release_identifier = 'some_vendor_id' expected_release_props = { 'artist_id': 7923, 'c_line': '2016 This is important info', 'delivered_version': 'Live at Wembley', 'description': 'New description here', 'release_format': 'Single', 'genre_id': 13, 'itunes_previewable': 'yes', 'label': 'A new and fantastic label', 'manufacturer_upc': '123456789012', 'meta_language': 'SUX', 'p_line': '2020 PLINE', 'preorder_date': preorder_date, 'release_date': release_date, 'release_name': '36 Chambers: Enter The Digital Clan', 'product_code': 'DIGI4LYFE', 'sale_start_date': sale_start_date, 'special_instructions': 'New instructions', 'version': 'Extremely Explicit Version', 'vendor_release_identifier': vendor_release_identifier} release_payload['vendor_release_identifier'] = vendor_release_identifier product_props['vendor_release_identifier'] = vendor_release_identifier release_response = response.Response(message=release_payload) mocker.patch.object(release, 'update', return_value=release_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) audio_product.update(product_id, product_props) release.update.assert_called_with( product_id, expected_release_props, '') @db.test_schema def test_update_release_response( mocker, product_id, product_props, release_payload, expected_product_message, cr_ff_disabled, mock_ows_project_get_project): """Test response payload on successful save.""" release_response = response.Response(message=release_payload) mocker.patch.object(release, 'update', return_value=release_response) mock_response = MagicMock(status_code=404, message=None) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.update(product_id, product_props) assert product_response.status == 200 assert product_response.message == expected_product_message @db.test_schema def test_update_checked_out_release_response(mocker, product_id, product_props): """Test response payload on successful save.""" mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=response.Response( status=200, message={'status': 'checked_out'})) product_response = audio_product.update(product_id, product_props) assert product_response.status == 400 assert product_response.errors == { 'code': 'internal_error', 'message': 'Product is already checked out'} @db.test_schema def test_update_checked_out_release_as_different_user_response_error( mocker, product_id, product_props, release_payload, expected_product_message, cr_ff_disabled, mock_ows_project_get_project): """Test respone payload for already checked out error. Ensures that non checked_out_by user trying to update the product fails. """ release_response = response.Response(message=release_payload) mocker.patch.object(release, 'update', return_value=release_response) mock_response = MagicMock(status=200, message={'status': 'checked_out', 'checked_out_by': 1233}) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) expected_product_message['release_approval_status'] = 'checked_out' product_response = audio_product.update(product_id, product_props, 'oa:1234') assert product_response.status == 400 assert product_response.errors == { 'code': 'internal_error', 'message': 'Product is already checked out'} @db.test_schema def test_update_checked_out_release_as_checked_out_user_response_success( mocker, product_id, product_props, release_payload, expected_product_message, cr_ff_disabled, mock_ows_project_get_project): """Test response payload on successful save. Ensures that checked_out_by user can update the product. """ release_response = response.Response(message=release_payload) mocker.patch.object(release, 'update', return_value=release_response) mock_response = MagicMock(status=200, message={'status': 'checked_out', 'checked_out_by': 1234}) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) expected_product_message['release_approval_status'] = 'checked_out' product_response = audio_product.update(product_id, product_props, 'oa:1234') assert product_response.status == 200 assert product_response.message == expected_product_message def test_update_release_error(mocker, product_id, product_props): """Test that an error is returned when saving release data fails.""" release_response = response.Response(status=500) mocker.patch.object(release, 'update', return_value=release_response) mocker.patch.object( ows_product_workflow, 'is_product_checked_out_by_another_user', return_value=False) mocker.patch.object( audio_product, '_is_genre_change', return_value=MagicMock(status_code=200, message=None)) mocker.patch.object( ows_track, 'change_genre', return_value=MagicMock(status_code=200, message=None)) result = audio_product.update(product_id, product_props) assert result.status == 500 assert result.errors == { 'code': 'internal_error', 'message': 'failed to save product'} @db.test_schema def test_update_release_subgenre_saved( mocker, product_id, upc, cr_ff_disabled, test_request_context, mock_ows_project_get_project, expected_create_product_response_message): """Test that the subgenre mapping is saved when subgenre_id included.""" subgenre_id = 9423 subgenre_props = { 'upc': upc, 'subgenre_id': subgenre_id} release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) subgenre_response = response.Response(message={'subgenre_id': subgenre_id}) mocker.patch.object( release_subgenre, 'save_release_subgenre', return_value=subgenre_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) result = audio_product.update(product_id, subgenre_props) release_subgenre.save_release_subgenre.assert_called_with({ 'release_id': product_id, 'subgenre_id': subgenre_id, 'upc': upc}) assert result.status == 200 assert result.message['subgenre_id'] == subgenre_id def test_update_release_subgenre_error( mocker, product_id, upc, expected_create_product_response_message, test_request_context, mock_ows_project_get_project): """Test that an error is returned if saving subgenre fails.""" subgenre_id = 9423 subgenre_props = { 'upc': upc, 'subgenre_id': subgenre_id} release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) subgenre_response = response.Response(status=500) mocker.patch.object( release_subgenre, 'save_release_subgenre', return_value=subgenre_response) mocker.patch.object( ows_product_workflow, 'is_product_checked_out_by_another_user', return_value=False) mocker.patch.object( audio_product, '_is_soundtrack_subgenre_change', return_value=MagicMock(status_code=200, message=None)) mocker.patch.object( ows_track, 'change_genre', return_value=MagicMock(status_code=200, message=None)) result = audio_product.update(product_id, subgenre_props) assert result.status == 500 assert result.errors == { 'code': 'internal_error', 'message': 'failed to save subgenre'} def test_update_release_subgenre_null( mocker, product_id, cr_ff_disabled, expected_create_product_response_message, mock_ows_project_get_project, test_request_context): """Test the successful calling of the subgenre delete method.""" release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) mocker.patch.object( release_subgenre, 'delete_release_subgenre', return_value=response.Response()) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response({})) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) update_product_payload = {'subgenre_id': None} result = audio_product.update(product_id, update_product_payload) assert result.status == 200 release_subgenre.delete_release_subgenre.assert_called_with(product_id) def test_update_product_not_found(mocker, product_id): """Test that a 404 is returned if the release does not exist.""" release_response = response.Response(status=404) mocker.patch.object(release, 'update', return_value=release_response) mocker.patch.object( ows_product_workflow, 'is_product_checked_out_by_another_user', return_value=False) props_for_update = { 'release_name': 'does not matter because the product does not exist'} product_response = audio_product.update(product_id, props_for_update) assert product_response.status == 404 @db.test_schema def test_update_not_submitted_error_correction_feature_flag_on( mocker, product_id, product_props, release_correction_get_message, submitted_release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Test that an updated product will return error correction status.""" # We use the submitted fixture because .update will transition # the product to submitted. release_response = response.Response(message=submitted_release_payload) mocker.patch.object(release, 'update', return_value=release_response) get_last_release_correction_response = response.Response( message=release_correction_get_message ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=get_last_release_correction_response ) mock_response = MagicMock(message=({'status': 'checked_in'})) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.update(product_id, audio_data=product_props) # The release should have a status of error_correction because there is # an active release_correction assert product_response.status == 200 assert product_response.message['release_status'] == 'error_correction' assert product_response.message['release_approval_status'] == 'checked_in' assert 'corrections' in product_response.message assert product_response.message['corrections'] == { 'release_correction_id': 1, 'status': 'active', 'items': [ { 'release_correction_detail_id': 1, 'table_name': 'releases', 'field_name': 'primary', 'key_id': 288212, 'key_value': 'HEY HEY HEY' }, { 'release_correction_detail_id': 2, 'table_name': 'releases', 'field_name': 'primary', 'key_id': 288213, 'key_value': 'EYH EYH EYH' }, { 'release_correction_detail_id': 3, 'table_name': 'releases', 'field_name': 'primary', 'key_id': 288214, 'key_value': 'HYE HYE HYE' } ] } @db.test_schema def test_update_not_submitted_no_details_error_correction_feature_flag_on( mocker, product_id, product_props, submitted_release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Test that an updated product will return error correction status. Also ensure that even though there are no details it will still return corrections key. """ # We use the submitted fixture becuase .update will transition # the product to submitted. release_response = response.Response(message=submitted_release_payload) mocker.patch.object(release, 'update', return_value=release_response) get_last_release_correction_response = response.Response( message={ 'release_correction_id': 1, 'status': 'active', 'items': [] } ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=get_last_release_correction_response ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.update(product_id, audio_data=product_props) # The release should have a status of error_correction because there is # an active release_correction assert product_response.status == 200 assert product_response.message['release_status'] == 'error_correction' assert 'corrections' in product_response.message @db.test_schema def test_update_not_submitted_with_no_correction( mocker, product_id, product_props, release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Test updating a not submitted product that has no release correction. Error correction flag is on. """ """Test that an updated product will return error correction status. Also ensure that even though there are no details it will still return corrections key. """ release_response = response.Response(message=release_payload) mocker.patch.object(release, 'update', return_value=release_response) get_last_release_correction_response = response.Response(status=404) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=get_last_release_correction_response ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.update(product_id, audio_data=product_props) assert product_response.status == 200 # Status can't be in error correction if release_correction not found. assert product_response.message['release_status'] == 'label_processing' # No release_correction_details if there is no release_correction. assert 'corrections' not in product_response.message @db.test_schema def test_update_not_submitted_with_error_getting_correction( mocker, product_id, product_props, submitted_release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Test updating a not submitted with was error getting release correction. Error Correction flag is on. """ # We use the submitted fixture becuase .update will transition # the product to submitted. release_response = response.Response(message=submitted_release_payload) mocker.patch.object(release, 'update', return_value=release_response) get_last_release_correction_response = response.Response(status=500) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=get_last_release_correction_response ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.update(product_id, audio_data=product_props) # Return release_correction response fatal error received. assert product_response.status == 500 assert product_response == get_last_release_correction_response @db.test_schema def test_update_submitted_error_correction_feature_flag_on( mocker, product_id, product_props, release_correction_submitted_get_message, submitted_release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Test updating a submitted product will update release_correction.""" release_response = response.Response(message=submitted_release_payload) mocker.patch.object(release, 'update', return_value=release_response) get_last_release_correction_response = response.Response( message=release_correction_submitted_get_message ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=get_last_release_correction_response ) mocker.patch.object( ows_product_workflow, 'update_release_correction' ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.update(product_id, audio_data=product_props) assert product_response.status == 200 # The release should not be in error_correction if it is submitted. assert product_response.message['release_status'] == 'transfer_to_content' assert product_response.message['corrections'] == \ release_correction_submitted_get_message @db.test_schema def test_update_submitted_error_correction_feature_flag_on_artwork_correction( mocker, product_id, product_props, submitted_release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Test updating a submitted product will update release_correction.""" release_response = response.Response(message=submitted_release_payload) mocker.patch.object(release, 'update', return_value=release_response) approval_response = response.Response(message={'status': 'checked_in'}) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=approval_response) release_correction_submitted_get_message = { 'status': 'submitted', 'items': [ { 'release_correction_detail_id': 1, 'table_name': 'releases', 'field_name': 'coverart', 'key_id': 288212, 'key_value': True } ] } release_correction_response = response.Response( message=release_correction_submitted_get_message ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=release_correction_response ) image_url = 'image.example.com' mocker.patch.object( ows_assets, 'get_correction_image', return_value=response.Response(message={ 'image': image_url }) ) mocker.patch.object( ows_product_workflow, 'update_release_correction' ) product_response = audio_product.update(product_id, audio_data=product_props) assert product_response.status == 200 # The release should not be in error_correction if it is submitted. assert product_response.message['release_status'] == 'transfer_to_content' assert product_response.message['corrections'] == \ release_correction_submitted_get_message correction_detail = product_response.message['corrections']['items'][0] assert correction_detail['key_value'] == image_url @db.test_schema def test_update_submitted_and_checked_in_and_error_correction_feature_flag_on( mocker, product_id, product_props, release_correction_submitted_get_message, submitted_release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Test updating a submitted product will update release_correction.""" release_response = response.Response(message=submitted_release_payload) mocker.patch.object(release, 'update', return_value=release_response) get_last_release_correction_response = response.Response( message=release_correction_submitted_get_message ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=get_last_release_correction_response ) mocker.patch.object( ows_product_workflow, 'update_release_correction' ) approval_response = response.Response(message={'status': 'checked_in'}) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=approval_response) product_response = audio_product.update(product_id, audio_data=product_props) assert product_response.status == 200 # The release should not be in error_correction if it is submitted. assert product_response.message['release_status'] == 'transfer_to_content' assert product_response.message['corrections'] == \ release_correction_submitted_get_message assert product_response.message['release_approval_status'] == 'checked_in' @db.test_schema def test_update_submitted_and_checked_out_and_error_correction_feature_flag_on( mocker, product_id, product_props, release_correction_submitted_get_message, submitted_release_payload ): """Test updating a submitted product will update release_correction.""" release_response = response.Response(message=submitted_release_payload) mocker.patch.object(release, 'update', return_value=release_response) get_last_release_correction_response = response.Response( message=release_correction_submitted_get_message ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=get_last_release_correction_response ) mocker.patch.object( ows_product_workflow, 'update_release_correction' ) approval_response = response.Response(message={'status': 'checked_out'}) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=approval_response) product_response = audio_product.update(product_id, audio_data=product_props) assert product_response.status == 400 assert product_response.errors == { 'code': 'internal_error', 'message': 'Product is already checked out' } def test_create_product_success( expected_product_payload, mocker, expected_create_release_response_message, expected_create_product_response_message, test_request_context, mock_ows_project_get_project): """Test the creation of an audio product when upc is included.""" release_response = response.Response( status=201, message=expected_create_release_response_message) mocker.patch.object(release, 'create', return_value=release_response) product_response = audio_product.create(expected_product_payload) assert product_response.status == 201 assert product_response.message == expected_create_product_response_message def test_create_product_failure(expected_product_payload, mocker): """Test the creation of an audio product when upc is included.""" release_response = response.create_fatal_response() mocker.patch.object(release, 'create', return_value=release_response) product_response = audio_product.create(expected_product_payload) assert product_response.status == 500 def test_clean_audio_product_to_release_data(): """Test clean_audio_product_to_release_data utility function.""" data = { 'product_name': 'Test product', 'previewable': True, 'imprint': 'Test label', 'not_in_properties': 'Should not be present', 'release_property': 'Should be present', } expected_release_data = { 'release_name': 'Test product', 'itunes_previewable': True, 'label': 'Test label', 'release_property': 'Should be present', } properties = ['release_property'] prepared_data = audio_product.clean_audio_product_to_release_data( data, properties) assert prepared_data == expected_release_data @db.test_schema def test_update_product_subgenre_not_given( mocker, product_id, cr_ff_disabled, test_request_context, mock_ows_project_get_project, expected_create_product_response_message): """Test that the subgenre id is fetched if not given.""" subgenre_id = 3939 release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) subgenre_response = response.Response(message={'subgenre_id': subgenre_id}) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=subgenre_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) props_for_update = {'product_name': 'A better name for a better product'} product_response = audio_product.update(product_id, props_for_update) release_subgenre.get_release_subgenre_by_release_id.assert_called_with( product_id) assert product_response.message['subgenre_id'] == subgenre_id @db.test_schema def test_update_product_artists_saved( mocker, product_id, upc, cr_ff_disabled, test_request_context, mock_ows_project_get_project, expected_create_product_response_message): """Test that product artists are saved when given.""" product_artists = [ { 'id': 120, 'role': 'primary_artist', 'name': 'Primary Pete', }, { 'id': 123, 'role': 'remixer', 'name': 'Mix-Master Ma$ha' } ] props_for_update = {'product_artists': product_artists} release_artists = [ { 'role': 'performer', 'artist_name': 'Primary Pete', 'release_artist_id': 120 }, { 'role': 'remixer', 'artist_name': 'Mix-Master Ma$ha', 'release_artist_id': 123 } ] release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) artists_response = response.Response(message=release_artists) mocker.patch.object( release_artist, 'save_for_release_id', return_value=artists_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) audio_product.update(product_id, props_for_update) release_artist.save_for_release_id.assert_called_with( product_id, upc, release_artists) @db.test_schema def test_update_product_artists_artist_info_id_saved( mocker, product_id, upc, cr_ff_disabled, test_request_context, mock_ows_project_get_project, expected_create_product_response_message): """Test that product artists with artist_info_ids are saved when given.""" product_artists = [ { 'id': 120, 'role': 'primary_artist', 'name': 'Primary Pete', 'artist_info_id': 1234 }, { 'id': 123, 'role': 'remixer', 'name': 'Mix-Master Ma$ha', 'artist_info_id': 1234 } ] props_for_update = {'product_artists': product_artists} release_artists = [ { 'role': 'performer', 'artist_name': 'Primary Pete', 'release_artist_id': 120, 'artist_info_id': 1234 }, { 'role': 'remixer', 'artist_name': 'Mix-Master Ma$ha', 'release_artist_id': 123, 'artist_info_id': 1234 } ] release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) artists_response = response.Response(message=release_artists) mocker.patch.object( release_artist, 'save_for_release_id', return_value=artists_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) audio_product.update(product_id, props_for_update) release_artist.save_for_release_id.assert_called_with( product_id, upc, release_artists) @db.test_schema def test_update_product_artists_artist_info_id_null_saved( mocker, product_id, upc, cr_ff_disabled, test_request_context, mock_ows_project_get_project, expected_create_product_response_message): """Test that product artists with artist_info_ids of null are saved.""" product_artists = [ { 'id': 120, 'role': 'primary_artist', 'name': 'Primary Pete', 'artist_info_id': None }, { 'id': 123, 'role': 'remixer', 'name': 'Mix-Master Ma$ha', 'artist_info_id': None } ] props_for_update = {'product_artists': product_artists} release_artists = [ { 'role': 'performer', 'artist_name': 'Primary Pete', 'release_artist_id': 120, 'artist_info_id': None }, { 'role': 'remixer', 'artist_name': 'Mix-Master Ma$ha', 'release_artist_id': 123, 'artist_info_id': None } ] release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) artists_response = response.Response(message=release_artists) mocker.patch.object( release_artist, 'save_for_release_id', return_value=artists_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) audio_product.update(product_id, props_for_update) release_artist.save_for_release_id.assert_called_with( product_id, upc, release_artists) @db.test_schema def test_update_product_artists_cleared_when_empty( mocker, product_id, upc, cr_ff_disabled, test_request_context, mock_ows_project_get_project, expected_create_product_response_message): """Test that product artists are cleared if an empty list is given.""" release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) props_for_update = {'product_artists': []} artists_response = response.Response(message=[]) mocker.patch.object( release_artist, 'save_for_release_id', return_value=artists_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) audio_product.update(product_id, props_for_update) release_artist.save_for_release_id.assert_called_with(product_id, upc, []) @db.test_schema def test_update_product_artists_cleared_when_null( mocker, product_id, upc, cr_ff_disabled, test_request_context, mock_ows_project_get_project, expected_create_product_response_message): """Test that product artists are cleared if given a null value.""" release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) props_for_update = {'product_artists': None} artists_response = response.Response(message=[]) mocker.patch.object( release_artist, 'save_for_release_id', return_value=artists_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) audio_product.update(product_id, props_for_update) release_artist.save_for_release_id.assert_called_with(product_id, upc, []) @db.test_schema def test_update_product_artists_not_given( mocker, product_id, upc, cr_ff_disabled, test_request_context, mock_ows_project_get_project, expected_create_product_response_message): """Test that artists are fetched if not given.""" release_response = response.Response( message=expected_create_product_response_message) mocker.patch.object(release, 'update', return_value=release_response) artists_response_message = [{ 'release_artist_id': 123, 'release_id': 456, 'upc': upc, 'role': 'sousaphonist', 'artist_name': 'Jacob Fowler'}] artists_response = response.Response(message=artists_response_message) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=artists_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.update(product_id, {'upc': upc}) assert product_response.message['product_artists'] == [{ 'artist_info_id': None, 'role': 'sousaphonist', 'name': 'Jacob Fowler', 'id': 123}] @db.test_schema def test_get_product( release_payload, product_id, mocker, expected_product_message, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Test fetching a product based on product id.""" expected_product_message['catalog_transfer_info'] = None release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response(message=[])) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mock_response = MagicMock(status_code=404, message=None) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 assert product_response.message == expected_product_message @db.test_schema def test_get_product_with_ff_contentreview( release_payload, product_id, mocker, expected_product_message, get_status_message, test_request_context, mock_ows_project_get_project): """Test fetching a product with content-review ff on.""" mocker.patch.object(features, 'is_rejections_from_content_review_enabled', return_value=True) expected_product_message.update({ 'release_approval_status': 'checked_in', 'catalog_transfer_info': None, }) release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response(message=[])) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mock_response = MagicMock(status_code=404, message=None) approval_response = response.Response(message=get_status_message) mocker.patch.object( ows_product_review, 'get_status', return_value=approval_response) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) ows_product_workflow.get_last_release_approval_queue.assert_not_called() assert product_response.status == 200 assert product_response.message == expected_product_message @db.test_schema def test_get_product_with_ff_contentreview_status_error( release_payload, product_id, mocker, test_request_context, mock_ows_project_get_project): """Return content-review status error without workflow fallback.""" mocker.patch.object( features, 'is_rejections_from_content_review_enabled', return_value=True) release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response(message=[])) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mocker.patch.object( ows_product_review, 'get_status', return_value=response.create_error_response( code='internal_error', message='status failed', status=500)) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=MagicMock(status_code=404, message=None)) product_response = audio_product.get_product(product_id) ows_product_workflow.get_last_release_approval_queue.assert_not_called() assert product_response.status == 500 assert product_response.errors == { 'code': 'internal_error', 'message': 'status failed'} @db.test_schema def test_get_product_with_ff_contentreview_status_not_available( release_payload, product_id, mocker, expected_product_message, test_request_context, mock_ows_project_get_project): """Use the default approval payload when content-review is missing.""" expected_product_message['catalog_transfer_info'] = None mocker.patch.object( features, 'is_rejections_from_content_review_enabled', return_value=True) release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response(message=[])) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mocker.patch.object( ows_product_review, 'get_status', return_value=response.create_error_response( code='not_found_error', message='Status not found', status=404)) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=MagicMock(status_code=404, message=None)) product_response = audio_product.get_product(product_id) ows_product_workflow.get_last_release_approval_queue.assert_not_called() assert product_response.status == 200 assert product_response.message == expected_product_message @db.test_schema def test_get_rejected_product_with_ff_contentreview( release_payload, product_id, mocker, expected_product_message, get_rejected_status_message, get_rejections_message, test_request_context, mock_ows_project_get_project): """Test fetching a rejected product with content-review ff on.""" mocker.patch.object( features, 'is_rejections_from_content_review_enabled', return_value=True) release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response(message=[])) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mock_response = MagicMock(status_code=404, message=None) approval_response = response.Response(message=get_rejected_status_message) get_rejections_response = response.Response(message=get_rejections_message) mocker.patch.object( ows_product_review, 'get_status', return_value=approval_response) mocker.patch.object( ows_product_review, 'get_rejection', return_value=get_rejections_response) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) features.is_rejections_from_content_review_enabled.assert_called_once() ows_product_workflow.get_last_release_approval_queue.assert_not_called() assert product_response.status == 200 assert product_response.message['release_status'] == 'action_required' assert 'rejections' in product_response.message @db.test_schema def test_get_rejected_error_corrected_product_with_ff_contentreview( release_payload, product_id, mocker, expected_product_message, get_rejected_status_message, get_rejections_message, test_request_context, mock_ows_project_get_project): """Test fetching a rejected product with content-review ff on.""" mocker.patch.object( features, 'is_rejections_from_content_review_enabled', return_value=True) release_payload['release_status'] = 'in_content' release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response(message=[])) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mock_response = MagicMock(status_code=404, message=None) approval_response = response.Response(message=get_rejected_status_message) get_rejections_response = response.Response(message=get_rejections_message) mocker.patch.object( ows_product_review, 'get_status', return_value=approval_response) mocker.patch.object( ows_product_review, 'get_rejection', return_value=get_rejections_response) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) release_correction_response = { 'status': 'active', 'items': [ { 'release_correction_detail_id': 1, 'table_name': 'releases', 'field_name': 'release_name', 'key_id': product_id, 'key_value': 'random' } ] } mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=response.Response(message=release_correction_response) ) product_response = audio_product.get_product(product_id) features.is_rejections_from_content_review_enabled.assert_called_once() ows_product_workflow.get_last_release_approval_queue.assert_not_called() assert product_response.status == 200 assert product_response.message['release_status'] == 'action_required' assert product_response.message['is_error_correction_and_action_required'] is True assert product_response.message['corrections'] == release_correction_response assert 'rejections' in product_response.message @db.test_schema def test_get_product_with_catalog_transfer_info( release_payload, product_id, mocker, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Test fetching a product that has a catalog transfer record.""" release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response(message=[])) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) db.seed_models(catalog_transfer_factory.CatalogTransferFactory.build( release_id=product_id, original_distributor='Distrokid', same_isrc_upc='Y')) product_response = audio_product.get_product(product_id) assert product_response.message['catalog_transfer_info'] == { 'original_distributor': 'Distrokid', 'same_isrc_upc': True, } @db.test_schema def test_get_product_with_catalog_transfer_info_same_isrc_upc_false( release_payload, product_id, mocker, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Test that same_isrc_upc 'N' converts to boolean False.""" release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response(message=[])) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) db.seed_models(catalog_transfer_factory.CatalogTransferFactory.build( release_id=product_id, original_distributor='Some Distributor', same_isrc_upc='N')) product_response = audio_product.get_product(product_id) assert product_response.message['catalog_transfer_info'] == { 'original_distributor': 'Some Distributor', 'same_isrc_upc': False, } @db.test_schema def test_get_product_with_subgenre( release_payload, product_id, mocker, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Test fetching a product based on product id that has a subgenre_id.""" subgenre_id = 3939 release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=response.Response(message=[])) subgenre_response = response.Response(message={'subgenre_id': subgenre_id}) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=subgenre_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) release_subgenre.get_release_subgenre_by_release_id.assert_called_with( product_id) assert product_response.message['subgenre_id'] == subgenre_id @db.test_schema def test_get_product_with_product_artists( release_payload, product_id, mocker, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Test fetching a product based on product id that has product artists.""" release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) artists_response_message = [{ 'artist_info_id': None, 'role': 'performer', 'artist_name': 'David Banner', 'release_artist_id': 1}] expected_artists = [{ 'artist_info_id': None, 'role': 'primary_artist', 'name': 'David Banner', 'id': 1}] artists_response = response.Response(message=artists_response_message) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=artists_response) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 assert product_response.message['product_artists'] == expected_artists def test_get_product_not_found(product_id, mocker): """Test fetching a product based on product id.""" response_404 = response.create_not_found_response() mocker.patch.object(release, 'get_release', return_value=response_404) product_response = audio_product.get_product(product_id) assert product_response.status == 404 @db.test_schema def test_get_product_action_required( mocker, product_id, release_payload, get_rejections_message, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Expect status of "action_required" if last approval was rejected.""" release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) approval_response = response.Response(message={'status': 'rejected'}) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=approval_response) get_rejections_response = response.Response(message=get_rejections_message) mocker.patch.object( ows_product_workflow, 'get_rejections', return_value=get_rejections_response) product_response = audio_product.get_product( product_id) assert product_response.status == 200 assert product_response.message['release_status'] == 'action_required' assert 'rejections' in product_response.message @db.test_schema def test_get_product_action_not_required( mocker, product_id, release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Do not expect "action_required" status if last approval not rejected.""" release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) approval_response = response.Response(message={'status': 'approved'}) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=approval_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 status_from_db = release_payload['release_status'] assert product_response.message['release_status'] == status_from_db @db.test_schema def test_get_product_approval_error( mocker, product_id, release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Expect error response if there is an error fetching release approval.""" release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) approval_error = response.create_fatal_response('facepalm') mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=approval_error) product_response = audio_product.get_product(product_id) assert product_response.status == 500 assert product_response.errors == { 'code': 'internal_error', 'message': 'facepalm'} @db.test_schema def test_get_product_ec_and_ar_required_feature_flag_on( mocker, product_id, release_payload, get_rejections_message, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Expect status of "action_required" and to include corrections.""" release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) approval_response = response.Response( message={'status': 'rejected', 'release_correction_id': 123}) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=approval_response) get_rejections_response = response.Response(message=get_rejections_message) mocker.patch.object( ows_product_workflow, 'get_rejections', return_value=get_rejections_response) release_correction_response = response.Response( message={ 'status': 'active', 'items': [ { 'release_correction_detail_id': 1, 'table_name': 'releases', 'field_name': 'primary', 'key_id': 288212, 'key_value': 'HEY HEY HEY' } ] } ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=release_correction_response ) product_response = audio_product.get_product(product_id) assert product_response.status == 200 assert product_response.message['release_status'] == 'action_required' assert \ product_response.message['is_error_correction_and_action_required'] \ is True assert 'rejections' in product_response.message assert 'corrections' in product_response.message @db.test_schema def test_get_product_error_correction( delivered_release_payload, mocker, product_id, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Expect status of in_content . Status is not modified. """ release_response = response.Response(message=delivered_release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) release_approval_response = response.Response( message={ 'status': 'checked_in' } ) mocker.patch.object(ows_product_workflow, 'get_last_release_approval_queue', return_value=release_approval_response) mock_response = MagicMock(status=404, message=None) mocker.patch.object(ows_product_workflow, 'get_last_release_correction', return_value=mock_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 assert product_response.message['release_status'] == 'in_content' @db.test_schema def test_get_product_error_correction_feature_flag_on( delivered_release_payload, mocker, product_id, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Expect status of "error_correction" if last approval was active.""" release_response = response.Response(message=delivered_release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) release_correction_response = response.Response( message={ 'status': 'active', 'items': [ { 'release_correction_detail_id': 1, 'table_name': 'releases', 'field_name': 'primary', 'key_id': 288212, 'key_value': 'HEY HEY HEY' } ] } ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=release_correction_response ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 assert product_response.message['release_status'] == 'error_correction' assert 'corrections' in product_response.message @db.test_schema def test_get_product_error_correction_feature_flag_on_not_submitted_product( mocker, product_id, release_payload, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Expect status of "label_processing" if last approval was active. Products that are not in_content should not have error_correction status. """ release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) release_correction_response = response.Response( message={'status': 'active'} ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=release_correction_response ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 assert product_response.message['release_status'] == 'label_processing' assert 'corrections' not in product_response.message @db.test_schema def test_get_product_error_correction_submitted( delivered_release_payload, mocker, product_id, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Status is "transfer_to_content" if last correction is submitted. The release also needs to be delivered (in_content). Payload should still contain correction information. """ release_response = response.Response(message=delivered_release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) release_correction_response = response.Response( message={'items': [], 'status': 'submitted'} ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=release_correction_response ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 assert product_response.message['release_status'] == 'transfer_to_content' assert 'corrections' in product_response.message @db.test_schema def test_get_submitted_product_with_submitted_correction( submitted_release_payload, mocker, product_id, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Status is not "error_correction" if last correction is submitted. Payload should still contain correction information. Payload should contain release_approval_status. """ release_response = response.Response(message=submitted_release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) approval_response = response.Response(message={'status': 'submitted'}) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=approval_response) release_correction_response = response.Response( message={'items': [], 'status': 'submitted'} ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=release_correction_response ) product_response = audio_product.get_product(product_id) assert product_response.status == 200 status_from_db = submitted_release_payload['release_status'] assert product_response.message['release_status'] == status_from_db assert 'corrections' in product_response.message assert 'release_approval_status' in product_response.message @db.test_schema def test_get_product_error_correction_applied( delivered_release_payload, mocker, product_id, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Status is not "error_correction" if last correction is applied.""" release_response = response.Response(message=delivered_release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) release_correction_response = response.Response( message={'status': 'applied'} ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=release_correction_response ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 status_from_db = delivered_release_payload['release_status'] assert product_response.message['release_status'] == status_from_db @db.test_schema def test_get_product_error_correction_detail_for_coverart( delivered_release_payload, mocker, product_id, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """The key value of cover art correction detail should be a url.""" release_response = response.Response(message=delivered_release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) release_correction_response = response.Response( message={ 'status': 'active', 'items': [ { 'release_correction_detail_id': 1, 'table_name': 'releases', 'field_name': 'coverart', 'key_id': 288212, 'key_value': True } ] } ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=release_correction_response ) image_url = 'image.example.com' mocker.patch.object( ows_assets, 'get_correction_image', return_value=response.Response(message={ 'image': image_url }) ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 correction_detail = product_response.message['corrections']['items'][0] assert correction_detail['key_value'] == image_url @db.test_schema def test_get_product_error_correction_detail_for_coverart_image_not_found( delivered_release_payload, mocker, product_id, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """The key value of cover art correction detail should be a url.""" release_response = response.Response(message=delivered_release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) release_correction_response = response.Response( message={ 'status': 'active', 'items': [ { 'release_correction_detail_id': 1, 'table_name': 'releases', 'field_name': 'coverart', 'key_id': 288212, 'key_value': True } ] } ) mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=release_correction_response ) mocker.patch.object( ows_assets, 'get_correction_image', return_value=response.Response(message={ 'code': 'not_found_error', 'message': 'Image not found.' }, status=404) ) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_product(product_id) assert product_response.status == 200 correction_detail = product_response.message['corrections']['items'][0] assert correction_detail['key_value'] is None @db.test_schema def test_get_product_correction_error( delivered_release_payload, mocker, product_id, cr_ff_disabled, test_request_context, mock_ows_project_get_project, ): """Error response if there is an error fetching release correction.""" release_response = response.Response(message=delivered_release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) correction_error_response = response.create_fatal_response('facepalm') mocker.patch.object( ows_product_workflow, 'get_last_release_correction', return_value=correction_error_response ) product_response = audio_product.get_product(product_id) assert product_response.status == 500 assert product_response.errors == { 'code': 'internal_error', 'message': 'facepalm' } @db.test_schema def test_update_product_when_move_product_all_status( mocker, preorder_date, product_id, product_props, release_date, release_payload, sale_start_date, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Test update is successful when feature is enabled.""" expected_release_props = { 'artist_id': 7923, 'c_line': '2016 This is important info', 'delivered_version': 'Live at Wembley', 'description': 'New description here', 'release_format': 'Single', 'genre_id': 13, 'itunes_previewable': 'yes', 'label': 'A new and fantastic label', 'manufacturer_upc': '123456789012', 'meta_language': 'SUX', 'p_line': '2020 PLINE', 'preorder_date': preorder_date, 'release_date': release_date, 'release_name': '36 Chambers: Enter The Digital Clan', 'product_code': 'DIGI4LYFE', 'sale_start_date': sale_start_date, 'special_instructions': 'New instructions', 'version': 'Extremely Explicit Version'} release_response = response.Response(message=release_payload) mocker.patch.object(release, 'update', return_value=release_response) mock_response = MagicMock(status_code=200) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) audio_product.update(product_id, product_props) release.update.assert_called_with(product_id, expected_release_props, '') @db.test_schema def test_update_product_soundtrack_subgenre( mocker, product_id, cr_ff_disabled, expected_create_product_response_message, mock_ows_project_get_project, test_request_context): """Test that the subgenre id is fetched if not given.""" subgenre_id = 545 release_response = response.Response(message={ **expected_create_product_response_message, 'upc': upc, 'genre_id': 123, 'subgenre_id': 23 }) mocker.patch.object(release, 'update', return_value=release_response) subgenre_response = response.Response(message={'subgenre_id': subgenre_id}) mocker.patch.object( audio_product, '_is_genre_change', return_value=False) mocker.patch.object( audio_product, 'get_product', return_value=release_response) mocker.patch.object( audio_product, '_save_release_subgenre', return_value=subgenre_response) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_track, 'change_genre', return_value=response.Response(message={'success'}, status=200)) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) props_for_update = { 'product_name': 'A better name for a better product', 'genre_id': 123, 'subgenre_id': subgenre_id} product_response = audio_product.update(product_id, props_for_update, 'alw:5622') assert product_response.message['subgenre_id'] == subgenre_id def test_format_corrections(): """Test _format_correction method.""" release_id = 123 correction_items = [{'release_correction_detail_id': 1234, 'table_name': 'releases', 'field_name': 'release_name', 'key_id': 123, 'key_value': 0}] orchard_user_id = 111 formatted_error_correction_resonse = audio_product._format_corrections( release_id, correction_items, orchard_user_id) for data in formatted_error_correction_resonse: assert isinstance(data['key_value'], str) def test_is_genre_change_null_genre_id(release_payload, product_id, mocker): """Test _is_genre_change method when product's genre_id is NULL.""" release_payload['genre_id'] = None release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) is_genre_change_response = audio_product._is_genre_change(product_id, 5) assert not is_genre_change_response def test_delete_success(product_id, mocker): """Test audio_product.delete method.""" mocker.patch.object( release_artist, 'delete', return_value=response.Response()) mocker.patch.object( release_status, 'delete', return_value=response.Response()) mocker.patch.object( release_subgenre, 'delete_release_subgenre', return_value=response.Response()) mocker.patch.object( mkt_priority, 'bulk_delete_mkt_priority_by_release_id', return_value=response.Response()) mocker.patch.object( ows_timed_release, 'delete_timed_release', return_value=response.Response()) mocker.patch.object( release_logging, 'delete', return_value=response.Response()) mocker.patch.object( release_manual_adjustment, 'delete', return_value=response.Response()) mocker.patch.object( release_grid, 'delete', return_value=response.Response()) mocker.patch.object( release_subtitles, 'delete', return_value=response.Response()) mocker.patch.object( release_approval_queue, 'delete', return_value=response.Response()) mocker.patch.object( track, 'delete_all_tracks', return_value=response.Response()) mocker.patch.object(release, 'delete', return_value=response.Response()) with mysql.db_session() as session: delete_response = audio_product.delete(product_id, session) assert delete_response.status == 200 assert delete_response.message.get('status') == 'ok' def test_delete_failure(product_id, mocker): """Test audio_product.delete returns 400 when some error occurs.""" mocker.patch.object( release_artist, 'delete', return_value=response.Response()) mocker.patch.object( release_status, 'delete', return_value=response.Response()) mocker.patch.object( release_subgenre, 'delete_release_subgenre', return_value=response.Response()) mocker.patch.object( mkt_priority, 'bulk_delete_mkt_priority_by_release_id', return_value=response.Response()) mocker.patch.object( release_logging, 'delete', return_value=response.Response()) mocker.patch.object( release_manual_adjustment, 'delete', return_value=response.Response()) mocker.patch.object( release_subtitles, 'delete', return_value=response.Response()) mocker.patch.object( release_grid, 'delete', return_value=response.Response()) mocker.patch.object( release_approval_queue, 'delete', return_value=response.Response()) mocker.patch.object( track, 'delete_all_tracks', return_value=response.create_error_response( status=400, code='error', message='some error' ) ) mocker.patch.object( release, 'delete', return_value=response.Response()) with mysql.db_session() as session: delete_response = audio_product.delete(product_id, session) assert delete_response.status == 400 @db.test_schema def test_get_products( release_payload, product_id, mocker, cr_ff_disabled, test_request_context, mock_ows_project_get_project): """Test fetching products based on product id that has product artists.""" release_response = response.Response(message=release_payload) mocker.patch.object(release, 'get_release', return_value=release_response) artists_response_message = [{ 'artist_info_id': None, 'role': 'performer', 'artist_name': 'David Banner', 'release_artist_id': 1}] expected_artists = [{ 'artist_info_id': None, 'role': 'primary_artist', 'name': 'David Banner', 'id': 1}] artists_response = response.Response(message=artists_response_message) mocker.patch.object( release_artist, 'get_release_artists_by_release_id', return_value=artists_response) mocker.patch.object( release_subgenre, 'get_release_subgenre_by_release_id', return_value=None) mock_response = MagicMock(status_code=404) mocker.patch.object( ows_product_workflow, 'get_last_release_approval_queue', return_value=mock_response) product_response = audio_product.get_products([product_id]) assert product_response.status == 200 assert product_response.message[0]['product_artists'] == expected_artists