"""Job logic tests.""" from typing import Any from unittest.mock import MagicMock import pytest from pytest_mock import MockerFixture from requests.exceptions import HTTPError from werkzeug.exceptions import BadRequest from video.constants import ( product as product_constants, release as release_constants, ) from video.exceptions import ( ProductOwnershipError, ProductVideoNotFound, ProjectOwnershipError, SubmissionNotAllowed, ) from video.logic import ( approval as approval_logic, auto_approval as auto_approval_logic, metadata, product as product_logic, ) from video.models.ows import ( artist as ows_artist, product as ows_product, project as ows_project, track as ows_track, ) from video.models.sql.classes import approval, product_video, release from video.utils import status_checker from tests.unit.ar_db_utils import mock_db_session def test_create_product(mocker: MockerFixture) -> None: """Test create product.""" mock_release_create: MagicMock = mocker.patch.object( release, "create", return_value={"release_id": 100}, ) mocker.patch.object( ows_project, "check_project_ownership", return_value=True, ) mocker.patch.object( ows_project, "get_project_by_id", return_value={"artist_id": 12}, ) mocker.patch.object( ows_product, "generate_placeholder_upc", return_value="123456789012", ) mock_save_metadata: MagicMock = mocker.patch.object( metadata, "save_metadata", return_value={"release_id": 100}, ) create_product_response = product_logic.create_product( {"subaccount_id": 2000, "project_id": 1}, "vendor", 2 ) mock_save_metadata.assert_called_once_with( 100, {"primary_artist_id": 12, "video_title": ""} ) mock_release_create.assert_called_once_with( { "upc": "123456789012", "subaccount_id": None, "vendor_catalog_number": None, "release_status": "label_processing", "artist_id": 12, "project_id": 1, "distribution_format_id": ( product_constants.MUSIC_VIDEO_DISTRIBUTION_FORMAT_ID ), "product_type_id": (product_constants.MUSIC_PRODUCT_TYPE_ID), "release_name": "", } ) assert create_product_response == {"release_id": 100} def test_create_product_no_ownership(mocker: MockerFixture) -> None: """Test create product.""" mocker.patch.object( ows_project, "check_project_ownership", side_effect=ProjectOwnershipError(), ) with pytest.raises(ProjectOwnershipError): product_logic.create_product( {"subaccount_id": 2000, "project_id": 1}, "vendor", 2 ) def test_create_product_bad_id(mocker: MockerFixture) -> None: """Test create product.""" mocker.patch.object( ows_project, "check_project_ownership", return_value=True, ) mocker.patch.object( ows_project, "get_project_by_id", side_effect=HTTPError("error"), ) with pytest.raises(HTTPError): product_logic.create_product( {"subaccount_id": 2000, "project_id": 1}, "vendor", 2 ) def test_create_product_bad_upc(mocker: MockerFixture) -> None: """Test create product.""" mocker.patch.object( ows_project, "check_project_ownership", return_value=True, ) mocker.patch.object( ows_project, "get_project_by_id", return_value={"artist_id": 12}, ) mocker.patch.object( ows_product, "generate_placeholder_upc", side_effect=HTTPError("error"), ) with pytest.raises(HTTPError): product_logic.create_product( {"subaccount_id": 2000, "project_id": 1}, "vendor", 2 ) def test_delete(mocker: MockerFixture) -> None: """Test delete product.""" session = mock_db_session(mocker) mocker.patch.object( ows_product, "check_product_ownership", return_value=True, ) mocker.patch.object( status_checker, "check_release_status_before_action", return_value=None, ) mock_delete_pv: MagicMock = mocker.patch.object( product_video, "delete_product", return_value=None ) mock_delete_release: MagicMock = mocker.patch.object( release, "delete_release", return_value=None ) mock_delete_approval: MagicMock = mocker.patch.object( approval, "delete_approval", return_value=None ) delete_response = product_logic.delete(1, "vendor", 2) mock_delete_release.assert_called_once_with(1, session=session) mock_delete_pv.assert_called_once_with(1, session=session) mock_delete_approval.assert_called_once_with(1, session=session) assert delete_response is not None def test_delete_invalid_status(mocker: MockerFixture) -> None: """Test delete product with an invalid status.""" mocker.patch.object( ows_product, "check_product_ownership", return_value=True, ) mocker.patch.object( status_checker, "check_release_status_before_action", side_effect=BadRequest("message"), ) with pytest.raises(BadRequest): product_logic.delete(1, "vendor", 2) @pytest.mark.parametrize( ("isrc", "upc", "get_isrc_calls", "get_upc_calls"), [(None, None, 1, 1), ("", "", 1, 1), (0, 0, 1, 1), ("999009", "1360", 0, 0)], ) def test_submit( mocker: MockerFixture, isrc: Any, upc: Any, get_isrc_calls: Any, get_upc_calls: Any ) -> None: """Test submit product.""" mocker.patch.object( ows_product, "check_product_ownership", return_value=True, ) mocker.patch.object( product_video, "get", return_value={ "is_valid": True, "upc": upc, "isrc": isrc, "submitted_at": None, "type_of_video": "Official Music Video", "special_instructions": "", "channel_selection": "Test Channel", }, ) mocker.patch.object( status_checker, "check_release_status_before_action", return_value=None, ) mocker.patch.object(product_video, "upsert", return_value=None) mock_get_upc: MagicMock = mocker.patch.object(release, "get_upc", return_value=12) mock_get_isrc: MagicMock = mocker.patch.object(release, "get_isrc", return_value=15) mock_save_metadata: MagicMock = mocker.patch.object( metadata, "save_metadata", return_value={ "is_valid": True, "upc": 12, "isrc": 15, "submitted_at": None, "type_of_video": "Official Music Video", "special_instructions": "", "channel_selection": "Test Channel", }, ) release_update_mock = mocker.patch.object( release, "update", return_value={"release_status": release_constants.TRANSFER_TO_CONTENT}, ) mocker.patch.object(release, "get_by_id_with_vendor", return_value={}) mocker.patch.object(release, "get", return_value={"upc": 13334}) mock_approval_change: MagicMock = mocker.patch.object( approval_logic, "change", ) mocker.patch.object( auto_approval_logic, "should_auto_apply_label_mgr_approval", return_value=False ) mocker.patch.object(auto_approval_logic, "auto_apply_video_type_carveouts") mocker.patch.object( auto_approval_logic, "should_auto_apply_vidops_approval", return_value=False ) mocker.patch.object( auto_approval_logic, "should_final_approval_be_applied", return_value=False ) mocker.patch.object( ows_track, "is_isrc_used", return_value={"used": False, "used_by_product_id": None}, ) submit_product_response = product_logic.submit(1, "vendor", 2) assert mock_get_upc.call_count == get_upc_calls assert mock_get_isrc.call_count == get_isrc_calls assert mock_approval_change.call_count == 0 if get_upc_calls > 0 or get_isrc_calls > 0: mock_save_metadata.assert_called_once_with(1, {"isrc": 15, "upc": 12}) release_update_mock.assert_called_once_with( 1, {"release_status": release_constants.TRANSFER_TO_CONTENT} ) assert submit_product_response == { "release_status": release_constants.TRANSFER_TO_CONTENT } def test_submit_product_no_ownership(mocker: MockerFixture) -> None: """Test submit product.""" mocker.patch.object( ows_product, "check_product_ownership", side_effect=ProductOwnershipError(), ) with pytest.raises(ProductOwnershipError): product_logic.submit(1, "vendor", 2) def test_submit_product_invalid_status(mocker: MockerFixture) -> None: """Test submit product with an invalid status.""" mocker.patch.object( ows_product, "check_product_ownership", return_value=True, ) mocker.patch.object( status_checker, "check_release_status_before_action", side_effect=BadRequest("message"), ) with pytest.raises(BadRequest): product_logic.submit(1, "vendor", 2) def test_submit_no_product_video(mocker: MockerFixture) -> None: """Test submit product.""" mocker.patch.object( ows_product, "check_product_ownership", return_value=True, ) mocker.patch.object( status_checker, "check_release_status_before_action", return_value=None, ) mocker.patch.object( product_video, "get", return_value=None, ) with pytest.raises(ProductVideoNotFound): product_logic.submit(1, "vendor", 2) def test_submit_not_valid(mocker: MockerFixture) -> None: """Test submit product.""" mocker.patch.object( ows_product, "check_product_ownership", return_value=True, ) mocker.patch.object( status_checker, "check_release_status_before_action", return_value=None, ) mocker.patch.object( product_video, "get", return_value={"is_valid": False}, ) with pytest.raises(SubmissionNotAllowed): product_logic.submit(1, "vendor", 2) def test_migrate_artist(mocker: MockerFixture) -> None: """Test migrate artist.""" mocker.patch.object( ows_product, "check_product_ownership", return_value=True, ) mocker.patch.object( ows_artist, "check_artist_ownership", return_value=True, ) mock_update_artist: MagicMock = mocker.patch.object( product_video, "update_primary_artist", return_value={ "release_id": 1234, "upc": 1234567, "isrc": "HYST98765", "submitted_at": None, "primary_artist_id": 12, }, ) migrate_artist_response = product_logic.migrate_artist(12, 1234, "vendor", 25824) assert migrate_artist_response == { "release_id": 1234, "upc": 1234567, "isrc": "HYST98765", "submitted_at": None, "primary_artist_id": 12, } mock_update_artist.assert_called_once() def test_migrate_artist_no_ownership(mocker: MockerFixture) -> None: """Test migrate artist having no ownership of product.""" mocker.patch.object( ows_product, "check_product_ownership", side_effect=ProductOwnershipError(), ) with pytest.raises(ProductOwnershipError): product_logic.migrate_artist(12, 1234, "vendor", 25824)