"""Tests for asset_status model.""" import json from datetime import datetime from typing import Any import pytest from flexmock import flexmock from sqlalchemy.exc import SQLAlchemyError from assets.connectors import mysql from assets.constants.error import ERROR_ASSET_STATUS_NOT_FOUND from assets.exceptions import AssetStatusNotFound from assets.models import asset_status from tests.unit.models import au_operations @pytest.fixture def asset_status_message() -> str: """Fixture for valid data for asset_status.""" return json.dumps( { "result_assets": [ { "key": "65a414c6_e1a7_4b42_9f48_2a32bada2c7a.flac", "bucket": "qa-orcd-mezzanine-assets", }, { "key": "287e54d7_7c06_4dea_ade3_b148d1a18641.wav", "bucket": "qa-orcd-mezzanine-assets", }, { "key": "3a569486_7c16_435b_846d_ad6770879ef1.mp3", "bucket": "qa-orcd-mezzanine-assets", }, ], "status": "completed", "input": { "key": "8aef199c_4843_49a1_9c96_349b71d752e2.wav", "bucket": "qa-orcd-raw-assets", }, } ) @pytest.fixture def valid_asset_status_data(asset_status_message: str) -> dict[str, Any]: """Fixture for valid data for create_asset_status.""" return { "asset_upload_id": 3, "status": "success", "description": None, "message": asset_status_message, "status_time": datetime(2017, 5, 5, 22, 23, 24, 333000), } @pytest.fixture def asset_status_data(asset_status_message: str) -> list[dict[str, Any]]: """Fixture for asset_status table.""" return [ { "asset_upload_id": 1, "status": "asset_1_status_1", "description": "Description", "message": "{}", "status_time": datetime(2000, 1, 1, 0, 0, 1), }, { "asset_upload_id": 1, "status": "asset_1_status_2", "description": "", "message": asset_status_message, "status_time": datetime(2001, 2, 2, 0, 0, 1), }, { # asset_2_status_2 inserted before asset_2_status_1 to ensure status_time is used for ordering "asset_upload_id": 2, "status": "asset_2_status_2", "description": "", "message": asset_status_message, "status_time": datetime(2016, 1, 1, 0, 0, 1, 1), }, { "asset_upload_id": 2, "status": "asset_2_status_1", "description": "Description", "message": "{}", "status_time": datetime(2016, 1, 1, 0, 0, 1, 0), }, { "asset_upload_id": 3, "status": "encoding_completed", "description": "", "message": asset_status_message, "status_time": datetime(2019, 1, 1, 0, 0, 1), }, ] @pytest.fixture def db_fixture( asset_status_data: list[dict[str, Any]], asset_upload_data: list[dict[str, Any]] ) -> None: """Set up the asset_status table.""" au_operations.truncate_tables() au_operations.seed_asset_upload_table(asset_upload_data) au_operations.seed_asset_status_table(asset_status_data) def test_create_asset_status( db_fixture: None, valid_asset_status_data: dict[str, Any] ) -> None: """Test creating a new asset status.""" asset_status.create_asset_status(**valid_asset_status_data) # no exception should be raised def test_test_create_asset_status_error( db_fixture: None, valid_asset_status_data: dict[str, Any] ) -> None: """Test creating a new asset status with sql error.""" error_message = "Query error" ( flexmock(mysql) .should_receive("au_db_session") .and_raise(SQLAlchemyError(error_message)) ) with pytest.raises(SQLAlchemyError) as exc: asset_status.create_asset_status(**valid_asset_status_data) assert str(exc.value) == error_message def test_get_last_asset_status(db_fixture: None) -> None: """Test getting last asset status.""" response = asset_status.get_last_asset_status(2) assert response["id"] == 3 assert response["status"] == "asset_2_status_2" def test_get_last_asset_status_encoding_completed( db_fixture: None, asset_status_message: str ) -> None: """Test getting last asset status.""" response = asset_status.get_last_asset_status(3) assert response["id"] == 5 assert response["status"] == "encoding_completed" def test_get_last_asset_status_not_found(db_fixture: None) -> None: """Test getting last asset status for non-existent asset.""" with pytest.raises(AssetStatusNotFound) as exc: asset_status.get_last_asset_status(4) assert exc.value.description == ERROR_ASSET_STATUS_NOT_FOUND def test_get_last_asset_status_error() -> None: """Test getting last asset status with SQLAlchemyError failure.""" error_message = "Query error" ( flexmock(mysql) .should_receive("au_db_session") .and_raise(SQLAlchemyError(error_message)) ) with pytest.raises(SQLAlchemyError) as exc: asset_status.get_last_asset_status(1) assert str(exc.value) == error_message def test_asset_status_without_message(db_fixture: None) -> None: """Test asset status without message.""" asset_status_item = asset_status.AssetStatus( asset_upload_id=4, status="status", status_time=datetime(2017, 5, 5, 22, 23, 24, 333000), ) assert asset_status_item.as_dict()["message"] is None def test_asset_status_with_message(db_fixture: None, asset_status_message: str) -> None: """Test asset status with message.""" asset_status_item = asset_status.AssetStatus( asset_upload_id=4, status="status", message=asset_status_message, status_time=datetime(2017, 5, 5, 22, 23, 24, 333000), ) assert asset_status_item.as_dict()["message"] == json.loads(asset_status_message) def test_get_asset_statuses_by_asset_upload_ids( asset_status_data: list[dict[str, Any]], ) -> None: """Test getting statuses by asset_upload_ids.""" message = asset_status.get_asset_statuses_by_asset_upload_ids([1, 2]) assert len(message.keys()) == 2 assert message[1]["status"] == asset_status_data[1]["status"] assert message[2]["status"] == asset_status_data[2]["status"] def test_get_asset_statuses_by_asset_upload_ids_missing_status() -> None: """Test getting statuses by asset_upload_ids missing status.""" response = asset_status.get_asset_statuses_by_asset_upload_ids([4]) assert response[4] == {} def test_get_asset_statuses_by_asset_upload_ids_error() -> None: """Test getting statuses by asset_upload_ids SQLAlchemy error.""" error_message = "Query error" ( flexmock(mysql) .should_receive("au_db_session") .and_raise(SQLAlchemyError(error_message)) ) with pytest.raises(SQLAlchemyError) as exc: asset_status.get_asset_statuses_by_asset_upload_ids([3]) assert str(exc.value) == error_message