Files
Meal-Planner/backend/tests/test_planner_generate.py

90 lines
3.2 KiB
Python

from datetime import date
from decimal import Decimal
from uuid import UUID, uuid4
import pytest
pytestmark = pytest.mark.requires_postgres
def test_generate_meal_plan_against_seeded_data():
"""Smoke test: with the seeded 30 recipes and a seeded grocery scrape,
generate produces a MealPlan with up to 3 items.
"""
from datetime import datetime, timezone
from app.database import SessionLocal
from app.models import (
FamilyProfile,
GroceryItem,
Ingredient,
IngredientGroceryMatch,
IngredientMatchSource,
MealPlan,
MealPlanItem,
)
from app.services.matcher import run_match_job
from app.services.planner.generate import generate_meal_plan
setup = SessionLocal()
try:
family = FamilyProfile(
id=uuid4(),
name="Generate Smoke Family",
household_size=4,
adult_count=2,
child_count=2,
calorie_target=500,
)
setup.add(family)
setup.commit()
family_id = family.id
# Seed at least one grocery_item per ingredient that the recipes use
# so cost matching can find prices. Pick a handful to keep runtime low.
for ing in setup.query(Ingredient).limit(20).all():
setup.add(
GroceryItem(
id=uuid4(),
name=ing.name,
source="lucky_california",
external_id=f"ext-test-{ing.id}",
current_price=Decimal("3.99"),
regular_price=Decimal("4.99"),
is_on_sale=True,
scraped_at=datetime.now(timezone.utc),
)
)
setup.commit()
finally:
setup.close()
work = SessionLocal()
try:
run_match_job(work)
result = generate_meal_plan(work, family_id=family_id, week_start_date=date(2026, 5, 11))
assert result.meal_plan_id is not None
assert 1 <= len(result.selected) <= 3 # at least 1, at most 3
plan = work.query(MealPlan).filter(MealPlan.id == result.meal_plan_id).first()
assert plan is not None
items = work.query(MealPlanItem).filter(MealPlanItem.meal_plan_id == plan.id).all()
assert len(items) == len(result.selected)
finally:
cleanup = SessionLocal()
try:
cleanup.query(MealPlanItem).filter(
MealPlanItem.meal_plan_id.in_(
[r[0] for r in cleanup.query(MealPlan.id).filter(MealPlan.family_profile_id == family_id).all()]
)
).delete(synchronize_session=False)
cleanup.query(MealPlan).filter(MealPlan.family_profile_id == family_id).delete(synchronize_session=False)
cleanup.query(FamilyProfile).filter(FamilyProfile.id == family_id).delete(synchronize_session=False)
cleanup.query(GroceryItem).filter(GroceryItem.external_id.like("ext-test-%")).delete(synchronize_session=False)
cleanup.query(IngredientGroceryMatch).filter(
IngredientGroceryMatch.source == IngredientMatchSource.AUTO
).delete(synchronize_session=False)
cleanup.commit()
finally:
cleanup.close()
work.close()