from unittest import mock import pytest from anydi import Container from dirty_equals import IsApprox from fansifter_common.auth.account import Account from starlette.testclient import TestClient from dmp.adapters.ows_socials import ArtistSocialsStats from dmp.fandata.models import FansByArtistAccountDbt, FansByCustomListAccountDbt from dmp.rosters.models import ArtistRosterLocalRep, CustomList from dmp.rosters.services import GlobalFanDataAccessService from tests.unit.types import BuildModel, CreateReportingModel @pytest.mark.db def test_get_rosters( client: TestClient, create_reporting_model: CreateReportingModel, build_model: BuildModel, ows_socials_client_mock: mock.MagicMock, account: Account, ) -> None: socials_stats = build_model(ArtistSocialsStats) fandata_list_item = create_reporting_model( FansByArtistAccountDbt, chartmetric_id=socials_stats.chartmetric_artist_id, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) ows_socials_client_mock.get_stats_by_artists_ids.return_value = [socials_stats] response = client.get("/rosters") assert response.status_code == 200 assert response.json() == { "total": 1, "items": [ { "globalParticipantId": fandata_list_item.global_participant_id, "customListId": None, "name": fandata_list_item.global_participant_name, "vendorId": fandata_list_item.vendor_id, "subaccountId": fandata_list_item.subaccount_id, "fansCount": fandata_list_item.fans_count, "fansCount7DaysChange": fandata_list_item.fans_count_7_days_change, "fansCount28DaysChange": fandata_list_item.fans_count_28_days_change, "fansCount6MonthChange": fandata_list_item.fans_count_6_month_change, "fansCount1YearChange": fandata_list_item.fans_count_1_year_change, "fansCount7DaysPercentChange": IsApprox( fandata_list_item.fans_count_7_days_percent_change ), "fansCount28DaysPercentChange": IsApprox( fandata_list_item.fans_count_28_days_percent_change ), "fansCount6MonthPercentChange": IsApprox( fandata_list_item.fans_count_6_month_percent_change ), "fansCount1YearPercentChange": IsApprox( fandata_list_item.fans_count_1_year_percent_change ), "fanDataOwner": True, "spotifyMonthlyListeners": socials_stats.spotify_monthly_listeners, "instagramFollowers": socials_stats.instagram_followers, "tiktokFollowers": socials_stats.tiktok_followers, "spotifyFollowers": socials_stats.spotify_followers, "facebookFollowers": socials_stats.facebook_followers, "youtubeFollowers": socials_stats.youtube_followers, "twitterFollowers": socials_stats.twitter_followers, "soundcloudFollowers": socials_stats.soundcloud_followers, "deezerFollowers": socials_stats.deezer_followers, "engagementBenchmark": fandata_list_item.engagement_benchmark, "engagementRatio": fandata_list_item.engagement_ratio, "adConsentFansCount": fandata_list_item.ad_consent_fans_count, "emailConsentFansCount": fandata_list_item.email_consent_fans_count, "smsConsentFansCount": fandata_list_item.sms_consent_fans_count, } ], "limit": 50, "offset": 0, } @pytest.mark.db def test_get_rosters_default_ordering( client: TestClient, create_reporting_model: CreateReportingModel, ows_socials_client_mock: mock.MagicMock, account: Account, ) -> None: item_1 = create_reporting_model( FansByArtistAccountDbt, fans_count=2, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) item_2 = create_reporting_model( FansByArtistAccountDbt, fans_count=3, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) item_3 = create_reporting_model( FansByArtistAccountDbt, fans_count=1, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) ows_socials_client_mock.get_stats_by_artists_ids.return_value = [] response = client.get("/rosters") assert response.status_code == 200 data = response.json() assert data["total"] == 3 # Default ordering is fans_count desc assert data["items"][0]["globalParticipantId"] == item_2.global_participant_id assert data["items"][1]["globalParticipantId"] == item_1.global_participant_id assert data["items"][2]["globalParticipantId"] == item_3.global_participant_id @pytest.mark.db @pytest.mark.parametrize( "not_allowed_field_for_ordering", [ ("vendorId.asc",), ("vendorId.desc",), ("subaccountId.asc",), ("subaccountId.desc",), ("globalParticipantId.asc",), ("globalParticipantId.desc",), ], ) def test_get_rosters_not_allowed_field_for_ordering( client: TestClient, not_allowed_field_for_ordering: str, ) -> None: response = client.get( "/rosters", params={"orderBy": [not_allowed_field_for_ordering]} ) assert response.status_code == 422 @pytest.mark.db def test_get_rosters_offset( client: TestClient, create_reporting_model: CreateReportingModel, ows_socials_client_mock: mock.MagicMock, account: Account, ) -> None: item_1 = create_reporting_model( FansByArtistAccountDbt, fans_count=2, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) create_reporting_model( FansByArtistAccountDbt, fans_count=3, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) item_3 = create_reporting_model( FansByArtistAccountDbt, fans_count=1, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) ows_socials_client_mock.get_stats_by_artists_ids.return_value = [] response = client.get("/rosters", params={"orderBy": "fansCount.desc", "offset": 1}) assert response.status_code == 200 data = response.json() assert data["total"] == 3 assert data["offset"] == 1 # offset=1 skips item with fans_count=3, returns item_1 then item_3 assert data["items"][0]["globalParticipantId"] == item_1.global_participant_id assert data["items"][1]["globalParticipantId"] == item_3.global_participant_id @pytest.mark.db def test_get_rosters_search( client: TestClient, create_reporting_model: CreateReportingModel, account: Account, ) -> None: artist = create_reporting_model( FansByArtistAccountDbt, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) custom_list = create_reporting_model( FansByCustomListAccountDbt, vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) response = client.get( "/rosters/search", params={ "vendorId": account.vendor_id, "subaccountId": account.subaccount_id, }, ) assert response.status_code == 200 assert response.json() == { "artists": [ { "id": artist.global_participant_id, "name": artist.global_participant_name, "isMainRep": None, } ], "customLists": [ { "id": custom_list.custom_list_id, "name": custom_list.custom_list_name, "isMainRep": None, } ], } @pytest.mark.db def test_get_custom_lists( client: TestClient, create_reporting_model: CreateReportingModel, account: Account, ) -> None: custom_list_1 = create_reporting_model( CustomList, name="List 1", vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) custom_list_2 = create_reporting_model( CustomList, name="List 2", vendor_id=account.vendor_id, subaccount_id=account.subaccount_id, ) response = client.get( "/rosters/custom-lists", params={ "customListIds": [ custom_list_1.id, custom_list_2.id, ] }, ) assert response.status_code == 200 assert response.json() == [ { "id": custom_list_1.id, "name": custom_list_1.name, "isMainRep": None, }, { "id": custom_list_2.id, "name": custom_list_2.name, "isMainRep": None, }, ] @pytest.mark.db def test_get_local_rep_countries( container: Container, client: TestClient, create_reporting_model: CreateReportingModel, ) -> None: global_fandata_access_service_mock = mock.MagicMock( spec=GlobalFanDataAccessService, is_enabled_for_vendor=mock.MagicMock(return_value=True), ) local_rep = create_reporting_model(ArtistRosterLocalRep, country_code="US") with container.override( GlobalFanDataAccessService, global_fandata_access_service_mock, ): response = client.get( "/rosters/local-rep-countries", params={ "vendorId": local_rep.vendor_id, "subaccountId": local_rep.subaccount_id, "globalParticipantIds": [local_rep.global_participant_id], }, ) assert response.status_code == 200 assert response.json() == ["US"]