1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-08-02 20:15:24 +02:00

feat: Add Households to Mealie (#3970)

This commit is contained in:
Michael Genson 2024-08-22 10:14:32 -05:00 committed by GitHub
parent 0c29cef17d
commit eb170cc7e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
315 changed files with 6975 additions and 3577 deletions

View file

@ -1,11 +1,14 @@
from mealie.repos.repository_factory import AllRepositories
from uuid import UUID
from mealie.schema.recipe.recipe import Recipe
from mealie.schema.recipe.recipe_ingredient import RecipeIngredient, SaveIngredientFood
from tests.utils.factories import random_string
from tests.utils.fixture_schemas import TestUser
def test_food_merger(database: AllRepositories, unique_user: TestUser):
def test_food_merger(unique_user: TestUser):
recipe: Recipe | None = None
database = unique_user.repos
slug1 = random_string(10)
food_1 = database.ingredient_foods.create(
@ -25,8 +28,8 @@ def test_food_merger(database: AllRepositories, unique_user: TestUser):
recipe = database.recipes.create(
Recipe(
name=slug1,
user_id=unique_user.group_id,
group_id=unique_user.group_id,
user_id=unique_user.user_id,
group_id=UUID(unique_user.group_id),
recipe_ingredient=[
RecipeIngredient(note="", food=food_1), # type: ignore
RecipeIngredient(note="", food=food_2), # type: ignore
@ -43,6 +46,7 @@ def test_food_merger(database: AllRepositories, unique_user: TestUser):
database.ingredient_foods.merge(food_2.id, food_1.id)
recipe = database.recipes.get_one(recipe.slug)
assert recipe
for ingredient in recipe.recipe_ingredient:
assert ingredient.food.id == food_1.id # type: ignore

View file

@ -4,9 +4,9 @@ from mealie.repos.repository_factory import AllRepositories
from tests.utils.factories import random_int, random_string
def test_create_group_resolve_similar_names(database: AllRepositories):
def test_create_group_resolve_similar_names(unfiltered_database: AllRepositories):
base_group_name = random_string()
groups = database.groups.create_many({"name": base_group_name} for _ in range(random_int(3, 10)))
groups = unfiltered_database.groups.create_many({"name": base_group_name} for _ in range(random_int(3, 10)))
seen_names = set()
seen_slugs = set()
@ -19,17 +19,17 @@ def test_create_group_resolve_similar_names(database: AllRepositories):
assert base_group_name in group.name
def test_group_get_by_slug_or_id(database: AllRepositories):
groups = [database.groups.create({"name": random_string()}) for _ in range(random_int(3, 10))]
def test_group_get_by_slug_or_id(unfiltered_database: AllRepositories):
groups = [unfiltered_database.groups.create({"name": random_string()}) for _ in range(random_int(3, 10))]
for group in groups:
assert database.groups.get_by_slug_or_id(group.id) == group
assert database.groups.get_by_slug_or_id(group.slug) == group
assert unfiltered_database.groups.get_by_slug_or_id(group.id) == group
assert unfiltered_database.groups.get_by_slug_or_id(group.slug) == group
def test_update_group_updates_slug(database: AllRepositories):
group = database.groups.create({"name": random_string()})
def test_update_group_updates_slug(unfiltered_database: AllRepositories):
group = unfiltered_database.groups.create({"name": random_string()})
assert group.slug == slugify(group.name)
new_name = random_string()
group = database.groups.update(group.id, {"name": new_name})
group = unfiltered_database.groups.update(group.id, {"name": new_name})
assert group.slug == slugify(new_name)

View file

@ -12,7 +12,7 @@ from pydantic import UUID4
from mealie.repos.repository_factory import AllRepositories
from mealie.repos.repository_units import RepositoryUnit
from mealie.schema.group.group_shopping_list import (
from mealie.schema.household.group_shopping_list import (
ShoppingListItemCreate,
ShoppingListMultiPurposeLabelCreate,
ShoppingListMultiPurposeLabelOut,
@ -64,14 +64,15 @@ def get_label_position_from_label_id(label_id: UUID4, label_settings: list[Shopp
raise Exception("Something went wrong when parsing label settings")
def test_repository_pagination(database: AllRepositories, unique_user: TestUser):
def test_repository_pagination(unique_user: TestUser):
database = unique_user.repos
group = database.groups.get_one(unique_user.group_id)
assert group
seeder = SeederService(database, None, group) # type: ignore
seeder = SeederService(AllRepositories(database.session, group_id=group.id))
seeder.seed_foods("en-US")
foods_repo = database.ingredient_foods.by_group(unique_user.group_id) # type: ignore
foods_repo = database.ingredient_foods
query = PaginationQuery(
page=1,
@ -99,14 +100,15 @@ def test_repository_pagination(database: AllRepositories, unique_user: TestUser)
assert result.id not in seen
def test_pagination_response_and_metadata(database: AllRepositories, unique_user: TestUser):
def test_pagination_response_and_metadata(unique_user: TestUser):
database = unique_user.repos
group = database.groups.get_one(unique_user.group_id)
assert group
seeder = SeederService(database, None, group) # type: ignore
seeder = SeederService(AllRepositories(database.session, group_id=group.id))
seeder.seed_foods("en-US")
foods_repo = database.ingredient_foods.by_group(unique_user.group_id) # type: ignore
foods_repo = database.ingredient_foods
# this should get all results
query = PaginationQuery(
@ -128,14 +130,15 @@ def test_pagination_response_and_metadata(database: AllRepositories, unique_user
assert last_page_of_results.items[-1] == all_results.items[-1]
def test_pagination_guides(database: AllRepositories, unique_user: TestUser):
def test_pagination_guides(unique_user: TestUser):
database = unique_user.repos
group = database.groups.get_one(unique_user.group_id)
assert group
seeder = SeederService(database, None, group) # type: ignore
seeder = SeederService(AllRepositories(database.session, group_id=group.id))
seeder.seed_foods("en-US")
foods_repo = database.ingredient_foods.by_group(unique_user.group_id) # type: ignore
foods_repo = database.ingredient_foods
foods_route = (
"/foods" # this doesn't actually have to be accurate, it's just a placeholder to test for query params
)
@ -173,7 +176,8 @@ def test_pagination_guides(database: AllRepositories, unique_user: TestUser):
@pytest.fixture(scope="function")
def query_units(database: AllRepositories, unique_user: TestUser):
def query_units(unique_user: TestUser):
database = unique_user.repos
unit_1 = database.ingredient_units.create(
SaveIngredientUnit(name="test unit 1", group_id=unique_user.group_id, use_abbreviation=True)
)
@ -193,7 +197,7 @@ def query_units(database: AllRepositories, unique_user: TestUser):
)
unit_ids = [unit.id for unit in [unit_1, unit_2, unit_3]]
units_repo = database.ingredient_units.by_group(unique_user.group_id) # type: ignore
units_repo = database.ingredient_units
yield units_repo, unit_1, unit_2, unit_3
@ -211,7 +215,8 @@ def test_pagination_filter_basic(query_units: tuple[RepositoryUnit, IngredientUn
assert unit_results[0].id == unit_2.id
def test_pagination_filter_null(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_null(unique_user: TestUser):
database = unique_user.repos
recipe_not_made_1 = database.recipes.create(
Recipe(
user_id=unique_user.user_id,
@ -237,7 +242,7 @@ def test_pagination_filter_null(database: AllRepositories, unique_user: TestUser
)
)
recipe_repo = database.recipes.by_group(unique_user.group_id) # type: ignore
recipe_repo = database.recipes
query = PaginationQuery(page=1, per_page=-1, query_filter="lastMade IS NONE")
recipe_results = recipe_repo.page_all(query).items
@ -300,7 +305,8 @@ def test_pagination_filter_in(query_units: tuple[RepositoryUnit, IngredientUnit,
assert unit_3.id in result_ids
def test_pagination_filter_in_advanced(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_in_advanced(unique_user: TestUser):
database = unique_user.repos
slug1, slug2 = (random_string(10) for _ in range(2))
tags = [
@ -418,7 +424,8 @@ def test_pagination_filter_like(query_units: tuple[RepositoryUnit, IngredientUni
assert unit_3.id in result_ids
def test_pagination_filter_keyword_namespace_conflict(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_keyword_namespace_conflict(unique_user: TestUser):
database = unique_user.repos
recipe_rating_1 = database.recipes.create(
Recipe(
user_id=unique_user.user_id,
@ -445,7 +452,7 @@ def test_pagination_filter_keyword_namespace_conflict(database: AllRepositories,
)
)
recipe_repo = database.recipes.by_group(unique_user.group_id) # type: ignore
recipe_repo = database.recipes
# "rating" contains the word "in", but we should not parse this as the keyword "IN"
query = PaginationQuery(page=1, per_page=-1, query_filter="rating > 2")
@ -467,7 +474,8 @@ def test_pagination_filter_keyword_namespace_conflict(database: AllRepositories,
assert recipe_rating_3.id in result_ids
def test_pagination_filter_logical_namespace_conflict(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_logical_namespace_conflict(unique_user: TestUser):
database = unique_user.repos
categories = [
CategorySave(group_id=unique_user.group_id, name=random_string(10)),
CategorySave(group_id=unique_user.group_id, name=random_string(10)),
@ -509,7 +517,7 @@ def test_pagination_filter_logical_namespace_conflict(database: AllRepositories,
# "recipeCategory" has the substring "or" in it, which shouldn't break queries
query = PaginationQuery(page=1, per_page=-1, query_filter=f'recipeCategory.id = "{category_1.id}"')
recipe_results = database.recipes.by_group(unique_user.group_id).page_all(query).items # type: ignore
recipe_results = database.recipes.page_all(query).items
assert len(recipe_results) == 1
recipe_ids = {recipe.id for recipe in recipe_results}
assert recipe_category_0.id not in recipe_ids
@ -616,9 +624,8 @@ def test_pagination_filter_datetimes(
[OrderDirection.asc, OrderDirection.desc],
ids=["ascending", "descending"],
)
def test_pagination_order_by_multiple(
database: AllRepositories, unique_user: TestUser, order_direction: OrderDirection
):
def test_pagination_order_by_multiple(unique_user: TestUser, order_direction: OrderDirection):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
alphabet = ["a", "b", "c", "d", "e"]
@ -676,11 +683,9 @@ def test_pagination_order_by_multiple(
],
)
def test_pagination_order_by_multiple_directions(
database: AllRepositories,
unique_user: TestUser,
order_by_str: str,
order_direction: OrderDirection,
unique_user: TestUser, order_by_str: str, order_direction: OrderDirection
):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
alphabet = ["a", "b", "c", "d", "e"]
@ -726,9 +731,8 @@ def test_pagination_order_by_multiple_directions(
[OrderDirection.asc, OrderDirection.desc],
ids=["order_ascending", "order_descending"],
)
def test_pagination_order_by_nested_model(
database: AllRepositories, unique_user: TestUser, order_direction: OrderDirection
):
def test_pagination_order_by_nested_model(unique_user: TestUser, order_direction: OrderDirection):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
alphabet = ["a", "b", "c", "d", "e"]
@ -758,7 +762,8 @@ def test_pagination_order_by_nested_model(
assert query.items == sorted_foods
def test_pagination_order_by_doesnt_filter(database: AllRepositories, unique_user: TestUser):
def test_pagination_order_by_doesnt_filter(unique_user: TestUser):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
label = database.group_multi_purpose_labels.create(
@ -771,7 +776,7 @@ def test_pagination_order_by_doesnt_filter(database: AllRepositories, unique_use
SaveIngredientFood(name=random_string(), group_id=unique_user.group_id)
)
query = database.ingredient_foods.by_group(unique_user.group_id).page_all(
query = database.ingredient_foods.page_all(
PaginationQuery(
per_page=-1,
query_filter=f"created_at>{current_time.isoformat()}",
@ -800,11 +805,9 @@ def test_pagination_order_by_doesnt_filter(database: AllRepositories, unique_use
],
)
def test_pagination_order_by_nulls(
database: AllRepositories,
unique_user: TestUser,
null_position: OrderByNullPosition,
order_direction: OrderDirection,
unique_user: TestUser, null_position: OrderByNullPosition, order_direction: OrderDirection
):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
label = database.group_multi_purpose_labels.create(
@ -836,7 +839,9 @@ def test_pagination_order_by_nulls(
assert query.items[1] == food_without_label
def test_pagination_shopping_list_items_with_labels(database: AllRepositories, unique_user: TestUser):
def test_pagination_shopping_list_items_with_labels(unique_user: TestUser):
database = unique_user.repos
# create a shopping list and populate it with some items with labels, and some without labels
shopping_list = database.group_shopping_lists.create(
ShoppingListSave(
@ -926,7 +931,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
for mealplan_to_create in [mealplan_today, mealplan_tomorrow]:
data = mealplan_to_create.model_dump()
data["date"] = data["date"].strftime("%Y-%m-%d")
response = api_client.post(api_routes.groups_mealplans, json=data, headers=unique_user.token)
response = api_client.post(api_routes.households_mealplans, json=data, headers=unique_user.token)
assert response.status_code == 201
## Yesterday
@ -935,7 +940,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date >= {yesterday.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -949,7 +954,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date > {yesterday.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -964,7 +969,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date >= {today.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -978,7 +983,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date > {today.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -993,7 +998,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date >= {tomorrow.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -1007,7 +1012,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date > {tomorrow.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -1019,7 +1024,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date >= {day_after_tomorrow.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
assert len(response_json["items"]) == 0
@ -1029,7 +1034,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date > {day_after_tomorrow.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
assert len(response_json["items"]) == 0
@ -1072,7 +1077,8 @@ def test_pagination_filter_advanced(query_units: tuple[RepositoryUnit, Ingredien
assert unit_3.id not in result_ids
def test_pagination_filter_advanced_frontend_sort(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_advanced_frontend_sort(unique_user: TestUser):
database = unique_user.repos
categories = [
CategorySave(group_id=unique_user.group_id, name=random_string(10)),
CategorySave(group_id=unique_user.group_id, name=random_string(10)),
@ -1174,7 +1180,7 @@ def test_pagination_filter_advanced_frontend_sort(database: AllRepositories, uni
)
)
repo = database.recipes.by_group(unique_user.group_id) # type: ignore
repo = database.recipes
qf = f'recipeCategory.id IN ["{category_1.id}"] AND tools.id IN ["{tool_1.id}"]'
query = PaginationQuery(page=1, per_page=-1, query_filter=qf)

View file

@ -3,9 +3,12 @@ from typing import cast
from uuid import UUID
import pytest
from sqlalchemy.orm import Session
from mealie.repos.all_repositories import get_repositories
from mealie.repos.repository_factory import AllRepositories
from mealie.repos.repository_recipes import RepositoryRecipes
from mealie.schema.household.household import HouseholdCreate
from mealie.schema.recipe import RecipeIngredient, SaveIngredientFood
from mealie.schema.recipe.recipe import Recipe, RecipeCategory, RecipeSummary
from mealie.schema.recipe.recipe_category import CategoryOut, CategorySave, TagSave
@ -17,18 +20,34 @@ from tests.utils.fixture_schemas import TestUser
@pytest.fixture()
def unique_local_group_id(database: AllRepositories) -> str:
return str(database.groups.create(GroupBase(name=random_string())).id)
def unique_local_group_id(unfiltered_database: AllRepositories) -> str:
return str(unfiltered_database.groups.create(GroupBase(name=random_string())).id)
@pytest.fixture()
def unique_local_user_id(database: AllRepositories, unique_local_group_id: str) -> str:
def unique_local_household_id(unfiltered_database: AllRepositories, unique_local_group_id: str) -> str:
database = get_repositories(unfiltered_database.session, group_id=UUID(unique_local_group_id), household_id=None)
return str(
database.households.create(HouseholdCreate(group_id=UUID(unique_local_group_id), name=random_string())).id
)
@pytest.fixture()
def unique_local_user_id(
unfiltered_database: AllRepositories, unique_local_group_id: str, unique_local_household_id: str
) -> str:
database = get_repositories(
unfiltered_database.session, group_id=UUID(unique_local_group_id), household_id=UUID(unique_local_household_id)
)
group = database.groups.get_one(unique_local_group_id)
household = database.households.get_one(unique_local_household_id)
return str(
database.users.create(
{
"username": random_string(),
"email": random_email(),
"group_id": unique_local_group_id,
"group": group.name,
"household": household.name,
"full_name": random_string(),
"password": random_string(),
"admin": False,
@ -38,11 +57,25 @@ def unique_local_user_id(database: AllRepositories, unique_local_group_id: str)
@pytest.fixture()
def search_recipes(database: AllRepositories, unique_local_group_id: str, unique_local_user_id: str) -> list[Recipe]:
def unique_ids(
unique_local_group_id: str, unique_local_household_id: str, unique_local_user_id: str
) -> tuple[str, str, str]:
return unique_local_group_id, unique_local_household_id, unique_local_user_id
@pytest.fixture()
def unique_db(session: Session, unique_ids: tuple[str, str, str]):
group_id, household_id, _ = unique_ids
return get_repositories(session, group_id=group_id, household_id=household_id)
@pytest.fixture()
def search_recipes(unique_db: AllRepositories, unique_ids: tuple[str, str, str]) -> list[Recipe]:
group_id, _, user_id = unique_ids
recipes = [
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name="Steinbock Sloop",
description="My favorite horns are delicious",
recipe_ingredient=[
@ -50,61 +83,63 @@ def search_recipes(database: AllRepositories, unique_local_group_id: str, unique
],
),
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name="Fiddlehead Fern Stir Fry",
recipe_ingredient=[
RecipeIngredient(note="moss"),
],
),
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name="Animal Sloop",
),
# Test diacritics
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name="Rátàtôuile",
),
# Add a bunch of recipes for stable randomization
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name=f"{random_string(10)} soup",
),
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name=f"{random_string(10)} soup",
),
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name=f"{random_string(10)} soup",
),
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name=f"{random_string(10)} soup",
),
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name=f"{random_string(10)} soup",
),
Recipe(
user_id=unique_local_user_id,
group_id=unique_local_group_id,
group_id=group_id,
user_id=user_id,
name=f"{random_string(10)} soup",
),
]
return database.recipes.create_many(recipes)
return unique_db.recipes.create_many(recipes)
def test_recipe_repo_get_by_categories_basic(database: AllRepositories, unique_user: TestUser):
def test_recipe_repo_get_by_categories_basic(unique_user: TestUser):
database = unique_user.repos
# Bootstrap the database with categories
slug1, slug2, slug3 = (random_string(10) for _ in range(3))
@ -149,12 +184,13 @@ def test_recipe_repo_get_by_categories_basic(database: AllRepositories, unique_u
# Get all recipes by category
for category in created_categories:
repo: RepositoryRecipes = database.recipes.by_group(unique_user.group_id) # type: ignore
repo: RepositoryRecipes = database.recipes
recipes = repo.get_by_categories([cast(RecipeCategory, category)])
assert len(recipes) == 5
for recipe in recipes:
assert recipe.recipe_category is not None
found_cat = recipe.recipe_category[0]
assert found_cat.name == category.name
@ -162,7 +198,8 @@ def test_recipe_repo_get_by_categories_basic(database: AllRepositories, unique_u
assert found_cat.id == category.id
def test_recipe_repo_get_by_categories_multi(database: AllRepositories, unique_user: TestUser):
def test_recipe_repo_get_by_categories_multi(unique_user: TestUser):
database = unique_user.repos
slug1, slug2 = (random_string(10) for _ in range(2))
categories = [
@ -204,16 +241,18 @@ def test_recipe_repo_get_by_categories_multi(database: AllRepositories, unique_u
database.recipes.create(recipe)
# Get all recipes by both categories
repo: RepositoryRecipes = database.recipes.by_group(unique_local_group_id) # type: ignore
repo: RepositoryRecipes = database.recipes
by_category = repo.get_by_categories(cast(list[RecipeCategory], created_categories))
assert len(by_category) == 10
for recipe_summary in by_category:
assert recipe_summary.recipe_category is not None
for recipe_category in recipe_summary.recipe_category:
assert recipe_category.id in known_category_ids
def test_recipe_repo_pagination_by_categories(database: AllRepositories, unique_user: TestUser):
def test_recipe_repo_pagination_by_categories(unique_user: TestUser):
database = unique_user.repos
slug1, slug2 = (random_string(10) for _ in range(2))
categories = [
@ -270,6 +309,7 @@ def test_recipe_repo_pagination_by_categories(database: AllRepositories, unique_
assert len(recipes_with_one_category) == 15
for recipe_summary in recipes_with_one_category:
assert recipe_summary.recipe_category is not None
category_ids = [category.id for category in recipe_summary.recipe_category]
assert category_id in category_ids
@ -279,6 +319,7 @@ def test_recipe_repo_pagination_by_categories(database: AllRepositories, unique_
assert len(recipes_with_one_category) == 15
for recipe_summary in recipes_with_one_category:
assert recipe_summary.recipe_category is not None
category_slugs = [category.slug for category in recipe_summary.recipe_category]
assert category_slug in category_slugs
@ -289,6 +330,7 @@ def test_recipe_repo_pagination_by_categories(database: AllRepositories, unique_
assert len(recipes_with_both_categories) == 10
for recipe_summary in recipes_with_both_categories:
assert recipe_summary.recipe_category is not None
category_ids = [category.id for category in recipe_summary.recipe_category]
for category in created_categories:
assert category.id in category_ids
@ -308,7 +350,8 @@ def test_recipe_repo_pagination_by_categories(database: AllRepositories, unique_
assert not all(i == random_ordered[0] for i in random_ordered)
def test_recipe_repo_pagination_by_tags(database: AllRepositories, unique_user: TestUser):
def test_recipe_repo_pagination_by_tags(unique_user: TestUser):
database = unique_user.repos
slug1, slug2 = (random_string(10) for _ in range(2))
tags = [
@ -365,6 +408,7 @@ def test_recipe_repo_pagination_by_tags(database: AllRepositories, unique_user:
assert len(recipes_with_one_tag) == 15
for recipe_summary in recipes_with_one_tag:
assert recipe_summary.tags is not None
tag_ids = [tag.id for tag in recipe_summary.tags]
assert tag_id in tag_ids
@ -374,6 +418,7 @@ def test_recipe_repo_pagination_by_tags(database: AllRepositories, unique_user:
assert len(recipes_with_one_tag) == 15
for recipe_summary in recipes_with_one_tag:
assert recipe_summary.tags is not None
tag_slugs = [tag.slug for tag in recipe_summary.tags]
assert tag_slug in tag_slugs
@ -382,6 +427,7 @@ def test_recipe_repo_pagination_by_tags(database: AllRepositories, unique_user:
assert len(recipes_with_both_tags) == 10
for recipe_summary in recipes_with_both_tags:
assert recipe_summary.tags is not None
tag_ids = [tag.id for tag in recipe_summary.tags]
for tag in created_tags:
assert tag.id in tag_ids
@ -402,7 +448,8 @@ def test_recipe_repo_pagination_by_tags(database: AllRepositories, unique_user:
assert not all(i == random_ordered[0] for i in random_ordered)
def test_recipe_repo_pagination_by_tools(database: AllRepositories, unique_user: TestUser):
def test_recipe_repo_pagination_by_tools(unique_user: TestUser):
database = unique_user.repos
slug1, slug2 = (random_string(10) for _ in range(2))
tools = [
@ -498,7 +545,8 @@ def test_recipe_repo_pagination_by_tools(database: AllRepositories, unique_user:
assert not all(i == random_ordered[0] for i in random_ordered)
def test_recipe_repo_pagination_by_foods(database: AllRepositories, unique_user: TestUser):
def test_recipe_repo_pagination_by_foods(unique_user: TestUser):
database = unique_user.repos
slug1, slug2 = (random_string(10) for _ in range(2))
foods = [
@ -606,13 +654,12 @@ def test_recipe_repo_pagination_by_foods(database: AllRepositories, unique_user:
],
)
def test_basic_recipe_search(
unique_db: AllRepositories,
search: str,
expected_names: list[str],
database: AllRepositories,
search_recipes: list[Recipe], # required so database is populated
unique_local_group_id: str,
):
repo = database.recipes.by_group(unique_local_group_id) # type: ignore
repo = unique_db.recipes
pagination = PaginationQuery(page=1, per_page=-1, order_by="created_at", order_direction=OrderDirection.asc)
results = repo.page_all(pagination, search=search).items
@ -626,15 +673,14 @@ def test_basic_recipe_search(
def test_fuzzy_recipe_search(
database: AllRepositories,
unique_db: AllRepositories,
search_recipes: list[Recipe], # required so database is populated
unique_local_group_id: str,
):
# this only works on postgres
if database.session.get_bind().name != "postgresql":
if unique_db.session.get_bind().name != "postgresql":
return
repo = database.recipes.by_group(unique_local_group_id) # type: ignore
repo = unique_db.recipes
pagination = PaginationQuery(page=1, per_page=-1, order_by="created_at", order_direction=OrderDirection.asc)
results = repo.page_all(pagination, search="Steinbuck").items
@ -642,11 +688,10 @@ def test_fuzzy_recipe_search(
def test_random_order_recipe_search(
database: AllRepositories,
unique_db: AllRepositories,
search_recipes: list[Recipe], # required so database is populated
unique_local_group_id: str,
):
repo = database.recipes.by_group(unique_local_group_id) # type: ignore
repo = unique_db.recipes
pagination = PaginationQuery(
page=1,
per_page=-1,
@ -661,15 +706,16 @@ def test_random_order_recipe_search(
assert not all(i == random_ordered[0] for i in random_ordered)
def test_order_by_rating(database: AllRepositories, user_tuple: tuple[TestUser, TestUser]):
def test_order_by_rating(user_tuple: tuple[TestUser, TestUser]):
user_1, user_2 = user_tuple
repo = database.recipes.by_group(UUID(user_1.group_id))
database = user_1.repos
repo = database.recipes
recipes: list[Recipe] = []
for i in range(3):
slug = f"recipe-{i+1}-{random_string(5)}"
recipes.append(
database.recipes.create(
repo.create(
Recipe(
user_id=user_1.user_id,
group_id=user_1.group_id,
@ -768,7 +814,7 @@ def test_order_by_rating(database: AllRepositories, user_tuple: tuple[TestUser,
)
pq = PaginationQuery(page=1, per_page=-1, order_by="rating", order_direction=OrderDirection.desc)
data = database.recipes.by_group(UUID(user_1.group_id)).page_all(pq).items
data = database.recipes.page_all(pq).items
assert len(data) == 3
assert data[0].slug == recipe_1.slug # global rating == 4.25 (avg of 5 and 3.5)
@ -776,7 +822,7 @@ def test_order_by_rating(database: AllRepositories, user_tuple: tuple[TestUser,
assert data[2].slug == recipe_2.slug # global rating == 2.5 (avg of 4 and 1)
pq = PaginationQuery(page=1, per_page=-1, order_by="rating", order_direction=OrderDirection.asc)
data = database.recipes.by_group(UUID(user_1.group_id)).page_all(pq).items
data = database.recipes.page_all(pq).items
assert len(data) == 3
assert data[0].slug == recipe_2.slug # global rating == 2.5 (avg of 4 and 1)

View file

@ -1,7 +1,9 @@
from datetime import datetime, timezone
import pytest
from sqlalchemy.orm import Session
from mealie.repos.all_repositories import get_repositories
from mealie.repos.repository_factory import AllRepositories
from mealie.schema.recipe.recipe_ingredient import IngredientUnit, SaveIngredientUnit
from mealie.schema.response.pagination import OrderDirection, PaginationQuery
@ -10,12 +12,17 @@ from tests.utils.factories import random_int, random_string
@pytest.fixture()
def unique_local_group_id(database: AllRepositories) -> str:
return str(database.groups.create(GroupBase(name=random_string())).id)
def unique_local_group_id(unfiltered_database: AllRepositories) -> str:
return str(unfiltered_database.groups.create(GroupBase(name=random_string())).id)
@pytest.fixture()
def search_units(database: AllRepositories, unique_local_group_id: str) -> list[IngredientUnit]:
def unique_db(session: Session, unique_local_group_id: str):
return get_repositories(session, group_id=unique_local_group_id)
@pytest.fixture()
def search_units(unique_db: AllRepositories, unique_local_group_id: str) -> list[IngredientUnit]:
units = [
SaveIngredientUnit(
group_id=unique_local_group_id,
@ -57,7 +64,7 @@ def search_units(database: AllRepositories, unique_local_group_id: str) -> list[
]
)
return database.ingredient_units.create_many(units)
return unique_db.ingredient_units.create_many(units)
@pytest.mark.parametrize(
@ -82,11 +89,10 @@ def search_units(database: AllRepositories, unique_local_group_id: str) -> list[
def test_basic_search(
search: str,
expected_names: list[str],
database: AllRepositories,
unique_db: AllRepositories,
search_units: list[IngredientUnit], # required so database is populated
unique_local_group_id: str,
):
repo = database.ingredient_units.by_group(unique_local_group_id)
repo = unique_db.ingredient_units
pagination = PaginationQuery(page=1, per_page=-1, order_by="created_at", order_direction=OrderDirection.asc)
results = repo.page_all(pagination, search=search).items
@ -100,15 +106,14 @@ def test_basic_search(
def test_fuzzy_search(
database: AllRepositories,
unique_db: AllRepositories,
search_units: list[IngredientUnit], # required so database is populated
unique_local_group_id: str,
):
# this only works on postgres
if database.session.get_bind().name != "postgresql":
if unique_db.session.get_bind().name != "postgresql":
return
repo = database.ingredient_units.by_group(unique_local_group_id)
repo = unique_db.ingredient_units
pagination = PaginationQuery(page=1, per_page=-1, order_by="created_at", order_direction=OrderDirection.asc)
results = repo.page_all(pagination, search="tabel spoone").items
@ -116,11 +121,10 @@ def test_fuzzy_search(
def test_random_order_search(
database: AllRepositories,
unique_db: AllRepositories,
search_units: list[IngredientUnit], # required so database is populated
unique_local_group_id: str,
):
repo = database.ingredient_units.by_group(unique_local_group_id)
repo = unique_db.ingredient_units
pagination = PaginationQuery(
page=1,
per_page=-1,

View file

@ -1,11 +1,14 @@
from mealie.repos.repository_factory import AllRepositories
from uuid import UUID
from mealie.schema.recipe.recipe import Recipe
from mealie.schema.recipe.recipe_ingredient import RecipeIngredient, SaveIngredientUnit
from tests.utils.factories import random_string
from tests.utils.fixture_schemas import TestUser
def test_unit_merger(database: AllRepositories, unique_user: TestUser):
def test_unit_merger(unique_user: TestUser):
database = unique_user.repos
recipe: Recipe | None = None
slug1 = random_string(10)
unit_1 = database.ingredient_units.create(
@ -25,8 +28,8 @@ def test_unit_merger(database: AllRepositories, unique_user: TestUser):
recipe = database.recipes.create(
Recipe(
name=slug1,
user_id=unique_user.group_id,
group_id=unique_user.group_id,
user_id=unique_user.user_id,
group_id=UUID(unique_user.group_id),
recipe_ingredient=[
RecipeIngredient(note="", unit=unit_1), # type: ignore
RecipeIngredient(note="", unit=unit_2), # type: ignore
@ -35,6 +38,7 @@ def test_unit_merger(database: AllRepositories, unique_user: TestUser):
)
# Santiy check make sure recipe got created
assert recipe.id is not None
for ing in recipe.recipe_ingredient:
@ -43,6 +47,7 @@ def test_unit_merger(database: AllRepositories, unique_user: TestUser):
database.ingredient_units.merge(unit_2.id, unit_1.id)
recipe = database.recipes.get_one(recipe.slug)
assert recipe
for ingredient in recipe.recipe_ingredient:
assert ingredient.unit.id == unit_1.id # type: ignore

View file

@ -1,9 +1,9 @@
from mealie.repos.all_repositories import AllRepositories
from mealie.schema.user import PrivateUser
from tests.utils.fixture_schemas import TestUser
def test_user_directory_deleted_on_delete(database: AllRepositories, unique_user: TestUser) -> None:
def test_user_directory_deleted_on_delete(unique_user: TestUser) -> None:
database = unique_user.repos
user_dir = PrivateUser.get_directory(unique_user.user_id)
assert user_dir.exists()
database.users.delete(unique_user.user_id)