Files
kempe-backend/test_rest_api.py
Michael Simard c10fdd594d Add REST API endpoints for team player statistics
Implemented complete REST API to retrieve NHL player statistics for entire teams:

Application Layer:
- Created DTOs for Player, SkaterStats, GoalieStats, and PlayerWithStatsDTO
- Implemented GetTeamPlayerStatsUseCase that orchestrates data retrieval
- Transforms domain entities to API-friendly DTOs

Presentation Layer:
- Created /api/v1/teams/{team_id}/players endpoint (all players)
- Created /api/v1/teams/{team_id}/players/skaters endpoint (skaters only)
- Created /api/v1/teams/{team_id}/players/goalies endpoint (goalies only)
- Integrated routes into main FastAPI application

Features:
- Retrieves complete roster for any NHL team by abbreviation
- Aggregates current season statistics for each player
- Differentiates between skater and goalie statistics
- Proper error handling with 404 for invalid teams
- Follows CLEAN architecture with dependency injection

Documentation:
- Created comprehensive API_GUIDE.md with usage examples
- Includes setup instructions, endpoint documentation
- Python, JavaScript, and cURL examples
- Complete list of NHL team abbreviations

Testing:
- Added test scripts for both direct adapter testing and REST API testing
- Verified functionality with Toronto Maple Leafs data

The REST API is now ready for integration with fantasy hockey analysis tools.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 22:44:39 -06:00

177 lines
5.5 KiB
Python

"""Test script for REST API endpoints."""
import sys
import httpx
import asyncio
from datetime import datetime
# Test base URL
BASE_URL = "http://localhost:8000"
async def test_health_check():
"""Test health check endpoint."""
print("\n" + "=" * 60)
print("TESTING HEALTH CHECK")
print("=" * 60)
async with httpx.AsyncClient() as client:
response = await client.get(f"{BASE_URL}/health")
print(f"Status: {response.status_code}")
print(f"Response: {response.json()}")
async def test_root():
"""Test root endpoint."""
print("\n" + "=" * 60)
print("TESTING ROOT ENDPOINT")
print("=" * 60)
async with httpx.AsyncClient() as client:
response = await client.get(f"{BASE_URL}/")
print(f"Status: {response.status_code}")
data = response.json()
print(f"App Name: {data.get('name')}")
print(f"Version: {data.get('version')}")
print(f"Status: {data.get('status')}")
async def test_team_players():
"""Test getting team players with stats."""
print("\n" + "=" * 60)
print("TESTING TEAM PLAYERS ENDPOINT")
print("=" * 60)
team_id = "TOR"
print(f"\nFetching players for team: {team_id}")
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(f"{BASE_URL}/api/v1/teams/{team_id}/players")
print(f"Status: {response.status_code}")
if response.status_code == 200:
data = response.json()
print(f"Total players: {len(data)}")
# Show first 3 players
print("\nFirst 3 players:")
for player_data in data[:3]:
player = player_data["player"]
stats = player_data["stats"]
stats_type = player_data["stats_type"]
print(f"\n #{player.get('jersey_number', '??')} {player['full_name']}")
print(f" Position: {player['position']}")
if stats_type == "skater" and stats:
print(f" GP: {stats['games_played']}, G: {stats['goals']}, A: {stats['assists']}, P: {stats['points']}")
elif stats_type == "goalie" and stats:
print(f" GP: {stats['games_played']}, W: {stats['wins']}, SV%: {stats['save_percentage']:.3f}")
else:
print(" No stats available")
else:
print(f"Error: {response.text}")
async def test_team_skaters():
"""Test getting team skaters only."""
print("\n" + "=" * 60)
print("TESTING TEAM SKATERS ENDPOINT")
print("=" * 60)
team_id = "TOR"
print(f"\nFetching skaters for team: {team_id}")
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(f"{BASE_URL}/api/v1/teams/{team_id}/players/skaters")
print(f"Status: {response.status_code}")
if response.status_code == 200:
data = response.json()
print(f"Total skaters: {len(data)}")
# Show top 5 scorers
sorted_skaters = sorted(
data,
key=lambda x: x["stats"]["points"] if x["stats"] else 0,
reverse=True,
)
print("\nTop 5 scorers:")
for player_data in sorted_skaters[:5]:
player = player_data["player"]
stats = player_data["stats"]
if stats:
print(f" {player['full_name']}: {stats['points']} pts ({stats['goals']}G, {stats['assists']}A)")
else:
print(f"Error: {response.text}")
async def test_team_goalies():
"""Test getting team goalies only."""
print("\n" + "=" * 60)
print("TESTING TEAM GOALIES ENDPOINT")
print("=" * 60)
team_id = "TOR"
print(f"\nFetching goalies for team: {team_id}")
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(f"{BASE_URL}/api/v1/teams/{team_id}/players/goalies")
print(f"Status: {response.status_code}")
if response.status_code == 200:
data = response.json()
print(f"Total goalies: {len(data)}")
print("\nGoalie stats:")
for player_data in data:
player = player_data["player"]
stats = player_data["stats"]
if stats:
print(f" {player['full_name']}:")
print(f" Record: {stats['wins']}-{stats['losses']}-{stats['overtime_losses']}")
print(f" SV%: {stats['save_percentage']:.3f}, GAA: {stats['goals_against_average']:.2f}")
else:
print(f"Error: {response.text}")
async def main():
"""Run all tests."""
print("\n" + "=" * 60)
print("REST API INTEGRATION TEST")
print(f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"Base URL: {BASE_URL}")
print("=" * 60)
try:
await test_health_check()
await test_root()
await test_team_players()
await test_skaters()
await test_team_goalies()
print("\n" + "=" * 60)
print("ALL TESTS COMPLETED")
print("=" * 60 + "\n")
except httpx.ConnectError:
print("\n✗ ERROR: Cannot connect to server.")
print("Make sure the FastAPI server is running:")
print(" uvicorn src.presentation.api.main:app --reload")
sys.exit(1)
except Exception as e:
print(f"\n✗ ERROR: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
asyncio.run(main())