1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-07-24 15:49:42 +02:00
mealie/tests/integration_tests/user_household_tests/test_group_mealplan.py

341 lines
13 KiB
Python
Raw Normal View History

import random
from datetime import datetime, timedelta, timezone
from uuid import UUID
from fastapi.testclient import TestClient
from mealie.schema.household.household import HouseholdSummary
from mealie.schema.meal_plan.new_meal import CreatePlanEntry
from mealie.schema.meal_plan.plan_rules import PlanRulesDay, PlanRulesOut, PlanRulesSave, PlanRulesType
from mealie.schema.recipe.recipe import Recipe
from mealie.schema.recipe.recipe_category import CategoryOut, CategorySave, TagOut, TagSave
from tests.utils import api_routes
from tests.utils.factories import random_string
from tests.utils.fixture_schemas import TestUser
def route_all_slice(page: int, perPage: int, start_date: str, end_date: str):
2024-08-22 10:14:32 -05:00
return (
f"{api_routes.households_mealplans}?page={page}&perPage={perPage}&start_date={start_date}&end_date={end_date}"
)
def create_recipe(unique_user: TestUser, tags: list[TagOut] | None = None, categories: list[CategoryOut] | None = None):
return unique_user.repos.recipes.create(
Recipe(
user_id=unique_user.user_id,
group_id=UUID(unique_user.group_id),
name=random_string(),
tags=tags or [],
recipe_category=categories or [],
)
)
def create_rule(
unique_user: TestUser,
day: PlanRulesDay,
entry_type: PlanRulesType,
tags: list[TagOut] | None = None,
categories: list[CategoryOut] | None = None,
households: list[HouseholdSummary] | None = None,
):
qf_parts: list[str] = []
if tags:
qf_parts.append(f'tags.id CONTAINS ALL [{",".join([str(tag.id) for tag in tags])}]')
if categories:
qf_parts.append(f'recipe_category.id CONTAINS ALL [{",".join([str(cat.id) for cat in categories])}]')
if households:
qf_parts.append(f'household_id IN [{",".join([str(household.id) for household in households])}]')
query_filter_string = " AND ".join(qf_parts)
return unique_user.repos.group_meal_plan_rules.create(
PlanRulesSave(
group_id=UUID(unique_user.group_id),
household_id=UUID(unique_user.household_id),
day=day,
entry_type=entry_type,
query_filter_string=query_filter_string,
)
)
def test_create_mealplan_no_recipe(api_client: TestClient, unique_user: TestUser):
title = random_string(length=25)
text = random_string(length=25)
new_plan = CreatePlanEntry(
date=datetime.now(timezone.utc).date(), entry_type="breakfast", title=title, text=text
).model_dump()
new_plan["date"] = datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
2024-08-22 10:14:32 -05:00
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
assert response.status_code == 201
response_json = response.json()
assert response_json["title"] == title
assert response_json["text"] == text
def test_create_mealplan_with_recipe(api_client: TestClient, unique_user: TestUser):
recipe_name = random_string(length=25)
response = api_client.post(api_routes.recipes, json={"name": recipe_name}, headers=unique_user.token)
assert response.status_code == 201
response = api_client.get(api_routes.recipes_slug(recipe_name), headers=unique_user.token)
recipe = response.json()
recipe_id = recipe["id"]
new_plan = CreatePlanEntry(
date=datetime.now(timezone.utc).date(), entry_type="dinner", recipe_id=recipe_id
).model_dump(by_alias=True)
new_plan["date"] = datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
new_plan["recipeId"] = str(recipe_id)
2024-08-22 10:14:32 -05:00
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
response_json = response.json()
assert response.status_code == 201
assert response_json["recipe"]["slug"] == recipe_name
def test_crud_mealplan(api_client: TestClient, unique_user: TestUser):
new_plan = CreatePlanEntry(
date=datetime.now(timezone.utc).date(),
entry_type="breakfast",
title=random_string(),
text=random_string(),
).model_dump()
# Create
new_plan["date"] = datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
2024-08-22 10:14:32 -05:00
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
response_json = response.json()
assert response.status_code == 201
plan_id = response_json["id"]
# Update
response_json["title"] = random_string()
response_json["text"] = random_string()
response = api_client.put(
2024-08-22 10:14:32 -05:00
api_routes.households_mealplans_item_id(plan_id), headers=unique_user.token, json=response_json
)
assert response.status_code == 200
assert response.json()["title"] == response_json["title"]
assert response.json()["text"] == response_json["text"]
# Delete
2024-08-22 10:14:32 -05:00
response = api_client.delete(api_routes.households_mealplans_item_id(plan_id), headers=unique_user.token)
assert response.status_code == 200
2024-08-22 10:14:32 -05:00
response = api_client.get(api_routes.households_mealplans_item_id(plan_id), headers=unique_user.token)
assert response.status_code == 404
def test_get_all_mealplans(api_client: TestClient, unique_user: TestUser):
for _ in range(3):
new_plan = CreatePlanEntry(
date=datetime.now(timezone.utc).date(),
entry_type="breakfast",
title=random_string(),
text=random_string(),
).model_dump()
new_plan["date"] = datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
2024-08-22 10:14:32 -05:00
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
assert response.status_code == 201
2024-08-22 10:14:32 -05:00
response = api_client.get(
api_routes.households_mealplans, headers=unique_user.token, params={"page": 1, "perPage": -1}
)
assert response.status_code == 200
assert len(response.json()["items"]) >= 3
def test_get_slice_mealplans(api_client: TestClient, unique_user: TestUser):
# Make List of 10 dates from now to +10 days
dates = [datetime.now(timezone.utc).date() + timedelta(days=x) for x in range(10)]
# Make a list of 10 meal plans
meal_plans = [
CreatePlanEntry(date=date, entry_type="breakfast", title=random_string(), text=random_string()).model_dump()
for date in dates
]
# Add the meal plans to the database
for meal_plan in meal_plans:
meal_plan["date"] = meal_plan["date"].strftime("%Y-%m-%d")
2024-08-22 10:14:32 -05:00
response = api_client.post(api_routes.households_mealplans, json=meal_plan, headers=unique_user.token)
assert response.status_code == 201
# Get meal slice of meal plans from database
slices = [dates, dates[1:2], dates[2:3], dates[3:4], dates[4:5]]
for date_range in slices:
start_date = date_range[0].strftime("%Y-%m-%d")
end_date = date_range[-1].strftime("%Y-%m-%d")
response = api_client.get(route_all_slice(1, -1, start_date, end_date), headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
for meal_plan in response_json["items"]:
assert meal_plan["date"] in [date.strftime("%Y-%m-%d") for date in date_range]
def test_get_mealplan_today(api_client: TestClient, unique_user: TestUser):
# Create Meal Plans for today
test_meal_plans = [
CreatePlanEntry(
date=datetime.now(timezone.utc).date(), entry_type="breakfast", title=random_string(), text=random_string()
).model_dump()
for _ in range(3)
]
# Add the meal plans to the database
for meal_plan in test_meal_plans:
meal_plan["date"] = meal_plan["date"].strftime("%Y-%m-%d")
2024-08-22 10:14:32 -05:00
response = api_client.post(api_routes.households_mealplans, json=meal_plan, headers=unique_user.token)
assert response.status_code == 201
# Get meal plan for today
2024-08-22 10:14:32 -05:00
response = api_client.get(api_routes.households_mealplans_today, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
for meal_plan in response_json:
assert meal_plan["date"] == datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
def test_get_mealplan_with_rules_categories_and_tags_filter(api_client: TestClient, unique_user: TestUser):
tags = [
unique_user.repos.tags.create(TagSave(name=random_string(), group_id=unique_user.group_id)) for _ in range(4)
]
categories = [
unique_user.repos.categories.create(CategorySave(name=random_string(), group_id=unique_user.group_id))
for _ in range(4)
]
[
create_recipe(unique_user, tags=[tag], categories=[category])
for tag, category in zip(tags, categories, strict=True)
]
[create_recipe(unique_user) for _ in range(5)]
i = random.randint(0, 3)
tag = tags[i]
category = categories[i]
rule = create_rule(
unique_user,
day=PlanRulesDay.saturday,
entry_type=PlanRulesType.breakfast,
tags=[tag],
categories=[category],
)
try:
payload = {"date": "2023-02-25", "entryType": "breakfast"}
response = api_client.post(api_routes.households_mealplans_random, json=payload, headers=unique_user.token)
assert response.status_code == 200
recipe_data = response.json()["recipe"]
assert recipe_data["tags"][0]["name"] == tag.name
assert recipe_data["recipeCategory"][0]["name"] == category.name
finally:
unique_user.repos.group_meal_plan_rules.delete(rule.id)
def test_get_mealplan_with_rules_date_and_type_filter(api_client: TestClient, unique_user: TestUser):
tags = [
unique_user.repos.tags.create(TagSave(name=random_string(), group_id=unique_user.group_id)) for _ in range(4)
]
recipes = [create_recipe(unique_user, tags=[tag]) for tag in tags]
[create_recipe(unique_user) for _ in range(5)]
rules: list[PlanRulesOut] = []
rules.append(
create_rule(unique_user, day=PlanRulesDay.saturday, entry_type=PlanRulesType.breakfast, tags=[tags[0]])
)
rules.append(create_rule(unique_user, day=PlanRulesDay.saturday, entry_type=PlanRulesType.dinner, tags=[tags[1]]))
rules.append(create_rule(unique_user, day=PlanRulesDay.sunday, entry_type=PlanRulesType.breakfast, tags=[tags[2]]))
rules.append(create_rule(unique_user, day=PlanRulesDay.sunday, entry_type=PlanRulesType.dinner, tags=[tags[3]]))
try:
payload = {"date": "2023-02-25", "entryType": "breakfast"}
response = api_client.post(api_routes.households_mealplans_random, json=payload, headers=unique_user.token)
assert response.status_code == 200
assert response.json()["recipe"]["slug"] == recipes[0].slug
finally:
for rule in rules:
unique_user.repos.group_meal_plan_rules.delete(rule.id)
def test_get_mealplan_with_rules_includes_other_households(
api_client: TestClient, unique_user: TestUser, h2_user: TestUser
):
tag = h2_user.repos.tags.create(TagSave(name=random_string(), group_id=h2_user.group_id))
recipe = create_recipe(h2_user, tags=[tag])
rule = create_rule(unique_user, day=PlanRulesDay.saturday, entry_type=PlanRulesType.breakfast, tags=[tag])
try:
payload = {"date": "2023-02-25", "entryType": "breakfast"}
response = api_client.post(api_routes.households_mealplans_random, json=payload, headers=unique_user.token)
assert response.status_code == 200
assert response.json()["recipe"]["slug"] == recipe.slug
finally:
unique_user.repos.group_meal_plan_rules.delete(rule.id)
def test_get_mealplan_with_rules_households_filter(api_client: TestClient, unique_user: TestUser, h2_user: TestUser):
tag = unique_user.repos.tags.create(TagSave(name=random_string(), group_id=unique_user.group_id))
recipe = create_recipe(unique_user, tags=[tag])
[create_recipe(h2_user, tags=[tag]) for _ in range(10)]
household = unique_user.repos.households.get_by_slug_or_id(unique_user.household_id)
assert household
rule = create_rule(
unique_user, day=PlanRulesDay.saturday, entry_type=PlanRulesType.breakfast, tags=[tag], households=[household]
)
try:
payload = {"date": "2023-02-25", "entryType": "breakfast"}
response = api_client.post(api_routes.households_mealplans_random, json=payload, headers=unique_user.token)
assert response.status_code == 200
assert response.json()["recipe"]["slug"] == recipe.slug
finally:
unique_user.repos.group_meal_plan_rules.delete(rule.id)
def test_get_mealplan_with_rules_households_filter_includes_any_households(
api_client: TestClient, unique_user: TestUser, h2_user: TestUser
):
tag = unique_user.repos.tags.create(TagSave(name=random_string(), group_id=unique_user.group_id))
recipe = create_recipe(h2_user, tags=[tag])
household = unique_user.repos.households.get_by_slug_or_id(unique_user.household_id)
assert household
h2_household = unique_user.repos.households.get_by_slug_or_id(h2_user.household_id)
assert h2_household
rule = create_rule(
unique_user,
day=PlanRulesDay.saturday,
entry_type=PlanRulesType.breakfast,
tags=[tag],
households=[household, h2_household],
)
try:
payload = {"date": "2023-02-25", "entryType": "breakfast"}
response = api_client.post(api_routes.households_mealplans_random, json=payload, headers=unique_user.token)
assert response.status_code == 200
assert response.json()["recipe"]["slug"] == recipe.slug
finally:
unique_user.repos.group_meal_plan_rules.delete(rule.id)