from unittest.mock import AsyncMock, Mock, create_autospec import pytest from src.backend.logic.audit.flags import youtube_checks as yt_checks from tests_backend.conftest import TEST_YT_ASSET_ID class TestMatchPolicyRule: _class = yt_checks.MatchPolicyRule @pytest.mark.parametrize( "params,expected", [ ({"action": yt_checks.YtCid.MONETIZE}, True), ({"action": "not monetize"}, False), ( { "action": yt_checks.YtCid.MONETIZE, "content_types": [yt_checks.YtCid.AUDIOVISUAL], }, True, ), ( {"action": yt_checks.YtCid.MONETIZE, "content_types": ["whatever"]}, False, ), ( { "action": yt_checks.YtCid.MONETIZE, "content_types": [yt_checks.YtCid.AUDIOVISUAL], "territories": [yt_checks.Countries.RU], "type": yt_checks.YtCid.INCLUDE, }, False, ), ( { "action": yt_checks.YtCid.MONETIZE, "content_types": [yt_checks.YtCid.AUDIOVISUAL], "territories": [yt_checks.Countries.RU], "type": yt_checks.YtCid.EXCLUDE, }, True, ), ], ) def test_is_valid(self, params, expected): instance = self._class(asset_id=TEST_YT_ASSET_ID, **params) assert instance.is_valid() is expected class TestYTChecks: _class = yt_checks.YTChecks @pytest.fixture(autouse=True) def mocker_yt_cid_client(self, mocker): mocker.patch.object( yt_checks, "YtCidClient", autospec=True, return_value=Mock( assets_list=AsyncMock(), references_list=AsyncMock(), ), ) @pytest.fixture def instance(self): return self._class() @pytest.fixture def mock_asset(self): mock_asset = Mock() mock_asset.configure_mock(id=TEST_YT_ASSET_ID, alias_id=[]) return mock_asset @pytest.mark.asyncio async def test_get_assets_uses_cache(self, instance, mock_asset): instance._yt_cid_client.assets_list.return_value = [mock_asset] for _ in range(3): result = await instance._get_assets([TEST_YT_ASSET_ID]) assert result assert result[0] is mock_asset assert instance._asset_cache == {TEST_YT_ASSET_ID: mock_asset} assert ( instance._yt_cid_client.assets_list.call_count == 1 ), "Should have used cache." @pytest.mark.asyncio async def test_get_assets_does_not_return_nones_for_not_found_assets( self, instance, mock_asset ): instance._yt_cid_client.assets_list.return_value = [] result = await instance._get_assets(["asset which won't be found"]) assert result == [] @pytest.mark.asyncio async def test_get_assets_handles_merged_assets_with_more_than_one_id( self, instance, mock_asset ): """Check fetching assets with Asset ID and any of its Alias IDs.""" alias_ids = ["alias1", "alias2"] check_ids = [mock_asset.id, *alias_ids] mock_asset.alias_id = alias_ids for asset_id in check_ids: instance._yt_cid_client.assets_list.return_value = [mock_asset] result = await instance._get_assets([asset_id]) assert result == [mock_asset] class TestGetAssetReferences(TestYTChecks): @pytest.mark.asyncio async def test_get_asset_references_cache(self, instance): assert not instance._reference_cache client = instance._yt_cid_client client.references_list.return_value = [ create_autospec(yt_checks.models.Reference, asset_id=TEST_YT_ASSET_ID) ] for _ in range(3): # Call > 1 time to make sure cache is used await instance.get_asset_references([TEST_YT_ASSET_ID]) assert instance._reference_cache[ TEST_YT_ASSET_ID ], "Expected references for asset" assert client.references_list.call_count == 1, "Should have used cache." @pytest.mark.asyncio async def test_get_asset_if_no_asset_ids_to_fetch_then_no_fetch(self, instance): instance._reference_cache = {TEST_YT_ASSET_ID: []} # Asset already in cache await instance.get_asset_references([TEST_YT_ASSET_ID]) client = instance._yt_cid_client assert client.references_list.call_count == 0, "Should not have fetched" @pytest.mark.asyncio async def test_get_asset_no_asset_ids_provided(self, instance): result = await instance.get_asset_references([]) client = instance._yt_cid_client assert client.references_list.call_count == 0, "Should not have fetched" assert result == {}, "Expected empty result"