hale-api / simulate_e2e.py
Raunak211006's picture
Deploy v3.2 to Hugging Face (excluding binaries)
c50a873
Raw
History Blame Contribute Delete
5.69 kB
import os
import sys
import json
from datetime import datetime
# Add app to path
sys.path.insert(0, os.path.abspath('.'))
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.main import app
from app.core.database import Base, get_db
from app.main import limiter
# 1. Setup isolated database
TEST_DB_PATH = "./data/e2e_test.db"
if os.path.exists(TEST_DB_PATH):
try:
os.remove(TEST_DB_PATH)
except:
pass
TEST_DB = f"sqlite:///{TEST_DB_PATH}"
engine = create_engine(TEST_DB, connect_args={"check_same_thread": False})
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base.metadata.create_all(bind=engine)
def override_get_db():
db = TestingSessionLocal()
try:
yield db
finally:
db.close()
from app.core.config import settings
# Force fallback generator to bypass rate limits
settings.GEMINI_API_KEYS = ""
app.dependency_overrides[get_db] = override_get_db
limiter._storage.reset() # Reset rate limits
client = TestClient(app)
print("\n--- Starting HALE E2E Simulation ---\n")
try:
# 2. Register
print("1. Registering new user...")
username = f"test_user_{int(datetime.now().timestamp())}"
res = client.post("/api/auth/register", json={
"user_id": username,
"name": "Bruce Wayne",
"password": "Batman_Password1"
})
assert res.status_code == 201, res.text
token = res.json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}
print(f"User registered: {username}")
# 3. Update Profile
print("\n2. Changing Coach Personality to 'drill_sergeant'...")
res = client.patch("/api/auth/profile", headers=headers, json={
"coach_personality": "drill_sergeant"
})
assert res.status_code == 200, res.text
print(f"Profile updated. Coach is now: {res.json()['coach_personality']}")
# 4. Create Goal
print("\n3. Creating a new goal: 'Learn Neuroscience in 7 days'")
print("... Waiting for AI Curriculum Generator (might take a few seconds)...")
res = client.post("/api/goals/", headers=headers, json={
"goal": "Learn Neuroscience basics",
"category": "education",
"duration_days": 10
})
assert res.status_code == 201, res.text
goal_data = res.json()
print(f"Goal Created! AI generated {len(goal_data['plan']['modules'])} modules.")
print(f" Sample module: {goal_data['plan']['modules'][0]['title']}")
# 5. Get Initial Daily Plan
print("\n4. Fetching today's personalized plan (Normal State)...")
res = client.get("/api/plan", headers=headers)
assert res.status_code == 200, res.text
plan_data = res.json()
print(f"Plan fetched:")
print(f" Topic: {plan_data['topic']}")
print(f" Behavior State: {plan_data['behavior']['action_label']} (Intensity: {plan_data['behavior']['intensity']})")
print(" Tasks:")
for t in plan_data['tasks']:
print(f" - {t}")
print(f" Coach Message (Drill Sergeant): \"{plan_data['coach_message']}\"")
# 6. Update State (Simulate high fatigue / sickness)
print("\n5. Oh no! User is extremely tired and burned out. Updating state...")
res = client.post("/api/update-state", headers=headers, json={
"fatigue": 0.9,
"mood": 0.2,
"stress": 0.8
})
assert res.status_code == 200, res.text
print("State updated successfully.")
# 7. Get Adapted Daily Plan
print("\n6. Fetching daily plan again to check AI adaptation...")
res = client.get("/api/plan", headers=headers)
assert res.status_code == 200, res.text
adapted_plan = res.json()
print(f"Adapted Plan fetched:")
print(f" Behavior State: {adapted_plan['behavior']['action_label']} (Intensity: {adapted_plan['behavior']['intensity']})")
print(" Adapted Tasks:")
for t in adapted_plan['tasks']:
print(f" - {t}")
print(" Notice how the tasks changed dynamically based on fatigue!")
# 8. Complete Task
print("\n7. Completing the tasks...")
today = datetime.today().strftime('%Y-%m-%d')
res = client.post("/api/complete-task", headers=headers, json={
"date": today,
"task_index": 0,
"actual_duration_min": 15,
"notes": "Was tired but pushed through a quick review."
})
assert res.status_code == 200, res.text
print(f"Task Completed! Result: {json.dumps(res.json(), ensure_ascii=True)}")
# 9. Check Complete Gamification Stats
print("\n8. Checking Gamification Stats...")
res = client.get("/api/stats", headers=headers)
assert res.status_code == 200, res.text
stats = res.json()
print("Current Stats:")
print(f" Level: {stats['level']} | XP: {stats['xp']}")
print(f" Current Streak: {stats['current_streak']}")
print(f" Tasks Completed: {stats['total_tasks_completed']}")
# 10. Generate Micro-Lesson
print("\n9. Asking AI to generate a quick lesson on 'Neurons'...")
res = client.get("/api/lesson/Neurons", headers=headers)
assert res.status_code == 200, res.text
print("Lesson generated successfully!")
print(f" Excerpt: {res.json()['content'][:150]}...\n")
print("--- E2E Simulation Completed Successfully! ---")
except Exception as e:
print(f"\nE2E Run Failed! Error:\n{e}")
finally:
# Cleanup DB
try:
if os.path.exists("./data/e2e_test.db"):
# Ensure engine is disposed to release the file handle
engine.dispose()
os.remove("./data/e2e_test.db")
except Exception as cleanup_err:
print(f"Cleanup warning: {cleanup_err}")