""" Tests for public API endpoints. This module tests the public API endpoints for predictions and matches. """ import pytest from fastapi.testclient import TestClient from sqlalchemy.orm import Session from app.main import app from app.database import get_db from app.models.prediction import Prediction from app.models.match import Match from datetime import datetime client = TestClient(app) @pytest.fixture def sample_match(db: Session): """Create a sample match for testing.""" match = Match( home_team="PSG", away_team="Olympique de Marseille", date=datetime.utcnow(), league="Ligue 1", status="scheduled" ) db.add(match) db.commit() db.refresh(match) return match @pytest.fixture def sample_prediction(db: Session, sample_match: Match): """Create a sample prediction for testing.""" prediction = Prediction( match_id=sample_match.id, energy_score="high", confidence="70.5%", predicted_winner="PSG", created_at=datetime.utcnow() ) db.add(prediction) db.commit() db.refresh(prediction) return prediction class TestPublicPredictionsEndpoint: """Tests for GET /api/public/v1/predictions endpoint.""" def test_get_public_predictions_success(self, sample_prediction: Prediction): """Test successful retrieval of public predictions.""" response = client.get("/api/public/v1/predictions") assert response.status_code == 200 data = response.json() assert "data" in data assert "meta" in data assert isinstance(data["data"], list) assert len(data["data"]) > 0 assert data["meta"]["version"] == "v1" def test_get_public_predictions_with_limit(self, sample_prediction: Prediction): """Test retrieval of public predictions with limit parameter.""" response = client.get("/api/public/v1/predictions?limit=5") assert response.status_code == 200 data = response.json() assert "data" in data assert "meta" in data assert data["meta"]["limit"] == 5 def test_get_public_predictions_data_structure(self, sample_prediction: Prediction): """Test that public predictions have correct structure without sensitive data.""" response = client.get("/api/public/v1/predictions") assert response.status_code == 200 data = response.json() prediction = data["data"][0] # Required fields assert "id" in prediction assert "match" in prediction assert "energy_score" in prediction assert "confidence" in prediction assert "predicted_winner" in prediction # Match details match = prediction["match"] assert "id" in match assert "home_team" in match assert "away_team" in match assert "date" in match assert "league" in match assert "status" in match def test_get_public_predictions_empty_database(self): """Test retrieval when no predictions exist.""" # Clear database for this test response = client.get("/api/public/v1/predictions") assert response.status_code == 200 data = response.json() assert "data" in data assert isinstance(data["data"], list) class TestPublicMatchesEndpoint: """Tests for GET /api/public/v1/matches endpoint.""" def test_get_public_matches_success(self, sample_match: Match): """Test successful retrieval of public matches.""" response = client.get("/api/public/v1/matches") assert response.status_code == 200 data = response.json() assert "data" in data assert "meta" in data assert isinstance(data["data"], list) assert len(data["data"]) > 0 assert data["meta"]["version"] == "v1" def test_get_public_matches_with_filters(self, sample_match: Match): """Test retrieval of public matches with league filter.""" response = client.get(f"/api/public/v1/matches?league=Ligue%201") assert response.status_code == 200 data = response.json() assert "data" in data assert "meta" in data def test_get_public_matches_data_structure(self, sample_match: Match): """Test that public matches have correct structure.""" response = client.get("/api/public/v1/matches") assert response.status_code == 200 data = response.json() match = data["data"][0] # Required fields (public only, no sensitive data) assert "id" in match assert "home_team" in match assert "away_team" in match assert "date" in match assert "league" in match assert "status" in match def test_get_public_matches_empty_database(self): """Test retrieval when no matches exist.""" response = client.get("/api/public/v1/matches") assert response.status_code == 200 data = response.json() assert "data" in data assert isinstance(data["data"], list) class TestPublicApiResponseFormat: """Tests for standardized API response format.""" def test_response_format_success(self, sample_prediction: Prediction): """Test that successful responses follow {data, meta} format.""" response = client.get("/api/public/v1/predictions") assert response.status_code == 200 data = response.json() assert "data" in data assert "meta" in data assert "timestamp" in data["meta"] assert "version" in data["meta"] def test_response_meta_timestamp_format(self, sample_prediction: Prediction): """Test that timestamp is in ISO 8601 format.""" response = client.get("/api/public/v1/predictions") assert response.status_code == 200 data = response.json() timestamp = data["meta"]["timestamp"] # ISO 8601 format check (simplified) assert "T" in timestamp assert "Z" in timestamp