From 832bf32a8c1ce2d60b718432d39105f82a3f4d2b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 00:01:11 +0000 Subject: [PATCH] chore: remove manager-era NBA test files and one-off debug scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The four test_nba_*.py files imported nba_managers, leaderboard_manager and odds_manager — top-level modules deleted when sports displays became plugins — inside try/except blocks that swallowed the ImportError, so they passed while exercising nothing. test_nba_data_structure.py and debug_nba_api.py (a diagnostic script living in test/) made live ESPN API calls rather than testing repo code. None were enrolled in CI. scripts/debug/direct_fix_imports.py and check_imports.py were one-shot artifacts that edited/inspected a hardcoded ~/LEDMatrix/web_interface/ app.py to fix an import problem solved long ago; nothing references them. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01SXb4mKcAkVaxkeTb3YnAdr --- docs/HOW_TO_RUN_TESTS.md | 1 - scripts/debug/check_imports.py | 28 --- scripts/debug/direct_fix_imports.py | 58 ------ test/debug_nba_api.py | 166 ----------------- test/test_nba_core_functionality.py | 262 -------------------------- test/test_nba_data_structure.py | 147 --------------- test/test_nba_integration.py | 280 ---------------------------- test/test_nba_leaderboard_fix.py | 113 ----------- 8 files changed, 1055 deletions(-) delete mode 100644 scripts/debug/check_imports.py delete mode 100644 scripts/debug/direct_fix_imports.py delete mode 100644 test/debug_nba_api.py delete mode 100644 test/test_nba_core_functionality.py delete mode 100644 test/test_nba_data_structure.py delete mode 100644 test/test_nba_integration.py delete mode 100644 test/test_nba_leaderboard_fix.py diff --git a/docs/HOW_TO_RUN_TESTS.md b/docs/HOW_TO_RUN_TESTS.md index a13b9628..c491e15d 100644 --- a/docs/HOW_TO_RUN_TESTS.md +++ b/docs/HOW_TO_RUN_TESTS.md @@ -253,7 +253,6 @@ test/ ├── test_error_aggregator.py # Error aggregation tests ├── test_schema_manager.py # Schema manager tests ├── test_web_api.py # Web API tests -├── test_nba_*.py # NBA-specific test suites ├── plugins/ # Per-plugin test suites │ ├── test_clock_simple.py │ ├── test_calendar.py diff --git a/scripts/debug/check_imports.py b/scripts/debug/check_imports.py deleted file mode 100644 index a1cefae0..00000000 --- a/scripts/debug/check_imports.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -""" -Check what imports are actually in the app.py file on the Pi -""" - -from pathlib import Path - -# Read the app.py file and check the import lines -app_py_path = Path.home() / 'LEDMatrix' / 'web_interface' / 'app.py' - -print(f"🔍 Checking imports in: {app_py_path}") -print(f"📁 File exists: {app_py_path.exists()}") - -if app_py_path.exists(): - with open(app_py_path, 'r') as f: - lines = f.readlines() - - print("\n🔍 Import lines in app.py:") - for i, line in enumerate(lines, 1): - if 'from' in line and 'blueprints' in line and 'import' in line: - print(f" Line {i}: {line.strip()}") - - print("\n🔍 Blueprint registration lines:") - for i, line in enumerate(lines, 1): - if 'register_blueprint' in line: - print(f" Line {i}: {line.strip()}") -else: - print("❌ app.py file not found!") diff --git a/scripts/debug/direct_fix_imports.py b/scripts/debug/direct_fix_imports.py deleted file mode 100644 index 79d451a9..00000000 --- a/scripts/debug/direct_fix_imports.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python3 -""" -Direct fix for import issues - manually edit the app.py file -""" - -import os -from pathlib import Path - -def fix_imports(): - app_py_path = Path.home() / 'LEDMatrix' / 'web_interface' / 'app.py' - - print(f"🔧 Directly fixing imports in: {app_py_path}") - - # Read the file - with open(app_py_path, 'r') as f: - lines = f.readlines() - - # Find and fix the import lines - fixed = False - for i, line in enumerate(lines, 1): - if 'from blueprints.pages_v3 import' in line: - lines[i-1] = "from web_interface.blueprints.pages_v3 import pages_v3\n" - print(f"✅ Fixed line {i}: from blueprints.pages_v3 import → from web_interface.blueprints.pages_v3 import") - fixed = True - elif 'from blueprints.api_v3 import' in line: - lines[i-1] = "from web_interface.blueprints.api_v3 import api_v3\n" - print(f"✅ Fixed line {i}: from blueprints.api_v3 import → from web_interface.blueprints.api_v3 import") - fixed = True - - if not fixed: - print("❌ No import lines found to fix") - return False - - # Write the fixed file back - with open(app_py_path, 'w') as f: - f.writelines(lines) - - print("✅ File updated successfully") - return True - -def verify_fix(): - print("\n🔍 Verifying the fix...") - os.system("python3 check_imports.py") - -if __name__ == "__main__": - if fix_imports(): - print("\n🧹 Clearing Python cache...") - os.system("find ~/LEDMatrix -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null || true") - os.system("find ~/LEDMatrix -name '*.pyc' -delete 2>/dev/null || true") - - print("\n✅ Imports fixed and cache cleared!") - verify_fix() - - print("\n🚀 Now try running the web interface:") - print("cd ~/LEDMatrix") - print("python3 web_interface/start.py") - else: - print("\n❌ Fix failed") diff --git a/test/debug_nba_api.py b/test/debug_nba_api.py deleted file mode 100644 index 5840f5e1..00000000 --- a/test/debug_nba_api.py +++ /dev/null @@ -1,166 +0,0 @@ -#!/usr/bin/env python3 -""" -Diagnostic script to examine NBA API data structure and identify the missing 'id' field issue. -""" -import requests -import logging -from typing import Dict, Any - -# Set up logging -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') -logger = logging.getLogger(__name__) - -def fetch_nba_teams_data() -> Dict[str, Any]: - """Fetch NBA teams data from ESPN API.""" - teams_url = "https://site.api.espn.com/apis/site/v2/sports/basketball/nba/teams" - - try: - logger.info(f"Fetching NBA teams data from: {teams_url}") - response = requests.get(teams_url, timeout=30) - response.raise_for_status() - data = response.json() - - logger.info(f"Successfully fetched NBA teams data") - logger.info(f"Response structure keys: {list(data.keys())}") - - # Examine the structure - sports = data.get('sports', []) - if sports: - logger.info(f"Number of sports: {len(sports)}") - sport = sports[0] - logger.info(f"Sport keys: {list(sport.keys())}") - - leagues = sport.get('leagues', []) - if leagues: - league = leagues[0] - logger.info(f"League keys: {list(league.keys())}") - - teams = league.get('teams', []) - logger.info(f"Number of teams: {len(teams)}") - - if teams: - # Examine first team structure - first_team = teams[0] - logger.info(f"First team keys: {list(first_team.keys())}") - - team_data = first_team.get('team', {}) - logger.info(f"Team data keys: {list(team_data.keys())}") - - # Check for id field - team_id = team_data.get('id') - team_abbr = team_data.get('abbreviation') - team_name = team_data.get('name') - - logger.info(f"Sample team: ID={team_id}, ABBR={team_abbr}, NAME={team_name}") - - if team_id: - logger.info(f"Team ID field exists: {team_id}") - else: - logger.error("Team ID field is missing!") - - # Check a few more teams to confirm structure - for i in range(min(5, len(teams))): - team = teams[i].get('team', {}) - logger.info(f"Team {i+1}: ID={team.get('id')}, ABBR={team.get('abbreviation')}") - - return data - - except Exception as e: - logger.error(f"Error fetching NBA teams data: {e}") - return {} - -def fetch_nba_standings_data() -> Dict[str, Any]: - """Fetch NBA standings data from ESPN API.""" - standings_url = "https://site.api.espn.com/apis/v2/sports/basketball/nba/standings" - - try: - logger.info(f"Fetching NBA standings data from: {standings_url}") - response = requests.get(standings_url, timeout=30) - response.raise_for_status() - data = response.json() - - logger.info(f"Successfully fetched NBA standings data") - logger.info(f"Response structure keys: {list(data.keys())}") - - # Check if standings has entries (direct structure) - if 'standings' in data and 'entries' in data['standings']: - entries = data['standings']['entries'] - logger.info(f"Number of standings entries (direct): {len(entries)}") - - if entries: - # Examine first entry structure - first_entry = entries[0] - logger.info(f"First entry keys: {list(first_entry.keys())}") - - team_data = first_entry.get('team', {}) - logger.info(f"Team data keys: {list(team_data.keys())}") - - # Check for id field - team_id = team_data.get('id') - team_abbr = team_data.get('abbreviation') - team_name = team_data.get('displayName') - - logger.info(f"Sample standings team: ID={team_id}, ABBR={team_abbr}, NAME={team_name}") - - if team_id: - logger.info(f"Standings team ID field exists: {team_id}") - else: - logger.error("Standings team ID field is missing!") - - # Check children structure (divisions/conferences) - if 'children' in data: - children = data.get('children', []) - logger.info(f"Number of children (divisions/conferences): {len(children)}") - - for i, child in enumerate(children): - logger.info(f"Child {i+1} keys: {list(child.keys())}") - child_name = child.get('displayName', 'Unknown') - logger.info(f"Child {i+1} name: {child_name}") - - if 'standings' in child and 'entries' in child['standings']: - entries = child['standings']['entries'] - logger.info(f"Child {i+1} has {len(entries)} entries") - - if entries: - # Examine first entry in this child - first_entry = entries[0] - logger.info(f"Child {i+1} first entry keys: {list(first_entry.keys())}") - - team_data = first_entry.get('team', {}) - logger.info(f"Child {i+1} team data keys: {list(team_data.keys())}") - - # Check for id field - team_id = team_data.get('id') - team_abbr = team_data.get('abbreviation') - team_name = team_data.get('displayName') - - logger.info(f"Child {i+1} sample team: ID={team_id}, ABBR={team_abbr}, NAME={team_name}") - - if team_id: - logger.info(f"Child {i+1} team ID field exists: {team_id}") - else: - logger.error(f"Child {i+1} team ID field is missing!") - - return data - - except Exception as e: - logger.error(f"Error fetching NBA standings data: {e}") - return {} - -def main(): - """Main diagnostic function.""" - logger.info("Starting NBA API data structure diagnosis") - - # Fetch teams data - teams_data = fetch_nba_teams_data() - - # Fetch standings data - standings_data = fetch_nba_standings_data() - - # Summary - logger.info("Diagnosis complete") - logger.info("Check the logs above to see if team 'id' fields are present") - logger.info("The leaderboard manager needs team 'id' fields for logo fetching") - -if __name__ == "__main__": - main() diff --git a/test/test_nba_core_functionality.py b/test/test_nba_core_functionality.py deleted file mode 100644 index 85112cb4..00000000 --- a/test/test_nba_core_functionality.py +++ /dev/null @@ -1,262 +0,0 @@ -#!/usr/bin/env python3 -""" -Core functionality test for NBA components without hardware dependencies. -""" -import sys -import os -import logging -import json - -# Set up logging -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') -logger = logging.getLogger(__name__) - -def test_nba_data_structure(): - """Test NBA data structure and team ID field presence.""" - try: - import requests - - # Test teams endpoint for data structure - teams_url = "https://site.api.espn.com/apis/site/v2/sports/basketball/nba/teams" - response = requests.get(teams_url, timeout=10) - response.raise_for_status() - teams_data = response.json() - - # Extract first team to check structure - sports = teams_data.get('sports', []) - if not sports: - logger.error("No sports data found") - return False - - leagues = sports[0].get('leagues', []) - if not leagues: - logger.error("No leagues data found") - return False - - teams = leagues[0].get('teams', []) - if not teams: - logger.error("No teams data found") - return False - - first_team = teams[0].get('team', {}) - team_id = first_team.get('id') - team_abbr = first_team.get('abbreviation') - - logger.info(f"Sample team: ID={team_id}, ABBR={team_abbr}") - - if team_id is None: - logger.error("❌ Team ID field missing!") - return False - - logger.info("✅ NBA data structure test PASSED") - return True - - except Exception as e: - logger.error(f"❌ NBA data structure test FAILED: {e}") - return False - -def test_odds_data_structure(): - """Test odds data structure.""" - try: - import requests - - # Test odds endpoint for data structure - odds_url = "https://sports.core.api.espn.com/v2/sports/basketball/leagues/nba/events/401585515/competitions/401585515/odds" - response = requests.get(odds_url, timeout=10) - response.raise_for_status() - odds_data = response.json() - - logger.info(f"Odds data structure keys: {list(odds_data.keys())}") - - # Check if odds data has expected structure - if 'items' in odds_data: - logger.info("✅ Odds data has expected structure") - return True - else: - logger.warning("⚠️ Odds data structure different than expected") - return True # Still pass since API is working - - except Exception as e: - logger.error(f"❌ Odds data structure test FAILED: {e}") - return False - -def test_nba_standings_structure(): - """Test NBA standings data structure for team IDs.""" - try: - import requests - - # Test standings endpoint - standings_url = "https://site.api.espn.com/apis/v2/sports/basketball/nba/standings" - response = requests.get(standings_url, timeout=10) - response.raise_for_status() - standings_data = response.json() - - # Check children structure (Eastern/Western conferences) - children = standings_data.get('children', []) - if not children: - logger.error("No children (conferences) found in standings") - return False - - # Check first conference for team data - first_conference = children[0] - standings = first_conference.get('standings', {}) - entries = standings.get('entries', []) - - if not entries: - logger.error("No standings entries found") - return False - - # Check first team for ID field - first_team = entries[0].get('team', {}) - team_id = first_team.get('id') - team_abbr = first_team.get('abbreviation') - - logger.info(f"Standings team: ID={team_id}, ABBR={team_abbr}") - - if team_id is None: - logger.error("❌ Standings team ID field missing!") - return False - - logger.info("✅ NBA standings structure test PASSED") - return True - - except Exception as e: - logger.error(f"❌ NBA standings structure test FAILED: {e}") - return False - -def test_configuration_analysis(): - """Analyze current NBA configuration.""" - try: - with open('config/config.json', 'r') as f: - config = json.load(f) - - # Analyze NBA scoreboard config - nba_scoreboard = config.get('nba_scoreboard', {}) - logger.info("NBA Scoreboard Configuration:") - logger.info(f" Enabled: {nba_scoreboard.get('enabled', False)}") - logger.info(f" Show Odds: {nba_scoreboard.get('show_odds', False)}") - logger.info(f" Favorite Teams: {nba_scoreboard.get('favorite_teams', [])}") - logger.info(f" Logo Directory: {nba_scoreboard.get('logo_dir', 'N/A')}") - - # Analyze leaderboard config - leaderboard = config.get('leaderboard', {}) - nba_leaderboard = leaderboard.get('enabled_sports', {}).get('nba', {}) - - logger.info("\nLeaderboard NBA Configuration:") - logger.info(f" Leaderboard Enabled: {leaderboard.get('enabled', False)}") - logger.info(f" NBA Enabled: {nba_leaderboard.get('enabled', False)}") - logger.info(f" NBA Top Teams: {nba_leaderboard.get('top_teams', 'N/A')}") - - # Check for potential issues - issues = [] - - if not nba_scoreboard.get('enabled', False) and nba_scoreboard.get('show_odds', False): - issues.append("⚠️ NBA scoreboard disabled but odds enabled") - - if leaderboard.get('enabled', False) and not nba_leaderboard.get('enabled', False): - issues.append("ℹ️ Leaderboard enabled but NBA disabled") - - if issues: - logger.warning("Configuration Issues Found:") - for issue in issues: - logger.warning(f" {issue}") - else: - logger.info("✅ No configuration issues found") - - return True - - except Exception as e: - logger.error(f"❌ Configuration analysis FAILED: {e}") - return False - -def test_nba_logo_path_construction(): - """Test NBA logo path construction logic.""" - try: - # Simulate the logo path construction from leaderboard manager - team_abbr = "LAL" - logo_dir = "assets/sports/nba_logos" - expected_path = f"{logo_dir}/{team_abbr}.png" - - logger.info(f"Expected logo path: {expected_path}") - - # Check if directory exists - if os.path.exists(logo_dir): - logger.info(f"✅ Logo directory exists: {logo_dir}") - else: - logger.warning(f"⚠️ Logo directory does not exist: {logo_dir}") - - # Test team ID mapping (simulate what we fixed) - sample_teams = [ - ("LAL", "13"), # Lakers - ("BOS", "2"), # Celtics - ("MIA", "14"), # Heat - ] - - for abbr, team_id in sample_teams: - logger.info(f"Team {abbr}: ID={team_id} (for logo fetching)") - - logger.info("✅ NBA logo path construction test PASSED") - return True - - except Exception as e: - logger.error(f"❌ NBA logo path construction test FAILED: {e}") - return False - -def main(): - """Run core functionality tests.""" - logger.info("🧪 Starting NBA Core Functionality Tests") - logger.info("=" * 60) - - tests = [ - ("NBA Data Structure", test_nba_data_structure), - ("Odds Data Structure", test_odds_data_structure), - ("NBA Standings Structure", test_nba_standings_structure), - ("Configuration Analysis", test_configuration_analysis), - ("NBA Logo Path Construction", test_nba_logo_path_construction), - ] - - results = [] - for test_name, test_func in tests: - logger.info(f"\n🔍 Running: {test_name}") - try: - result = test_func() - results.append((test_name, result)) - except Exception as e: - logger.error(f"❌ {test_name} crashed: {e}") - results.append((test_name, False)) - - # Summary - logger.info("\n" + "=" * 60) - logger.info("📊 TEST SUMMARY") - logger.info("=" * 60) - - passed = 0 - failed = 0 - - for test_name, result in results: - status = "✅ PASSED" if result else "❌ FAILED" - logger.info(f"{test_name:<30} {status}") - if result: - passed += 1 - else: - failed += 1 - - logger.info("-" * 60) - logger.info(f"Total: {len(results)} | Passed: {passed} | Failed: {failed}") - - if failed == 0: - logger.info("🎉 ALL CORE TESTS PASSED!") - logger.info("\n📋 SUMMARY:") - logger.info("✅ NBA API provides team ID fields correctly") - logger.info("✅ Odds API integration is working") - logger.info("✅ NBA standings structure includes team IDs") - logger.info("✅ Logo fetching will work with team IDs") - logger.info("✅ Configuration is properly set up") - return True - else: - logger.error(f"❌ {failed} test(s) failed. Please check the issues above.") - return False - -if __name__ == "__main__": - success = main() - sys.exit(0 if success else 1) diff --git a/test/test_nba_data_structure.py b/test/test_nba_data_structure.py deleted file mode 100644 index c4f20768..00000000 --- a/test/test_nba_data_structure.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python3 -""" -Simple test script to verify NBA data structure includes team ID fields. -""" -import sys -import requests -import logging - -# Set up logging -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') -logger = logging.getLogger(__name__) - -def test_nba_data_structure(): - """Test that NBA data includes team ID fields.""" - try: - # Test fetching NBA teams data directly - logger.info("Testing NBA teams API...") - teams_url = "https://site.api.espn.com/apis/site/v2/sports/basketball/nba/teams" - response = requests.get(teams_url, timeout=30) - response.raise_for_status() - teams_data = response.json() - - # Extract team information - sports = teams_data.get('sports', []) - if not sports: - logger.error("No sports data found!") - return False - - leagues = sports[0].get('leagues', []) - if not leagues: - logger.error("No leagues data found!") - return False - - teams = leagues[0].get('teams', []) - if not teams: - logger.error("No teams data found!") - return False - - logger.info(f"Found {len(teams)} NBA teams") - - # Check first few teams for ID fields - teams_with_ids = 0 - for i, team_data in enumerate(teams[:5]): - team = team_data.get('team', {}) - team_id = team.get('id') - team_abbr = team.get('abbreviation', 'Unknown') - team_name = team.get('name', 'Unknown') - - logger.info(f"Team {i+1}: ID={team_id}, ABBR={team_abbr}, NAME={team_name}") - - if team_id is not None: - teams_with_ids += 1 - - if teams_with_ids == 0: - logger.error("No teams have ID fields!") - return False - - logger.info(f"{teams_with_ids} out of 5 tested teams have ID fields") - - # Test fetching NBA standings data directly - logger.info("Testing NBA standings API...") - standings_url = "https://site.api.espn.com/apis/v2/sports/basketball/nba/standings" - response = requests.get(standings_url, timeout=30) - response.raise_for_status() - standings_data = response.json() - - # Check standings structure - children = standings_data.get('children', []) - logger.info(f"Found {len(children)} conference/division groups") - - standings_teams_with_ids = 0 - total_standings_teams = 0 - - for child in children: - if 'standings' in child and 'entries' in child['standings']: - entries = child['standings']['entries'] - total_standings_teams += len(entries) - - for entry in entries[:3]: # Check first 3 teams per conference - team = entry.get('team', {}) - team_id = team.get('id') - team_abbr = team.get('abbreviation', 'Unknown') - team_name = team.get('displayName', 'Unknown') - - logger.info(f"Standings team: ID={team_id}, ABBR={team_abbr}, NAME={team_name}") - - if team_id is not None: - standings_teams_with_ids += 1 - - if standings_teams_with_ids == 0: - logger.error("No standings teams have ID fields!") - return False - - logger.info(f"{standings_teams_with_ids} standings teams have ID fields out of {total_standings_teams} total teams") - - # Simulate the fixed leaderboard manager logic - logger.info("Simulating fixed leaderboard manager logic...") - - # Simulate the team data structure that would be created by the fixed code - simulated_teams = [] - for team_data in teams[:3]: # Test with first 3 teams - team = team_data.get('team', {}) - simulated_teams.append({ - 'name': team.get('name', 'Unknown'), - 'id': team.get('id'), # This is the fix - including the ID field - 'abbreviation': team.get('abbreviation', 'Unknown'), - 'wins': 10, # Mock data - 'losses': 5, # Mock data - 'ties': 0, # Mock data - 'win_percentage': 0.667 # Mock data - }) - - # Verify that our simulated teams have ID fields - teams_with_ids_in_simulation = 0 - for team in simulated_teams: - if team.get('id') is not None: - teams_with_ids_in_simulation += 1 - logger.info(f"Simulated team: {team['abbreviation']} (ID: {team['id']})") - - if teams_with_ids_in_simulation == len(simulated_teams): - logger.info("✅ All simulated teams have ID fields - fix is working!") - return True - else: - logger.error(f"❌ {len(simulated_teams) - teams_with_ids_in_simulation} simulated teams missing ID fields!") - return False - - except Exception as e: - logger.error(f"Error testing NBA data structure: {e}") - return False - -def main(): - """Main test function.""" - logger.info("Testing NBA data structure and fix...") - - success = test_nba_data_structure() - - if success: - logger.info("✅ NBA data structure test PASSED!") - logger.info("The NBA leaderboard fix should work correctly") - else: - logger.error("❌ NBA data structure test FAILED!") - - return success - -if __name__ == "__main__": - success = main() - sys.exit(0 if success else 1) diff --git a/test/test_nba_integration.py b/test/test_nba_integration.py deleted file mode 100644 index fc3ed3cf..00000000 --- a/test/test_nba_integration.py +++ /dev/null @@ -1,280 +0,0 @@ -#!/usr/bin/env python3 -""" -Comprehensive test script to verify NBA Manager, Leaderboard, and Odds Manager integration. -""" -import sys -import os -import logging -import json - -# Set up logging -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') -logger = logging.getLogger(__name__) - -def test_nba_api_connectivity(): - """Test basic NBA API connectivity.""" - try: - import requests - - # Test teams endpoint - teams_url = "https://site.api.espn.com/apis/site/v2/sports/basketball/nba/teams" - response = requests.get(teams_url, timeout=10) - response.raise_for_status() - teams_data = response.json() - - # Test standings endpoint - standings_url = "https://site.api.espn.com/apis/v2/sports/basketball/nba/standings" - response = requests.get(standings_url, timeout=10) - response.raise_for_status() - standings_data = response.json() - - # Test live games endpoint - live_url = "https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard" - response = requests.get(live_url, timeout=10) - response.raise_for_status() - live_data = response.json() - - logger.info("✅ NBA API connectivity test PASSED") - return True - - except Exception as e: - logger.error(f"❌ NBA API connectivity test FAILED: {e}") - return False - -def test_odds_api_connectivity(): - """Test odds API connectivity.""" - try: - import requests - - # Test ESPN odds API - odds_url = "https://sports.core.api.espn.com/v2/sports/basketball/leagues/nba/events/401585515/competitions/401585515/odds" - response = requests.get(odds_url, timeout=10) - response.raise_for_status() - odds_data = response.json() - - logger.info("✅ Odds API connectivity test PASSED") - return True - - except Exception as e: - logger.error(f"❌ Odds API connectivity test FAILED: {e}") - return False - -def test_nba_manager_initialization(): - """Test NBA manager initialization and configuration.""" - try: - # Mock the required dependencies since we're not on Raspberry Pi - class MockDisplayManager: - def __init__(self): - self.matrix = type('obj', (object,), {'width': 64, 'height': 32})() - - class MockCacheManager: - def __init__(self): - self.config_manager = None - - def get(self, key): - return None - - def save_cache(self, key, data): - pass - - # Load config - with open('config/config.json', 'r') as f: - config = json.load(f) - - # Test manager imports - sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) - - from nba_managers import BaseNBAManager, NBALiveManager, NBARecentManager, NBAUpcomingManager - - # Test initialization - display_manager = MockDisplayManager() - cache_manager = MockCacheManager() - - # Test base manager - base_manager = BaseNBAManager(config, display_manager, cache_manager) - logger.info(f"✅ Base NBA Manager initialized: {base_manager.league}") - - # Test live manager - live_manager = NBALiveManager(config, display_manager, cache_manager) - logger.info(f"✅ NBA Live Manager initialized") - - # Test recent manager - recent_manager = NBARecentManager(config, display_manager, cache_manager) - logger.info(f"✅ NBA Recent Manager initialized") - - # Test upcoming manager - upcoming_manager = NBAUpcomingManager(config, display_manager, cache_manager) - logger.info(f"✅ NBA Upcoming Manager initialized") - - return True - - except Exception as e: - logger.error(f"❌ NBA Manager initialization test FAILED: {e}") - return False - -def test_leaderboard_nba_integration(): - """Test leaderboard NBA integration.""" - try: - # Mock dependencies - class MockDisplayManager: - def __init__(self): - self.matrix = type('obj', (object,), {'width': 64, 'height': 32})() - - class MockCacheManager: - def __init__(self): - self.config_manager = None - - def get_cached_data_with_strategy(self, key, strategy): - return None - - def save_cache(self, key, data): - pass - - def clear_cache(self, key): - pass - - # Load config - with open('config/config.json', 'r') as f: - config = json.load(f) - - sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) - - from leaderboard_manager import LeaderboardManager - - # Test initialization - display_manager = MockDisplayManager() - cache_manager = MockCacheManager() - - leaderboard = LeaderboardManager(config, display_manager) - - # Check if NBA is configured in leaderboard - nba_config = leaderboard.league_configs.get('nba', {}) - logger.info(f"NBA leaderboard config: {nba_config}") - - # Test NBA standings fetching (without actual API call) - logger.info("✅ Leaderboard NBA integration test PASSED") - return True - - except Exception as e: - logger.error(f"❌ Leaderboard NBA integration test FAILED: {e}") - return False - -def test_odds_manager_integration(): - """Test odds manager integration.""" - try: - # Mock cache manager - class MockCacheManager: - def __init__(self): - self.config_manager = None - - def get_with_auto_strategy(self, key): - return None - - sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) - - from odds_manager import OddsManager - - # Test initialization - cache_manager = MockCacheManager() - odds_manager = OddsManager(cache_manager) - - logger.info(f"✅ Odds Manager initialized") - - # Test NBA odds URL construction (without actual API call) - test_event_id = "401585515" # Sample NBA game ID - expected_url = f"https://sports.core.api.espn.com/v2/sports/basketball/leagues/nba/events/{test_event_id}/competitions/{test_event_id}/odds" - logger.info(f"Expected odds URL: {expected_url}") - - logger.info("✅ Odds Manager integration test PASSED") - return True - - except Exception as e: - logger.error(f"❌ Odds Manager integration test FAILED: {e}") - return False - -def test_configuration_consistency(): - """Test that configurations are consistent across components.""" - try: - with open('config/config.json', 'r') as f: - config = json.load(f) - - # Check NBA scoreboard config - nba_scoreboard = config.get('nba_scoreboard', {}) - nba_enabled = nba_scoreboard.get('enabled', False) - nba_show_odds = nba_scoreboard.get('show_odds', False) - - # Check leaderboard config - leaderboard = config.get('leaderboard', {}) - leaderboard_enabled = leaderboard.get('enabled', False) - nba_leaderboard_enabled = leaderboard.get('enabled_sports', {}).get('nba', {}).get('enabled', False) - - logger.info(f"NBA Scoreboard - Enabled: {nba_enabled}, Show Odds: {nba_show_odds}") - logger.info(f"Leaderboard - Enabled: {leaderboard_enabled}, NBA Enabled: {nba_leaderboard_enabled}") - - # Check for consistency - if not nba_enabled and nba_show_odds: - logger.warning("⚠️ NBA scoreboard disabled but odds enabled - odds won't be used") - - if leaderboard_enabled and not nba_leaderboard_enabled: - logger.info("ℹ️ Leaderboard enabled but NBA disabled - NBA won't appear in leaderboard") - - logger.info("✅ Configuration consistency test PASSED") - return True - - except Exception as e: - logger.error(f"❌ Configuration consistency test FAILED: {e}") - return False - -def main(): - """Run all integration tests.""" - logger.info("🧪 Starting NBA Manager, Leaderboard, and Odds Manager Integration Tests") - logger.info("=" * 70) - - tests = [ - ("NBA API Connectivity", test_nba_api_connectivity), - ("Odds API Connectivity", test_odds_api_connectivity), - ("NBA Manager Initialization", test_nba_manager_initialization), - ("Leaderboard NBA Integration", test_leaderboard_nba_integration), - ("Odds Manager Integration", test_odds_manager_integration), - ("Configuration Consistency", test_configuration_consistency), - ] - - results = [] - for test_name, test_func in tests: - logger.info(f"\n🔍 Running: {test_name}") - try: - result = test_func() - results.append((test_name, result)) - except Exception as e: - logger.error(f"❌ {test_name} crashed: {e}") - results.append((test_name, False)) - - # Summary - logger.info("\n" + "=" * 70) - logger.info("📊 TEST SUMMARY") - logger.info("=" * 70) - - passed = 0 - failed = 0 - - for test_name, result in results: - status = "✅ PASSED" if result else "❌ FAILED" - logger.info(f"{test_name:<25} {status}") - if result: - passed += 1 - else: - failed += 1 - - logger.info("-" * 70) - logger.info(f"Total: {len(results)} | Passed: {passed} | Failed: {failed}") - - if failed == 0: - logger.info("🎉 ALL TESTS PASSED! NBA integration is working correctly.") - return True - else: - logger.error(f"❌ {failed} test(s) failed. Please check the issues above.") - return False - -if __name__ == "__main__": - success = main() - sys.exit(0 if success else 1) diff --git a/test/test_nba_leaderboard_fix.py b/test/test_nba_leaderboard_fix.py deleted file mode 100644 index 81e18078..00000000 --- a/test/test_nba_leaderboard_fix.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python3 -""" -Test script to verify that the NBA leaderboard fix works correctly. -This script simulates the leaderboard manager's data fetching process. -""" -import sys -import os -import logging - -# Add the src directory to Python path so we can import the leaderboard manager -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) - -# Set up logging -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') -logger = logging.getLogger(__name__) - -def test_nba_standings_data(): - """Test that NBA standings data includes team ID fields.""" - try: - from leaderboard_manager import LeaderboardManager - from display_manager import DisplayManager - from cache_manager import CacheManager - import json - - # Load config - with open('config/config.json', 'r') as f: - config = json.load(f) - - # Create mock display and cache managers - display_manager = DisplayManager(config) - cache_manager = CacheManager() - - # Create leaderboard manager - leaderboard_manager = LeaderboardManager(config, display_manager) - - # Test NBA standings fetching - logger.info("Testing NBA standings data fetching...") - nba_config = leaderboard_manager.league_configs['nba'] - nba_config['enabled'] = True # Enable NBA for testing - - standings = leaderboard_manager._fetch_standings(nba_config) - - if not standings: - logger.error("No NBA standings data returned!") - return False - - logger.info(f"Successfully fetched {len(standings)} NBA teams") - - # Check if team ID fields are present - missing_id_count = 0 - for i, team in enumerate(standings[:5]): # Check first 5 teams - team_id = team.get('id') - team_abbr = team.get('abbreviation', 'Unknown') - team_name = team.get('name', 'Unknown') - - logger.info(f"Team {i+1}: ID={team_id}, ABBR={team_abbr}, NAME={team_name}") - - if team_id is None: - logger.error(f"Team {team_abbr} is missing ID field!") - missing_id_count += 1 - - if missing_id_count > 0: - logger.error(f"{missing_id_count} teams are missing ID fields!") - return False - else: - logger.info("All tested teams have ID fields!") - - # Test that we can create a leaderboard image (without actually displaying) - logger.info("Testing leaderboard image creation...") - leaderboard_manager.leaderboard_data = [{ - 'league': 'nba', - 'league_config': nba_config, - 'teams': standings[:3] # Test with first 3 teams - }] - - try: - leaderboard_manager._create_leaderboard_image() - if leaderboard_manager.leaderboard_image: - logger.info(f"Successfully created leaderboard image: {leaderboard_manager.leaderboard_image.width}x{leaderboard_manager.leaderboard_image.height}") - return True - else: - logger.error("Failed to create leaderboard image!") - return False - except Exception as e: - logger.error(f"Error creating leaderboard image: {e}") - return False - - except ImportError as e: - logger.error(f"Import error: {e}") - logger.info("This script needs to be run from the LEDMatrix project directory") - return False - except Exception as e: - logger.error(f"Unexpected error: {e}") - return False - -def main(): - """Main test function.""" - logger.info("Testing NBA leaderboard fix...") - - success = test_nba_standings_data() - - if success: - logger.info("✅ NBA leaderboard fix test PASSED!") - logger.info("The NBA leaderboard should now work correctly with team logos") - else: - logger.error("❌ NBA leaderboard fix test FAILED!") - logger.info("The issue may not be fully resolved") - - return success - -if __name__ == "__main__": - success = main() - sys.exit(0 if success else 1)