"""Tests for new_music_friday_date logic""" import pytest from unittest.mock import patch from unittest.mock import ANY from uuid import UUID from charts.connectors import snowflake from charts.logic import new_music_friday_date @pytest.mark.parametrize( "input,expected_sql_parts,expected_params", ( ( new_music_friday_date.NewMusicFridayDateEntriesFilter(), [ '(TRUE)', ], {}, ), ( new_music_friday_date.NewMusicFridayDateEntriesFilter( appears_on_market='', ), [ 'dnmfc2.country = :filter_appears_on_market', ], { 'filter_appears_on_market': '', } ), ( new_music_friday_date.NewMusicFridayDateEntriesFilter( appears_on_market='US', ), [ 'dnmfc2.country = :filter_appears_on_market', ], { 'filter_appears_on_market': 'US', } ), ( new_music_friday_date.NewMusicFridayDateEntriesFilter( brand_uuid_in=[], ), [ "FALSE", ], {} ), ( new_music_friday_date.NewMusicFridayDateEntriesFilter( brand_uuid_in=[ UUID('a1c988d3-12f8-4fb9-82d7-7017d49393f1'), UUID('c3e22f58-5898-40ac-a7df-2859a30029f8'), ], ), [ "AND vcbpc.company_brand_uuid IN ('a1c988d3-12f8-4fb9-82d7-7017d49393f1', 'c3e22f58-5898-40ac-a7df-2859a30029f8')", ], {} ), ( new_music_friday_date.NewMusicFridayDateEntriesFilter( isrc='', ), [ 'isrcs.isrc = :filter_isrc', ], { 'filter_isrc': '', } ), ( new_music_friday_date.NewMusicFridayDateEntriesFilter( isrc='AA1921391239', ), [ 'isrcs.isrc = :filter_isrc', ], { 'filter_isrc': 'AA1921391239', } ), ( new_music_friday_date.NewMusicFridayDateEntriesFilter( appears_on_market='US', brand_uuid_in=[ UUID('a1c988d3-12f8-4fb9-82d7-7017d49393f1'), UUID('c3e22f58-5898-40ac-a7df-2859a30029f8'), ], isrc='AA1921391239', ), [ 'dnmfc2.country = :filter_appears_on_market', "AND vcbpc.company_brand_uuid IN ('a1c988d3-12f8-4fb9-82d7-7017d49393f1', 'c3e22f58-5898-40ac-a7df-2859a30029f8')", 'isrcs.isrc = :filter_isrc', ], { 'filter_appears_on_market': 'US', 'filter_isrc': 'AA1921391239', } ), ) ) def test_new_music_friday_date_entires_filter_to_sql( input: new_music_friday_date.NewMusicFridayDateEntriesFilter, expected_sql_parts: list[str] | str, expected_params: snowflake.SnowflakeParameterType, ) -> None: sql, params = new_music_friday_date.new_music_friday_date_entries_filter_to_sql(input) for expected_sql_part in expected_sql_parts: assert expected_sql_part in sql assert params == expected_params @pytest.mark.parametrize( "input,expected", ( ( new_music_friday_date.NewMusicFridayDateEntriesOrder( by='FEATURING', dir='ASC', ), 'feature ASC' ), ( new_music_friday_date.NewMusicFridayDateEntriesOrder( by='FEATURING', dir='DESC', ), 'feature DESC' ), ( new_music_friday_date.NewMusicFridayDateEntriesOrder( by='AVERAGE_POSITION', dir='ASC', ), 'average_position ASC' ), ( new_music_friday_date.NewMusicFridayDateEntriesOrder( by='AVERAGE_POSITION', dir='DESC', ), 'average_position DESC' ), ( new_music_friday_date.NewMusicFridayDateEntriesOrder( by='TOP_10_RANK', dir='ASC', ), 'top_10_rank ASC' ), ( new_music_friday_date.NewMusicFridayDateEntriesOrder( by='TOP_10_RANK', dir='DESC', ), 'top_10_rank DESC' ), ( new_music_friday_date.NewMusicFridayDateEntriesOrder( by='POSITION_IN_MARKET', market='US', dir='ASC', ), "MIN(CASE WHEN fna.country = 'US' THEN position ELSE NULL END) ASC NULLS LAST" ), ( new_music_friday_date.NewMusicFridayDateEntriesOrder( by='POSITION_IN_MARKET', market='JP', dir='DESC', ), "MIN(CASE WHEN fna.country = 'JP' THEN position ELSE NULL END) DESC NULLS LAST" ), ) ) def test_new_music_friday_date_entires_order_to_sql( input: new_music_friday_date.NewMusicFridayDateEntriesOrder, expected: str, ) -> None: result = new_music_friday_date.new_music_friday_date_entires_order_to_sql(input) assert result == expected def test_new_music_friday_date_entires_orders_to_sql() -> None: result = new_music_friday_date.new_music_friday_date_entires_orders_to_sql( [ new_music_friday_date.NewMusicFridayDateEntriesOrder( by='FEATURING', dir='ASC', ), new_music_friday_date.NewMusicFridayDateEntriesOrder( by='TOP_10_RANK', dir='DESC', ), ], ) assert result == 'feature ASC, top_10_rank DESC' def test_new_music_friday_date_entries_no_results() -> None: fetchall_mock_response: list[str] = [] with patch.object(snowflake, 'fetchall_nocache', return_value=fetchall_mock_response) as mock_fetchall: result = new_music_friday_date.new_music_friday_date_entries( '2025-01-01', new_music_friday_date.NewMusicFridayDateEntriesFilter( isrc='AA1921391239', ), [ new_music_friday_date.NewMusicFridayDateEntriesOrder( by='FEATURING', dir='ASC', ), new_music_friday_date.NewMusicFridayDateEntriesOrder( by='TOP_10_RANK', dir='DESC', ), ], 123, 456, ) mock_fetchall.assert_called_once_with( ANY, { 'date': '2025-01-01', 'offset': 123, 'limit': 456, 'filter_isrc': 'AA1921391239', }, ) assert 'isrcs.isrc = :filter_isrc' in mock_fetchall.call_args[0][0] assert 'ORDER BY feature ASC, top_10_rank DESC, isrcs.track_name ASC\n' in mock_fetchall.call_args[0][0] assert result.model_dump() == { 'total': 0, 'entries': [] } def test_new_music_friday_date_entries_with_results() -> None: fetchall_mock_response = [ ( 2, 'ISRC1', 'Test Track Name', 'Test Artist Name', 'Test Image URL', 1, 1.5, 2, '[{"market":"US","position":1,"spotify_id":"spotify_id_1"},{"market":"GB","position":null,"spotify_id":"spotify_id_2"}]' ), ( 2, 'ISRC2', None, None, None, 2, 2.5, 3, '[{"market":"US","position":5,"spotify_id":"spotify_id_3"},{"market":"GB","position":1,"spotify_id":"spotify_id_4"}]' ), ] with patch.object(snowflake, 'fetchall_nocache', return_value=fetchall_mock_response) as mock_fetchall: result = new_music_friday_date.new_music_friday_date_entries( '2025-01-01', new_music_friday_date.NewMusicFridayDateEntriesFilter( isrc='AA1921391239' ), [ new_music_friday_date.NewMusicFridayDateEntriesOrder( by='FEATURING', dir='ASC', ), new_music_friday_date.NewMusicFridayDateEntriesOrder( by='TOP_10_RANK', dir='DESC', ), ], 123, 456, ) mock_fetchall.assert_called_once_with( ANY, { 'date': '2025-01-01', 'offset': 123, 'limit': 456, 'filter_isrc': 'AA1921391239', }, ) assert 'isrcs.isrc = :filter_isrc' in mock_fetchall.call_args[0][0] assert 'ORDER BY feature ASC, top_10_rank DESC, isrcs.track_name ASC\n' in mock_fetchall.call_args[0][0] assert result.model_dump() == { 'total': 2, 'entries': [ { 'isrc': 'ISRC1', 'track_name': 'Test Track Name', 'artist_name': 'Test Artist Name', 'image_url': 'Test Image URL', 'feature': 1, 'average_position': 1.5, 'top_10_rank': 2, 'placements': [ { 'market': 'US', 'position': 1, 'spotify_id': 'spotify_id_1', }, { 'market': 'GB', 'position': None, 'spotify_id': 'spotify_id_2', }, ], }, { 'isrc': 'ISRC2', 'track_name': None, 'artist_name': None, 'image_url': None, 'feature': 2, 'average_position': 2.5, 'top_10_rank': 3, 'placements': [ { 'market': 'US', 'position': 5, 'spotify_id': 'spotify_id_3', }, { 'market': 'GB', 'position': 1, 'spotify_id': 'spotify_id_4', }, ], }, ] } def test_new_music_friday_date_entries_handles_null_average_position() -> None: """Rows with NULL AVG(position) — e.g. ISRC only chart in markets where data_received=FALSE on the requested date — must serialize cleanly. """ fetchall_mock_response = [ ( 1, 'ISRC1', 'Test Track Name', 'Test Artist Name', None, 0, None, 0, '[]', ), ] with patch.object(snowflake, 'fetchall_nocache', return_value=fetchall_mock_response): result = new_music_friday_date.new_music_friday_date_entries( '2025-01-01', new_music_friday_date.NewMusicFridayDateEntriesFilter(isrc='ISRC1'), [new_music_friday_date.NewMusicFridayDateEntriesOrder(by='FEATURING', dir='DESC')], 0, 10, ) assert result.total == 1 assert result.entries[0].isrc == 'ISRC1' assert result.entries[0].feature == 0 assert result.entries[0].average_position is None assert result.entries[0].top_10_rank == 0 assert result.entries[0].placements == [] def test_new_music_friday_date_markets() -> None: """Test new_music_friday_date_markets.""" fetchall_mock_response = [ ('US', False), ('GB', True), ('JP', False), ('FR', True), ] with patch.object(snowflake, 'fetchall_nocache', return_value=fetchall_mock_response) as mock_fetchall: result = new_music_friday_date.new_music_friday_date_markets('2025-01-01') assert result.model_dump() == { 'markets': [ { 'market': 'US', 'data_received': False, }, { 'market': 'GB', 'data_received': True, }, { 'market': 'JP', 'data_received': False, }, { 'market': 'FR', 'data_received': True, }, ] } mock_fetchall.assert_called_once_with( ANY, { 'date': '2025-01-01', } )