from unittest.mock import patch from analytics.logic.tadas import ( calculate_trending_flags, get_tadas_data_availability, get_tadas_trend_globalsoundrecording_by_isrc, get_tadas_trends, get_trending_flags_for_row, ) EXPECTED_RESULT_TADAS_DATA_AVAILABILITY = [ { "by_country_tadas_last_available_date": "2023-10-15", "global_tadas_last_available_date": "2023-10-20", } ] EXPECTED_RESULT_TADAS_TRENDS = [ { "id": "1", "isrc": "US123123", "country_code": "US", "tadas_last_available_date": "2023-10-01", "tadas_days_trending": 10, "tadas_30days_score": 85.5, "tadas_trending_start_date": "2023-09-21", "spotify_streams_1_day": 5000, "apple_music_streams_1_day": 3000, "total_count": 2, "spotify_collection_flag": 1, "spotify_collection_lift": 0.15, "spotify_lean_forward_flag": 0, "spotify_lean_forward_lift": -0.21, "spotify_search_flag": 1, "spotify_search_lift": 0.33, "spotify_all_flag": 1, "spotify_all_lift": 0.25, "apple_lean_forward_flag": 0, "apple_lean_forward_lift": -0.11, "apple_search_flag": 1, "apple_search_lift": 0.45, "apple_all_flag": 1, "apple_all_lift": 0.32, "tiktok_creations_country_flag": 0, "tiktok_creations_country_lift": -0.1, "tiktok_creations_global_flag": 1, "tiktok_creations_global_lift": 0.2, "tiktok_views_country_flag": 1, "tiktok_views_country_lift": 0.3, "tiktok_views_global_flag": 0, "tiktok_views_global_lift": -0.4, "tiktok_likes_country_flag": 1, "tiktok_likes_country_lift": 0.5, "tiktok_likes_global_flag": 1, "tiktok_likes_global_lift": 0.6, }, { "id": "2", "isrc": "US54225678", "country_code": "US", "tadas_last_available_date": "2023-10-02", "tadas_days_trending": 15, "tadas_30days_score": 90.0, "tadas_trending_start_date": "2023-09-17", "spotify_streams_1_day": 6000, "apple_music_streams_1_day": 3500, "total_count": 2, "spotify_collection_flag": 0, "spotify_collection_lift": -0.15, "spotify_lean_forward_flag": 1, "spotify_lean_forward_lift": 0.21, "spotify_search_flag": 0, "spotify_search_lift": -0.33, "spotify_all_flag": 1, "spotify_all_lift": 0.12, "apple_lean_forward_flag": 1, "apple_lean_forward_lift": 0.11, "apple_search_flag": 0, "apple_search_lift": -0.45, "apple_all_flag": 1, "apple_all_lift": 0.23, "tiktok_creations_country_flag": 1, "tiktok_creations_country_lift": 0.1, "tiktok_creations_global_flag": 0, "tiktok_creations_global_lift": -0.2, "tiktok_views_country_flag": 0, "tiktok_views_country_lift": -0.3, "tiktok_views_global_flag": 1, "tiktok_views_global_lift": 0.4, "tiktok_likes_country_flag": 0, "tiktok_likes_country_lift": -0.5, "tiktok_likes_global_flag": 0, "tiktok_likes_global_lift": -0.6, }, ] def test_get_tadas_trends(): with patch( "analytics.logic.tadas.TADASTrends.execute", return_value=EXPECTED_RESULT_TADAS_TRENDS, ) as execute: result = get_tadas_trends( { "market": "US", "company_brand_uuids": ["123", "456"], "parent_company_uuids": ["789"], "limit": 10, "offset": 0, "order_by": "tadas_days_trending", "order_dir": "asc", }, {}, ) assert execute.call_count == 1 # Check that the result has the expected structure after trending_flags processing assert "trends" in result assert "count" in result assert result["count"] == 2 assert len(result["trends"]) == 2 # Check that trending_flags were added and _flag/_lift columns were removed for trend in result["trends"]: assert "trending_flags" in trend assert isinstance(trend["trending_flags"], list) # Ensure no _flag or _lift columns remain flag_lift_columns = [ k for k in trend.keys() if k.endswith("_flag") or k.endswith("_lift") ] assert len(flag_lift_columns) == 0 # Check that other fields are preserved assert "id" in trend assert "isrc" in trend def test_get_tadas_data_availability(): with patch( "analytics.logic.tadas.TADASDataAvailability.execute", return_value=EXPECTED_RESULT_TADAS_DATA_AVAILABILITY, ) as execute: result = get_tadas_data_availability( {}, {}, ) execute.assert_called_once() assert result == { "by_country_tadas_last_available_date": "2023-10-15", "global_tadas_last_available_date": "2023-10-20", } def test_get_tadas_trend_globalsoundrecording_by_isrc(): with patch( "analytics.logic.tadas.TADASTrendByISRC.execute", return_value=EXPECTED_RESULT_TADAS_TRENDS, ) as execute: result = get_tadas_trend_globalsoundrecording_by_isrc( { "isrc": "US123123", "markets": ["US", "GB"], }, {}, ) execute.assert_called_once() # Check that the result has the expected structure after trending_flags processing assert "trends" in result assert "count" in result assert result["count"] == 2 assert len(result["trends"]) == 2 # Check that trending_flags were added and _flag/_lift columns were removed for trend in result["trends"]: assert "trending_flags" in trend assert isinstance(trend["trending_flags"], list) # Ensure no _flag or _lift columns remain flag_lift_columns = [ k for k in trend.keys() if k.endswith("_flag") or k.endswith("_lift") ] assert len(flag_lift_columns) == 0 def test_get_trending_flags_for_row_s_tier_flags(): """Test get_trending_flags_for_row with S tier flags only.""" row = { "market": "US", "spotify_collection_flag": True, "spotify_collection_lift": 0.15, "spotify_lean_forward_flag": True, "spotify_lean_forward_lift": 0.25, "spotify_search_flag": True, "spotify_search_lift": 0.33, "tiktok_creations_global_flag": True, "tiktok_creations_global_lift": 0.20, # Lower tier flags that should be ignored "apple_lean_forward_flag": True, "apple_lean_forward_lift": 0.50, } result = get_trending_flags_for_row(row) # Should return top 3 S tier flags sorted by lift assert len(result) == 3 assert result[0]["name"] == "Spotify Search Streams" assert result[0]["lift"] == 0.33 assert result[0]["tier"] == "S" assert result[0]["market"] == "US" assert result[0]["store_id"] == 286 assert result[1]["name"] == "Spotify Lean Forward Streams" assert result[1]["lift"] == 0.25 assert result[1]["tier"] == "S" assert result[1]["store_id"] == 286 assert result[2]["name"] == "TikTok Creations" assert result[2]["lift"] == 0.20 assert result[2]["tier"] == "S" assert result[2]["market"] == "GLOBAL" assert result[2]["store_id"] == 1202 def test_get_trending_flags_for_row_no_s_tier_flags(): """Test get_trending_flags_for_row with no S tier flags, should use Tier 1.""" row = { "market": "DE", "spotify_collection_flag": False, # S tier # Tier 1 flags "apple_lean_forward_flag": True, "apple_lean_forward_lift": 0.30, "apple_search_flag": True, "apple_search_lift": 0.25, "tiktok_views_country_flag": True, "tiktok_views_country_lift": 0.35, "tiktok_likes_global_flag": True, "tiktok_likes_global_lift": 0.45, # Tier 2 flag (should be ignored) "apple_all_flag": True, "apple_all_lift": 0.90, } result = get_trending_flags_for_row(row) # Should return top 3 from Tier 1, sorted by lift assert len(result) == 3 assert result[0]["name"] == "TikTok Likes" assert result[0]["tier"] == "ONE" assert result[0]["lift"] == 0.45 assert result[0]["market"] == "GLOBAL" assert result[0]["store_id"] == 1202 assert result[1]["name"] == "TikTok Views" assert result[1]["tier"] == "ONE" assert result[1]["lift"] == 0.35 assert result[1]["market"] == "DE" assert result[1]["store_id"] == 1202 assert result[2]["name"] == "Apple Music Lean Forward Streams" assert result[2]["tier"] == "ONE" assert result[2]["lift"] == 0.30 assert result[2]["store_id"] == 1 def test_get_trending_flags_for_row_less_than_3_flags_total(): """Test get_trending_flags_for_row with fewer than 3 flags in total.""" row = { "market": "FR", "spotify_search_flag": True, # S tier "spotify_search_lift": 0.5, "apple_all_flag": True, # Tier 2 "apple_all_lift": 0.4, } result = get_trending_flags_for_row(row) # Should return both flags, in correct tier order assert len(result) == 2 assert result[0]["name"] == "Spotify Search Streams" assert result[0]["tier"] == "S" assert result[0]["store_id"] == 286 assert result[1]["name"] == "Apple Music Overall streams" assert result[1]["tier"] == "TWO" assert result[1]["store_id"] == 1 def test_get_trending_flags_for_row_tie_in_lift_values(): """Test get_trending_flags_for_row with a tie in lift values.""" row = { "market": "JP", "spotify_collection_flag": True, "spotify_collection_lift": 0.5, "spotify_lean_forward_flag": True, "spotify_lean_forward_lift": 0.6, "spotify_search_flag": True, "spotify_search_lift": 0.6, # Tie with lean forward } result = get_trending_flags_for_row(row) assert len(result) == 3 # The top two could be in any order, so check for names and lifts assert result[0]["lift"] == 0.6 assert result[1]["lift"] == 0.6 assert {"Spotify Lean Forward Streams", "Spotify Search Streams"} == { result[0]["name"], result[1]["name"], } # Both should have store_id 286 (Spotify) assert result[0]["store_id"] == 286 assert result[1]["store_id"] == 286 assert result[2]["name"] == "Spotify Collection Streams" assert result[2]["lift"] == 0.5 assert result[2]["store_id"] == 286 def test_get_trending_flags_for_row_all_tiers_present(): """Test get_trending_flags_for_row with flags from all tiers present.""" row = { "market": "AU", "spotify_collection_flag": True, # S "spotify_collection_lift": 0.1, "apple_lean_forward_flag": True, # 1 "apple_lean_forward_lift": 0.9, "apple_all_flag": True, # 2 "apple_all_lift": 0.8, "spotify_all_flag": True, # 3 "spotify_all_lift": 0.7, } result = get_trending_flags_for_row(row) # Should only contain the S-tier flag because it stops after processing a tier with flags # and having >= 3 flags is not met until all tiers are processed. # The final result is then sorted by tier, then lift. assert len(result) == 3 assert result[0]["name"] == "Spotify Collection Streams" assert result[0]["tier"] == "S" assert result[0]["store_id"] == 286 assert result[1]["name"] == "Apple Music Lean Forward Streams" assert result[1]["tier"] == "ONE" assert result[1]["store_id"] == 1 assert result[2]["name"] == "Apple Music Overall streams" assert result[2]["tier"] == "TWO" assert result[2]["store_id"] == 1 def test_calculate_trending_flags_removes_flag_lift_columns(): """Test that calculate_trending_flags removes all _flag and _lift columns.""" results = [ { "id": "1", "isrc": "US123123", "market": "US", "spotify_collection_flag": True, "spotify_collection_lift": 0.15, "spotify_search_flag": True, "spotify_search_lift": 0.33, "apple_lean_forward_flag": False, "apple_lean_forward_lift": -0.11, "some_other_field": "value", } ] result = calculate_trending_flags(results) # Check that trending_flags was added assert "trending_flags" in result[0] assert len(result[0]["trending_flags"]) == 2 # Check that all _flag and _lift columns were removed flag_lift_columns = [ k for k in result[0].keys() if k.endswith("_flag") or k.endswith("_lift") ] assert len(flag_lift_columns) == 0 # Check that other fields remain assert result[0]["id"] == "1" assert result[0]["isrc"] == "US123123" assert result[0]["some_other_field"] == "value" def test_calculate_trending_flags_multiple_rows(): """Test calculate_trending_flags with multiple rows.""" results = [ { "id": "1", "market": "US", "spotify_collection_flag": True, "spotify_collection_lift": 0.15, "spotify_search_flag": True, "spotify_search_lift": 0.33, }, { "id": "2", "market": "GB", "apple_lean_forward_flag": True, "apple_lean_forward_lift": 0.25, }, ] result = calculate_trending_flags(results) # Check first row assert len(result[0]["trending_flags"]) == 2 assert result[0]["trending_flags"][0]["name"] == "Spotify Search Streams" assert result[0]["trending_flags"][0]["tier"] == "S" assert result[0]["trending_flags"][0]["store_id"] == 286 # Check second row assert len(result[1]["trending_flags"]) == 1 assert result[1]["trending_flags"][0]["name"] == "Apple Music Lean Forward Streams" assert result[1]["trending_flags"][0]["tier"] == "ONE" assert result[1]["trending_flags"][0]["store_id"] == 1 # Check that flag/lift columns are removed from both rows for row in result: flag_lift_columns = [ k for k in row.keys() if k.endswith("_flag") or k.endswith("_lift") ] assert len(flag_lift_columns) == 0 def test_calculate_trending_flags_tier_priority(): """Test that calculate_trending_flags respects tier priority.""" results = [ { "id": "1", "market": "US", # S tier flag with lower lift "spotify_collection_flag": True, "spotify_collection_lift": 0.10, # Tier 2 flag with higher lift (should not be selected first) "apple_all_flag": True, "apple_all_lift": 0.60, } ] result = calculate_trending_flags(results) # The result should contain both, but S-tier should be first. assert len(result[0]["trending_flags"]) == 2 assert result[0]["trending_flags"][0]["name"] == "Spotify Collection Streams" assert result[0]["trending_flags"][0]["tier"] == "S" assert result[0]["trending_flags"][0]["lift"] == 0.10 assert result[0]["trending_flags"][0]["store_id"] == 286 assert result[0]["trending_flags"][1]["name"] == "Apple Music Overall streams" assert result[0]["trending_flags"][1]["tier"] == "TWO" assert result[0]["trending_flags"][1]["lift"] == 0.60 assert result[0]["trending_flags"][1]["store_id"] == 1