84 lines
3.0 KiB
Python
84 lines
3.0 KiB
Python
import unittest
|
|
from datetime import date, datetime, time, timedelta, timezone
|
|
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import Session, sessionmaker
|
|
|
|
from app.db.models import Base, FitnessProfile, FoodLog, User, WorkoutLog
|
|
from app.fitness.gamification import _plan_hit, build_gamification
|
|
|
|
|
|
class GamificationTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.engine = create_engine("sqlite:///:memory:")
|
|
Base.metadata.create_all(self.engine)
|
|
self.Session = sessionmaker(bind=self.engine)
|
|
with Session(self.engine) as db:
|
|
user = User(username="g1", api_token_hash="x")
|
|
db.add(user)
|
|
db.commit()
|
|
self.user_id = user.id
|
|
db.add(
|
|
FitnessProfile(
|
|
user_id=self.user_id,
|
|
goal="lose",
|
|
weekly_workouts=3,
|
|
calorie_target=2000,
|
|
)
|
|
)
|
|
db.commit()
|
|
|
|
def test_plan_hit_lose_goal(self) -> None:
|
|
summary = {
|
|
"meals": [{"id": 1}],
|
|
"totals": {"calories": 1900},
|
|
"targets": {"calories": 2000},
|
|
}
|
|
self.assertTrue(_plan_hit(summary, "lose"))
|
|
summary["totals"]["calories"] = 2200
|
|
self.assertFalse(_plan_hit(summary, "lose"))
|
|
|
|
def test_meal_streak_and_medals(self) -> None:
|
|
d1 = date(2026, 6, 16)
|
|
d2 = date(2026, 6, 17)
|
|
d3 = date(2026, 6, 18)
|
|
with Session(self.engine) as db:
|
|
for d in (d1, d2, d3):
|
|
db.add(
|
|
FoodLog(
|
|
user_id=self.user_id,
|
|
description="meal",
|
|
calories=1800,
|
|
logged_at=datetime.combine(d, time(12), tzinfo=timezone.utc),
|
|
)
|
|
)
|
|
db.commit()
|
|
result = build_gamification(db, self.user_id, end_day=d3)
|
|
|
|
self.assertEqual(result["streaks"]["meal_log"], 3)
|
|
meal_medal = next(m for m in result["medals"] if m["id"] == "meal_streak_3")
|
|
self.assertTrue(meal_medal["earned"])
|
|
|
|
def test_workout_week_goal_uses_profile(self) -> None:
|
|
d = date(2026, 6, 18)
|
|
with Session(self.engine) as db:
|
|
for i in range(3):
|
|
db.add(
|
|
WorkoutLog(
|
|
user_id=self.user_id,
|
|
title=f"w{i}",
|
|
duration_min=30,
|
|
logged_at=datetime.combine(
|
|
d - timedelta(days=i),
|
|
time(10),
|
|
tzinfo=timezone.utc,
|
|
),
|
|
)
|
|
)
|
|
db.commit()
|
|
result = build_gamification(db, self.user_id, end_day=d)
|
|
|
|
medal = next(m for m in result["medals"] if m["id"] == "workout_week_goal")
|
|
self.assertTrue(medal["earned"])
|
|
self.assertEqual(result["workouts"]["weekly_target"], 3)
|