File size: 3,447 Bytes
5b1bd9c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
from fastapi.testclient import TestClient

from app.api import roadmap_routes
from app.main import app
from app.schemas.roadmap_schema import RoadmapResponse
from app.services.roadmap_service import RoadmapServiceFailure, RoadmapServiceSuccess


client = TestClient(app)


def test_health_endpoint() -> None:
    response = client.get("/health")
    assert response.status_code == 200
    assert response.json() == {"status": "healthy"}


def test_api_health_endpoint() -> None:
    response = client.get("/api/health")
    assert response.status_code == 200
    body = response.json()
    assert body["status"] == "healthy"
    assert "supabase_enabled" in body


def test_generate_endpoint_success_envelope() -> None:
    class FakeService:
        async def generate(self, _request):
            data = RoadmapResponse.model_validate(
                {
                    "goal": "Machine Learning",
                    "duration_days": 7,
                    "milestones": [{"title": "Kickoff", "start_day": 1, "end_day": 7}],
                    "first_week_plan": {
                        1: [{"title": "Install Python", "duration_minutes": 60}],
                        2: [{"title": "Learn syntax", "duration_minutes": 60}],
                        3: [{"title": "Practice loops", "duration_minutes": 60}],
                        4: [{"title": "Functions intro", "duration_minutes": 60}],
                        5: [{"title": "Data types", "duration_minutes": 60}],
                        6: [{"title": "Simple exercise", "duration_minutes": 60}],
                        7: [{"title": "Mini project", "duration_minutes": 90}],
                    },
                }
            )
            return RoadmapServiceSuccess(data=data)

    class FakeStore:
        async def save(self, _request, _roadmap):
            return True

        def health(self):
            return {"supabase_enabled": False}

    app.dependency_overrides[roadmap_routes.get_service] = lambda: FakeService()
    app.dependency_overrides[roadmap_routes.get_store] = lambda: FakeStore()

    response = client.post(
        "/api/generate",
        json={
            "goal": "Machine Learning",
            "duration_days": 7,
            "daily_minutes": 120,
            "level": "beginner",
        },
    )

    app.dependency_overrides.clear()

    assert response.status_code == 200
    body = response.json()
    assert body["ok"] is True
    assert "data" in body
    assert body["data"]["goal"] == "Machine Learning"


def test_generate_endpoint_failure_envelope() -> None:
    class FakeService:
        async def generate(self, _request):
            return RoadmapServiceFailure(reason="Gemini request timed out")

    class FakeStore:
        async def save(self, _request, _roadmap):
            return True

        def health(self):
            return {"supabase_enabled": False}

    app.dependency_overrides[roadmap_routes.get_service] = lambda: FakeService()
    app.dependency_overrides[roadmap_routes.get_store] = lambda: FakeStore()

    response = client.post(
        "/api/generate",
        json={
            "goal": "Machine Learning",
            "duration_days": 7,
            "daily_minutes": 120,
            "level": "beginner",
        },
    )

    app.dependency_overrides.clear()

    assert response.status_code == 200
    body = response.json()
    assert body == {"ok": False, "reason": "Gemini request timed out"}