"""Integration tests for 14-day trend logic.""" from datetime import datetime, timedelta, timezone import requests from tests.integration.config import QA_BASE_URL from tests.integration.consts.permissions import ALL_PERMISSIONS_EMPLOYEE_HEADERS # Test data RAPCAVIAR_PLAYLIST_ID = "37i9dQZF1DX0XUsuxWHRQd" # RapCaviar TODAY_TOP_HITS_PLAYLIST_ID = "37i9dQZF1DXcBWIGoYBM5M" # Today's Top Hits SPOTIFY_STORE_ID = 286 class TestPlacements14DayTrend: """Test that position trends are hidden when position changes occurred more than 14 days ago.""" def test_hides_trend_when_position_changed_more_than_14_days_ago(self): """Test that position_change is null when the change was more than 14 days ago. When a position change occurred more than 14 days ago, only position_change should be null. The previous_position and previous_position_date fields should still contain their values for historical reference. """ response = requests.get( f"{QA_BASE_URL}/playlist/{TODAY_TOP_HITS_PLAYLIST_ID}/placements", params={ "store_id": SPOTIFY_STORE_ID, "limit": 50, }, headers=ALL_PERMISSIONS_EMPLOYEE_HEADERS, ) assert response.status_code == 200 placements = response.json()["data"]["placements"] # Find tracks where position has changed and the integer day count is > 14 # The query uses .days truncation (integer), so we match that logic now = datetime.now(timezone.utc) for placement in placements: previous_position_date = placement.get("previous_position_date") current_position = placement.get("current_position") previous_position = placement.get("previous_position") position_change = placement.get("position_change") # Skip if no date information if not previous_position_date: continue # Parse the date change_date = datetime.fromisoformat( previous_position_date.replace("Z", "+00:00") ) # Use same logic as query: integer day count > 14 days_ago = (now - change_date).days # If position changed (current != previous) and days_ago > 14 # Then position_change should be null (but previous_position can have a value) if ( days_ago > 14 and previous_position is not None and current_position != previous_position ): assert position_change is None, ( f"Track at position {current_position} (ISRC: {placement.get('isrc')}) " f"had position change on {previous_position_date} (>14 days ago) " f"but position_change is {position_change} instead of null" ) def test_shows_trend_when_position_changed_recently(self): """Test that trends are shown when the position change was within the last 14 days.""" response = requests.get( f"{QA_BASE_URL}/playlist/{RAPCAVIAR_PLAYLIST_ID}/placements", params={ "store_id": SPOTIFY_STORE_ID, "limit": 50, }, headers=ALL_PERMISSIONS_EMPLOYEE_HEADERS, ) assert response.status_code == 200 placements = response.json()["data"]["placements"] fourteen_days_ago = datetime.now(timezone.utc) - timedelta(days=14) found_recent_change = False for placement in placements: previous_position_date = placement.get("previous_position_date") current_position = placement.get("current_position") previous_position = placement.get("previous_position") position_change = placement.get("position_change") # Skip if no date information if not previous_position_date: continue # Parse the date change_date = datetime.fromisoformat( previous_position_date.replace("Z", "+00:00") ) # If position change was within the last 14 days and position actually changed # Then previous_position and position_change should NOT be null if ( change_date > fourteen_days_ago and current_position != previous_position ): found_recent_change = True assert previous_position is not None, ( f"Track at position {current_position} (ISRC: {placement.get('isrc')}) " f"had position change on {previous_position_date} (<14 days ago) " f"but previous_position is null" ) assert position_change is not None, ( f"Track at position {current_position} (ISRC: {placement.get('isrc')}) " f"had position change on {previous_position_date} (<14 days ago) " f"but position_change is null" ) # Verify the calculation is correct expected_change = previous_position - current_position assert position_change == expected_change, ( f"Position change calculation incorrect: expected {expected_change}, " f"got {position_change}" ) # Note: This test validates that IF recent changes exist, they are displayed correctly # It's okay if no recent changes are found in the test data, as the first test # validates the opposite case (old changes being hidden) if found_recent_change: # At least one recent change was validated successfully pass