"""ows-product model tests.""" from typing import Any from unittest.mock import MagicMock import pytest from pytest_mock import MockerFixture from werkzeug.exceptions import BadRequest from video.exceptions import ReleaseNotFound, VideoAssetNotFound from video.logic import ( asset as asset_logic, track as track_logic, video_asset as video_asset_logic, video_product_copy as video_product_copy_logic, ) from video.models.ows import track as ows_track from video.models.sql import queries from video.models.sql.classes import release, track as ows_tracks, track_video from tests.unit.jsonschema import test_jsonschema_tracks, test_jsonschema_video_asset @pytest.fixture def volume_data() -> list[list[str]]: """Mock Dummy volume data.""" return [["4763145", "4763147"], ["4763146", "4763148"]] def test_create_bundle_with_video_only_bundle_type( mocker: MockerFixture, volume_data: Any ) -> None: """Test with video_only bundle type.""" audio_product_id = 123 selected_thumbnail_id = "4763147" bundle_type = "VIDEO" get_tracks_by_product_id_mock = mocker.patch.object( ows_tracks, "get_tracks_by_product_id", return_value=test_jsonschema_tracks.get_tracks_json()["items"], autospec=True, ) copy_track_metadata_mock = mocker.patch.object( video_product_copy_logic, "copy_track_metadata", return_value=None ) copy_video_asset_details_mock = mocker.patch.object( video_product_copy_logic, "copy_video_asset_details", return_value=None ) with pytest.raises(BadRequest): video_product_copy_logic.create_bundle( audio_product_id, bundle_type, selected_thumbnail_id, volume_data ) get_tracks_by_product_id_mock.assert_called_once_with(audio_product_id) copy_track_metadata_mock.assert_not_called() copy_video_asset_details_mock.assert_not_called() def test_copy_track_metadata_success(mocker: MockerFixture, volume_data: Any) -> None: """Test copy track metadata success.""" audio_product_id = 123 selected_thumbnail_id = "4763147" get_track_mock = mocker.patch.object( ows_track, "get_track", return_value=test_jsonschema_tracks.get_tracks_json(), autospec=True, ) mocker.patch.object( ows_tracks, "get_tracks_by_product_id", return_value=test_jsonschema_tracks.get_tracks_json()["items"], autospec=True, ) track_video_metadata = [ { "track_id": 37299468, "duration_minutes": 3, "duration_seconds": 9, "closed_caption_exists": 0, "closed_caption_reason_id": 1, "color": "color", "channel": "2", "fps": "24", "resolution": "1080HD", "aspect_ratio": "16:9", } ] get_track_metadata_mock = mocker.patch.object( track_logic, "get_tracks_metadata", return_value=track_video_metadata, autospec=True, ) inserted_track_data = { "product_id": 3888989, "track_name": "Unwavering Vow", "meta_language_code": None, "isrc": "USSTT1590558", "p_info": "2022 Pure Noise Records", "explicit": "N", "volume_number": 1, "track_number": 3, "upc": 196925147910, "preview_start_time": 10000, "track_type": "video", "offer_type": "all", "stereo_or_mono": "stereo", "track_id": 37299468, } add_track_metadata_mock = mocker.patch.object( video_product_copy_logic, "add_track_metadata", return_value=inserted_track_data, autospec=True, ) mocker.patch.object(track_video, "upsert", return_value=True, autospec=True) get_upc_by_product_id_mock = mocker.patch.object( release, "get_upc_by_product_id", return_value={"upc": 196925147910}, autospec=True, ) upsert_mock = mocker.patch.object( track_video, "upsert", return_value=None, ) result = video_product_copy_logic.copy_track_metadata( audio_product_id, selected_thumbnail_id, volume_data ) assert get_upc_by_product_id_mock.call_count == 1 assert result == { 4763145: {"track_id": 37299468, "video_thumbnail_product": False}, 4763147: {"track_id": 37299468, "video_thumbnail_product": True}, 4763146: {"track_id": 37299468, "video_thumbnail_product": False}, 4763148: {"track_id": 37299468, "video_thumbnail_product": False}, } assert add_track_metadata_mock.call_count == 4 assert get_track_metadata_mock.call_count == 4 assert upsert_mock.call_count == 4 assert get_track_mock.call_count == 4 def test_copy_track_metadata_failure(mocker: MockerFixture) -> None: """Test copy track metadata failure when volume_data is empty.""" audio_product_id = 123 selected_thumbnail_id = "4763147" get_upc_by_product_id_mock = mocker.patch.object( release, "get_upc_by_product_id", return_value={"upc": 196925147910}, autospec=True, ) with pytest.raises(BadRequest): video_product_copy_logic.copy_track_metadata( audio_product_id, selected_thumbnail_id, [] ) get_upc_by_product_id_mock.assert_called_once_with(audio_product_id) def test_add_track_metadata_success(mocker: MockerFixture) -> None: """Test add track metadata success.""" inserted_track_data = { "product_id": 3888989, "track_name": "Unwavering Vow", "meta_language_code": None, "isrc": "USSTT1590558", "p_info": "2022 Pure Noise Records", "explicit": "N", "volume_number": 1, "track_number": 3, "upc": 196925147910, "preview_start_time": 10000, "track_type": "video", "offer_type": "all", "stereo_or_mono": "stereo", "track_id": 37299468, } mocker.patch.object( video_product_copy_logic, "add_track_metadata", return_value=inserted_track_data, autospec=True, ) create_track_response = video_product_copy_logic.add_track_metadata( inserted_track_data ) assert create_track_response == inserted_track_data assert create_track_response["track_id"] == 37299468 def test_add_track_metadata_failure(mocker: MockerFixture) -> None: """Test add track metadata failure when upsert raises.""" inserted_track_data = { "product_id": 3888989, "track_name": "Unwavering Vow", "meta_language_code": None, "isrc": "USSTT1590558", "p_info": "2022 Pure Noise Records", "explicit": "N", "volume_number": 1, "track_number": 3, "upc": 196925147910, "preview_start_time": 10000, "track_type": "video", "offer_type": "all", "stereo_or_mono": "stereo", "track_id": 37299468, } mocker.patch.object( ows_tracks, "upsert", side_effect=BadRequest("Something went wrong"), autospec=True, ) with pytest.raises(BadRequest): video_product_copy_logic.add_track_metadata(inserted_track_data) def test_extract_track_video_data() -> None: """Test extract track video data.""" track_video_metadata = { "fps": 30, "resolution": "1920x1080", "aspect_ratio": "16:9", "color": "RGB", "channel": "Stereo", } # Expected output expected_output = { "fps": 30, "resolution": "1920x1080", "aspect_ratio": "16:9", "color": "RGB", "channel": "Stereo", } result = video_product_copy_logic.extract_track_video_data(track_video_metadata) assert result == expected_output def test_extract_track_data() -> None: """Test extract track data.""" track = { "isrc": "US1234567890", "track_name": "Sample Track", "duration_minutes": 3, "duration_seconds": 30, "explicit": False, "offer_type": "Premium", "p_info": "Sample P Info", "meta_language_code": "en", "preview_start_time": "00:00:30", "track_type": "Audio", "version": "Original", "closed_caption_exists": True, "closed_caption_reason_id": 1, } track_video_metadata = { "track_id": 37299468, "duration_minutes": 3, "duration_seconds": 9, "closed_caption_exists": True, "closed_caption_reason_id": 1, "color": "color", "channel": "2", "fps": "24", "resolution": "1080HD", "aspect_ratio": "16:9", } audio_product_id = 123456 audio_product_tracks_upc = "ABC123" track_number_counter = 1 volume = 1 # Expected output expected_output = { "isrc": "US1234567890", "track_name": "Sample Track", "duration_minutes": 3, "duration_seconds": 30, "explicit": False, "offer_type": "Premium", "p_info": "Sample P Info", "meta_language_code": "en", "closed_caption_exists": True, "closed_caption_reason_id": 1, "preview_start_time": "00:00:30", "track_type": "Audio", "upc": "ABC123", "product_id": 123456, "track_number": 1, "stereo_or_mono": "stereo", "volume_number": 1, } result = video_product_copy_logic.extract_track_data( track, track_video_metadata, audio_product_id, audio_product_tracks_upc, track_number_counter, volume, ) assert result == expected_output def test_format_video_assets_success() -> None: """Test format_video_assets success.""" video_assets = test_jsonschema_video_asset.get_video_assets_json() video_products = { 4736139: {"track_id": 40808003, "video_thumbnail_product": True}, 4736140: {"track_id": 40808003, "video_thumbnail_product": False}, } audio_product_id = 3888989 expected_output = [ { "product_id": 3888989, "asset_type": "video_master", "asset_path": "mezzanine/prores/162058/4736139.mov", "tuid": 40808003, "duration": 30.733, }, { "product_id": 3888989, "asset_type": "H264_HD", "asset_path": "mezzanine/h.264/162058/4736139.mp4", "tuid": 40808003, "duration": 30.733, }, { "product_id": 3888989, "asset_type": "H264_SD", "asset_path": "mezzanine/h.264/162058/4736139.mp4", "tuid": 40808003, "duration": 30.733, }, { "product_id": 3888989, "asset_type": "video_image_S2", "asset_path": "mezzanine/tiff/162058/4736139.0000014_s2.tif", "tuid": 0, "duration": 0.0, }, { "product_id": 3888989, "asset_type": "video_image_S5", "asset_path": "mezzanine/tiff/162058/4736139.0000014_s5.tif", "tuid": 0, "duration": 0.0, }, { "product_id": 3888989, "asset_type": "video_image_S10", "asset_path": "mezzanine/tiff/162058/4736139.0000014_s10.tif", "tuid": 0, "duration": 0.0, }, { "product_id": 3888989, "asset_type": "video_image_S11", "asset_path": "mezzanine/tiff/162058/4736139.0000014_s11.tif", "tuid": 0, "duration": 0.0, }, { "product_id": 3888989, "asset_type": "video_master", "asset_path": "mezzanine/prores/162067/4736140.mov", "tuid": 40808003, "duration": 30.733, }, { "product_id": 3888989, "asset_type": "H264_HD", "asset_path": "mezzanine/h.264/162067/4736140.mp4", "tuid": 40808003, "duration": 30.733, }, ] result = video_product_copy_logic.format_video_assets( video_assets, video_products, audio_product_id ) assert result == expected_output def test_copy_video_asset_details_success(mocker: MockerFixture) -> None: """Test copy video asset success.""" expected_result = [ { "product_id": 3888989, "asset_type": "video_master", "asset_path": "mezzanine/prores/162058/4736139.mov", "tuid": 40808003, "duration": 0.0, } ] video_product_track_mapping = { 123: {"track_id": 40808003, "video_thumbnail_product": True}, 234: {"track_id": 40808003, "video_thumbnail_product": False}, } audio_product_id = 3888989 assets = [ { "product_id": 123, "asset_type": "video_master", "asset_path": "video_master_s3_path", "s3_key": "mezzanine/prores/162058/4736139.mov", "tuid": 1, "duration": 0.0, }, { "product_id": 234, "asset_type": "video_image_S10", "asset_path": "video_image_s3_path", "s3_key": "mezzanine/prores/162058/4736139.mov", "tuid": 1, "duration": 0.0, }, ] get_product_assets_mock = mocker.patch.object( asset_logic, "get_product_assets", return_value=assets, ) bulk_upsert_video_assets_mock = mocker.patch.object( video_asset_logic, "bulk_upsert_video_assets", return_value=expected_result ) video_assets_records = video_product_copy_logic.copy_video_asset_details( video_product_track_mapping, audio_product_id ) get_product_assets_mock.assert_called_once_with([123, 234]) bulk_upsert_video_assets_mock.assert_called_once() assert video_assets_records == expected_result def test_copy_video_asset_details_failure(mocker: MockerFixture) -> None: """Test copy video asset failure.""" error_sentinel: Any = {"error": "TEST", "message": "TESTERROR"} expected_json = [ { "product_id": 3888989, "asset_type": "video_master", "asset_path": "mezzanine/prores/162058/4736139.mov", "tuid": 40808003, "duration": 0.0, } ] video_product_track_mapping = { 124: {"track_id": 40808003, "video_thumbnail_product": True}, 125: {"track_id": 40808003, "video_thumbnail_product": False}, } audio_product_id = 3888989 product_ids = [123, 234] assets = [ { "product_id": 123, "asset_type": "video_master", "asset_path": "video_master_s3_path", "s3_key": "mezzanine/prores/162058/4736139.mov", "tuid": 1, }, { "product_id": 234, "asset_type": "video_image_S10", "asset_path": "video_image_s3_path", "s3_key": "mezzanine/prores/162058/4736139.mov", "tuid": 1, }, ] get_product_assets_mock = mocker.patch.object( queries, "get_product_assets", return_value=assets ) result = asset_logic.get_product_assets(product_ids) format_video_assets_mock = mocker.patch.object( video_product_copy_logic, "format_video_assets", return_value=expected_json ) bulk_upsert_video_assets_mock = mocker.patch.object( video_asset_logic, "bulk_upsert_video_assets", return_value=error_sentinel ) video_asset_insert = video_product_copy_logic.format_video_assets( result, video_product_track_mapping, audio_product_id ) video_assets_records = video_asset_logic.bulk_upsert_video_assets( video_asset_insert ) get_product_assets_mock.assert_called_once_with(product_ids, asset_types=[]) format_video_assets_mock.assert_called_once_with( result, video_product_track_mapping, audio_product_id ) bulk_upsert_video_assets_mock.assert_called_once_with(video_asset_insert) assert video_assets_records is error_sentinel def test_copy_video_asset_details_product_assets_failure(mocker: MockerFixture) -> None: """Test copy video asset failure when get_product_assets raises VideoAssetNotFound.""" video_product_track_mapping = { 124: {"track_id": 40808003, "video_thumbnail_product": True}, } audio_product_id = 3888989 mocker.patch.object( asset_logic, "get_product_assets", side_effect=VideoAssetNotFound(), ) format_video_assets_mock = mocker.patch.object( video_product_copy_logic, "format_video_assets", return_value=None ) video_asset_logic_mock = mocker.patch.object( video_asset_logic, "bulk_upsert_video_assets", return_value=None ) with pytest.raises(VideoAssetNotFound): video_product_copy_logic.copy_video_asset_details( video_product_track_mapping, audio_product_id ) format_video_assets_mock.assert_not_called() video_asset_logic_mock.assert_not_called() def test_create_bundle_success(mocker: MockerFixture, volume_data: Any) -> None: """Test create bundle success.""" expected_result = 123 audio_product_id = 123 selected_thumbnail_id = "4763147" bundle_type = "AUDIO_VIDEO" video_product_track_mapping = { 124: {"track_id": 40808003, "video_thumbnail_product": True}, 125: {"track_id": 40808003, "video_thumbnail_product": False}, } get_tracks_by_product_id_mock = mocker.patch.object( ows_tracks, "get_tracks_by_product_id", return_value=test_jsonschema_tracks.get_tracks_json()["items"], autospec=True, ) copy_track_metadata_mock = mocker.patch.object( video_product_copy_logic, "copy_track_metadata", return_value=video_product_track_mapping, ) copy_video_asset_details_mock = mocker.patch.object( video_product_copy_logic, "copy_video_asset_details", return_value=[], ) validate_bundle_mock = mocker.patch.object( video_product_copy_logic, "validate_bundle", return_value=None, ) result = video_product_copy_logic.create_bundle( audio_product_id, bundle_type, selected_thumbnail_id, volume_data ) validate_bundle_mock.assert_called_once_with( audio_product_id, bundle_type, volume_data ) copy_track_metadata_mock.assert_called_once_with( audio_product_id, selected_thumbnail_id, volume_data ) copy_video_asset_details_mock.assert_called_once_with( video_product_track_mapping, audio_product_id ) get_tracks_by_product_id_mock.assert_not_called() assert result == expected_result def test_create_bundle_failure(mocker: MockerFixture, volume_data: Any) -> None: """Test create bundle failure when copy_track_metadata raises.""" audio_product_id = 123 selected_thumbnail_id = "4763147" bundle_type = "AUDIO_VIDEO" copy_track_metadata_mock = mocker.patch.object( video_product_copy_logic, "copy_track_metadata", side_effect=BadRequest("Failed to add track metadata"), ) copy_video_asset_details_mock = mocker.patch.object( video_product_copy_logic, "copy_video_asset_details", return_value=[], ) validate_bundle_mock = mocker.patch.object( video_product_copy_logic, "validate_bundle", return_value=None, ) with pytest.raises(BadRequest): video_product_copy_logic.create_bundle( audio_product_id, bundle_type, selected_thumbnail_id, volume_data ) validate_bundle_mock.assert_called_once_with( audio_product_id, bundle_type, volume_data ) copy_track_metadata_mock.assert_called_once_with( audio_product_id, selected_thumbnail_id, volume_data ) copy_video_asset_details_mock.assert_not_called() def test_validate_bundle_validation_failure( mocker: MockerFixture, volume_data: Any ) -> None: """Test validate bundle raises BadRequest for VIDEO bundle type with existing tracks.""" audio_product_id = 123 bundle_type = "VIDEO" mocker.patch.object( ows_tracks, "get_tracks_by_product_id", return_value=test_jsonschema_tracks.get_tracks_json()["items"], autospec=True, ) get_upc_by_product_id_mock = mocker.patch.object( release, "get_upc_by_product_id", return_value={"upc": 196925147910}, autospec=True, ) with pytest.raises(BadRequest): video_product_copy_logic.validate_bundle( audio_product_id, bundle_type, volume_data ) get_upc_by_product_id_mock.assert_not_called() def test_validate_bundle_release_not_found( mocker: MockerFixture, volume_data: Any ) -> None: """Test validate bundle raises BadRequest when release is not found.""" audio_product_id = 123 bundle_type = "AUDIO_VIDEO" mocker.patch.object( ows_tracks, "get_tracks_by_product_id", return_value=None, autospec=True, ) mocker.patch.object( release, "get_upc_by_product_id", side_effect=ReleaseNotFound(), autospec=True, ) with pytest.raises(BadRequest): video_product_copy_logic.validate_bundle( audio_product_id, bundle_type, volume_data ) def test_validate_bundle_video_assets(mocker: MockerFixture, volume_data: Any) -> None: """Test validate bundle raises NotFound when video assets are missing.""" audio_product_id = 123 bundle_type = "AUDIO_VIDEO" mocker.patch.object( ows_track, "get_track", return_value=test_jsonschema_tracks.get_tracks_json(), autospec=True, ) track_video_metatdata = [ { "track_id": 37299468, "duration_minutes": 3, "duration_seconds": 9, "closed_caption_exists": 0, "closed_caption_reason_id": 1, "color": "color", "channel": "2", "fps": "24", "resolution": "1080HD", "aspect_ratio": "16:9", } ] get_tracks_metadata_mock = mocker.patch.object( track_logic, "get_tracks_metadata", return_value=track_video_metatdata, autospec=True, ) release_get_upc_by_product_id_mock: MagicMock = mocker.patch.object( release, "get_upc_by_product_id", return_value={"upc": 196925147910}, autospec=True, ) mocker.patch.object( asset_logic, "get_product_assets", side_effect=VideoAssetNotFound() ) with pytest.raises(VideoAssetNotFound): video_product_copy_logic.validate_bundle( audio_product_id, bundle_type, volume_data ) release_get_upc_by_product_id_mock.assert_called_once_with(audio_product_id) assert get_tracks_metadata_mock.call_count == 4 def test_validate_bundle_success(mocker: MockerFixture, volume_data: Any) -> None: """Test validate bundle success.""" audio_product_id = 123 bundle_type = "AUDIO_VIDEO" mocker.patch.object( ows_tracks, "get_tracks_by_product_id", return_value=test_jsonschema_tracks.get_tracks_json()["items"], autospec=True, ) get_upc_by_product_id_mock = mocker.patch.object( release, "get_upc_by_product_id", return_value={"upc": 196925147910}, autospec=True, ) get_track_mock = mocker.patch.object( ows_track, "get_track", return_value=test_jsonschema_tracks.get_tracks_json(), autospec=True, ) track_video_metadata = [ { "track_id": 37299468, "duration_minutes": 3, "duration_seconds": 9, "closed_caption_exists": 0, "closed_caption_reason_id": 1, "color": "color", "channel": "2", "fps": "24", "resolution": "1080HD", "aspect_ratio": "16:9", } ] get_tracks_metadata_mock = mocker.patch.object( track_logic, "get_tracks_metadata", return_value=track_video_metadata, autospec=True, ) video_asset = [ { "product_id": 4763145, "asset_type": "video_master", }, { "product_id": 4763146, "asset_type": "H264_HD", }, { "product_id": 4763147, "asset_type": "H264_SD", }, { "product_id": 4763148, "asset_type": "video_image_S2", }, ] get_product_assets_mock = mocker.patch.object( asset_logic, "get_product_assets", return_value=video_asset, autospec=True, ) video_product_copy_logic.validate_bundle(audio_product_id, bundle_type, volume_data) get_upc_by_product_id_mock.assert_called_once_with(audio_product_id) assert get_track_mock.call_count == 4 assert get_tracks_metadata_mock.call_count == 4 assert get_product_assets_mock.call_count == 1