mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-05 21:45:25 +02:00
feat: Add Households to Mealie (#3970)
This commit is contained in:
parent
0c29cef17d
commit
eb170cc7e5
315 changed files with 6975 additions and 3577 deletions
|
@ -2,9 +2,9 @@ import random
|
|||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.cookbook.cookbook import SaveCookBook
|
||||
from mealie.schema.cookbook.cookbook import ReadCookBook, SaveCookBook
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from mealie.schema.recipe.recipe_category import TagSave
|
||||
from tests.utils import api_routes
|
||||
|
@ -12,41 +12,63 @@ from tests.utils.factories import random_int, random_string
|
|||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_private_group", [True, False], ids=["group_is_private", "group_is_public"])
|
||||
@pytest.mark.parametrize("is_private_group", [True, False])
|
||||
@pytest.mark.parametrize("is_household_1_private", [True, False])
|
||||
@pytest.mark.parametrize("is_household_2_private", [True, False])
|
||||
def test_get_all_cookbooks(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
h2_user: TestUser,
|
||||
is_private_group: bool,
|
||||
is_household_1_private: bool,
|
||||
is_household_2_private: bool,
|
||||
):
|
||||
## Set Up Group
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
group = unique_user.repos.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = is_private_group
|
||||
group.preferences.recipe_public = not is_private_group
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
unique_user.repos.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
## Set Up Cookbooks
|
||||
default_cookbooks = database.cookbooks.create_many(
|
||||
[SaveCookBook(name=random_string(), group_id=unique_user.group_id) for _ in range(random_int(15, 20))]
|
||||
)
|
||||
## Set Up Household and Cookbooks
|
||||
household_private_map: dict[UUID4, bool] = {}
|
||||
public_cookbooks: list[ReadCookBook] = []
|
||||
private_cookbooks: list[ReadCookBook] = []
|
||||
for database, is_private_household in [
|
||||
(unique_user.repos, is_household_1_private),
|
||||
(h2_user.repos, is_household_2_private),
|
||||
]:
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
random.shuffle(default_cookbooks)
|
||||
split_index = random_int(6, 12)
|
||||
public_cookbooks = default_cookbooks[:split_index]
|
||||
private_cookbooks = default_cookbooks[split_index:]
|
||||
household_private_map[household.id] = is_private_household
|
||||
household.preferences.private_household = is_private_household
|
||||
household.preferences.recipe_public = not is_private_household
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
for cookbook in public_cookbooks:
|
||||
cookbook.public = True
|
||||
## Set Up Cookbooks
|
||||
default_cookbooks = database.cookbooks.create_many(
|
||||
[
|
||||
SaveCookBook(name=random_string(), group_id=unique_user.group_id, household_id=unique_user.household_id)
|
||||
for _ in range(random_int(15, 20))
|
||||
]
|
||||
)
|
||||
|
||||
for cookbook in private_cookbooks:
|
||||
cookbook.public = False
|
||||
random.shuffle(default_cookbooks)
|
||||
split_index = random_int(6, 12)
|
||||
public_cookbooks.extend(default_cookbooks[:split_index])
|
||||
private_cookbooks.extend(default_cookbooks[split_index:])
|
||||
|
||||
database.cookbooks.update_many(public_cookbooks + private_cookbooks)
|
||||
for cookbook in default_cookbooks[:split_index]:
|
||||
cookbook.public = True
|
||||
|
||||
for cookbook in default_cookbooks[split_index:]:
|
||||
cookbook.public = False
|
||||
|
||||
database.cookbooks.update_many(default_cookbooks)
|
||||
|
||||
## Test Cookbooks
|
||||
response = api_client.get(api_routes.explore_cookbooks_group_slug(unique_user.group_id))
|
||||
response = api_client.get(api_routes.explore_groups_group_slug_cookbooks(unique_user.group_id))
|
||||
if is_private_group:
|
||||
assert response.status_code == 404
|
||||
return
|
||||
|
@ -56,55 +78,61 @@ def test_get_all_cookbooks(
|
|||
fetched_ids: set[str] = {cookbook["id"] for cookbook in cookbooks_data["items"]}
|
||||
|
||||
for cookbook in public_cookbooks:
|
||||
assert str(cookbook.id) in fetched_ids
|
||||
is_private_household = household_private_map[cookbook.household_id]
|
||||
if is_private_household:
|
||||
assert str(cookbook.id) not in fetched_ids
|
||||
else:
|
||||
assert str(cookbook.id) in fetched_ids
|
||||
|
||||
for cookbook in private_cookbooks:
|
||||
assert str(cookbook.id) not in fetched_ids
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"is_private_group, is_private_cookbook",
|
||||
[
|
||||
(True, True),
|
||||
(True, False),
|
||||
(False, True),
|
||||
(False, False),
|
||||
],
|
||||
ids=[
|
||||
"group_is_private_cookbook_is_private",
|
||||
"group_is_private_cookbook_is_public",
|
||||
"group_is_public_cookbook_is_private",
|
||||
"group_is_public_cookbook_is_public",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("is_private_group", [True, False])
|
||||
@pytest.mark.parametrize("is_private_household", [True, False])
|
||||
@pytest.mark.parametrize("is_private_cookbook", [True, False])
|
||||
def test_get_one_cookbook(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
is_private_group: bool,
|
||||
is_private_household: bool,
|
||||
is_private_cookbook: bool,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
## Set Up Group
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = is_private_group
|
||||
group.preferences.recipe_public = not is_private_group
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
## Set Up Household
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = is_private_household
|
||||
household.preferences.recipe_public = not is_private_household
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
## Set Up Cookbook
|
||||
cookbook = database.cookbooks.create(
|
||||
SaveCookBook(
|
||||
name=random_string(),
|
||||
group_id=unique_user.group_id,
|
||||
household_id=unique_user.household_id,
|
||||
public=not is_private_cookbook,
|
||||
)
|
||||
)
|
||||
|
||||
## Test Cookbook
|
||||
response = api_client.get(api_routes.explore_cookbooks_group_slug_item_id(unique_user.group_id, cookbook.id))
|
||||
if is_private_group or is_private_cookbook:
|
||||
response = api_client.get(api_routes.explore_groups_group_slug_cookbooks_item_id(unique_user.group_id, cookbook.id))
|
||||
if is_private_group or is_private_household or is_private_cookbook:
|
||||
assert response.status_code == 404
|
||||
if is_private_group:
|
||||
assert response.json()["detail"] == "group not found"
|
||||
else:
|
||||
assert response.json()["detail"] == "cookbook not found"
|
||||
return
|
||||
|
||||
assert response.status_code == 200
|
||||
|
@ -112,18 +140,31 @@ def test_get_one_cookbook(
|
|||
assert cookbook_data["id"] == str(cookbook.id)
|
||||
|
||||
|
||||
def test_get_cookbooks_with_recipes(api_client: TestClient, unique_user: TestUser, database: AllRepositories):
|
||||
def test_get_cookbooks_with_recipes(api_client: TestClient, unique_user: TestUser, h2_user: TestUser):
|
||||
database = unique_user.repos
|
||||
|
||||
# Create a public and private recipe with a known tag
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = False
|
||||
group.preferences.recipe_public = True
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = False
|
||||
household.preferences.recipe_public = True
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
tag = database.tags.create(TagSave(name=random_string(), group_id=unique_user.group_id))
|
||||
public_recipe, private_recipe = database.recipes.create_many(
|
||||
Recipe(user_id=unique_user.user_id, group_id=unique_user.group_id, name=random_string()) for _ in range(2)
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=random_string(),
|
||||
)
|
||||
for _ in range(2)
|
||||
)
|
||||
|
||||
assert public_recipe.settings
|
||||
|
@ -136,14 +177,40 @@ def test_get_cookbooks_with_recipes(api_client: TestClient, unique_user: TestUse
|
|||
|
||||
database.recipes.update_many([public_recipe, private_recipe])
|
||||
|
||||
# Create a recipe in another household that's public with the same known tag
|
||||
other_database = h2_user.repos
|
||||
other_household = other_database.households.get_one(h2_user.household_id)
|
||||
assert other_household and other_household.preferences
|
||||
|
||||
other_household.preferences.private_household = False
|
||||
other_household.preferences.recipe_public = True
|
||||
other_database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
other_household_recipe = other_database.recipes.create(
|
||||
Recipe(
|
||||
user_id=h2_user.user_id,
|
||||
group_id=h2_user.group_id,
|
||||
name=random_string(),
|
||||
)
|
||||
)
|
||||
assert other_household_recipe.settings
|
||||
other_household_recipe.settings.public = True
|
||||
other_household_recipe.tags = [tag]
|
||||
other_database.recipes.update(other_household_recipe.slug, other_household_recipe)
|
||||
|
||||
# Create a public cookbook with tag
|
||||
cookbook = database.cookbooks.create(
|
||||
SaveCookBook(name=random_string(), group_id=unique_user.group_id, public=True, tags=[tag])
|
||||
SaveCookBook(
|
||||
name=random_string(),
|
||||
group_id=unique_user.group_id,
|
||||
household_id=unique_user.household_id,
|
||||
public=True,
|
||||
tags=[tag],
|
||||
)
|
||||
)
|
||||
database.cookbooks.create(cookbook)
|
||||
|
||||
# Get the cookbook and make sure we only get the public recipe
|
||||
response = api_client.get(api_routes.explore_cookbooks_group_slug_item_id(unique_user.group_id, cookbook.id))
|
||||
# Get the cookbook and make sure we only get the public recipe from the correct household
|
||||
response = api_client.get(api_routes.explore_groups_group_slug_cookbooks_item_id(unique_user.group_id, cookbook.id))
|
||||
assert response.status_code == 200
|
||||
cookbook_data = response.json()
|
||||
assert cookbook_data["id"] == str(cookbook.id)
|
||||
|
@ -152,3 +219,4 @@ def test_get_cookbooks_with_recipes(api_client: TestClient, unique_user: TestUse
|
|||
assert len(cookbook_recipe_ids) == 1
|
||||
assert str(public_recipe.id) in cookbook_recipe_ids
|
||||
assert str(private_recipe.id) not in cookbook_recipe_ids
|
||||
assert str(other_household_recipe.id) not in cookbook_recipe_ids
|
||||
|
|
|
@ -1,35 +1,46 @@
|
|||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.recipe.recipe_ingredient import SaveIngredientFood
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.factories import random_int, random_string
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_private_group", [True, False], ids=["group_is_private", "group_is_public"])
|
||||
@pytest.mark.parametrize("is_private_group", [True, False])
|
||||
@pytest.mark.parametrize("is_private_household", [True, False])
|
||||
def test_get_all_foods(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
is_private_group: bool,
|
||||
is_private_household: bool,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
## Set Up Group
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = is_private_group
|
||||
group.preferences.recipe_public = not is_private_group
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
## Set Up Household
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = is_private_household
|
||||
household.preferences.recipe_public = not is_private_household
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
## Set Up Foods
|
||||
foods = database.ingredient_foods.create_many(
|
||||
[SaveIngredientFood(name=random_string(), group_id=unique_user.group_id) for _ in range(random_int(15, 20))]
|
||||
)
|
||||
|
||||
## Test Foods
|
||||
response = api_client.get(api_routes.explore_foods_group_slug(unique_user.group_id))
|
||||
response = api_client.get(api_routes.explore_groups_group_slug_foods(unique_user.group_id))
|
||||
|
||||
# whether or not the household is private shouldn't affect food visibility
|
||||
if is_private_group:
|
||||
assert response.status_code == 404
|
||||
return
|
||||
|
@ -42,26 +53,38 @@ def test_get_all_foods(
|
|||
assert str(food.id) in fetched_ids
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_private_group", [True, False], ids=["group_is_private", "group_is_public"])
|
||||
@pytest.mark.parametrize("is_private_group", [True, False])
|
||||
@pytest.mark.parametrize("is_private_household", [True, False])
|
||||
def test_get_one_food(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
is_private_group: bool,
|
||||
is_private_household: bool,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
## Set Up Group
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = is_private_group
|
||||
group.preferences.recipe_public = not is_private_group
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
## Set Up Household
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = is_private_household
|
||||
household.preferences.recipe_public = not is_private_household
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
## Set Up Food
|
||||
food = database.ingredient_foods.create(SaveIngredientFood(name=random_string(), group_id=unique_user.group_id))
|
||||
|
||||
## Test Food
|
||||
response = api_client.get(api_routes.explore_foods_group_slug_item_id(unique_user.group_id, food.id))
|
||||
response = api_client.get(api_routes.explore_groups_group_slug_foods_item_id(unique_user.group_id, food.id))
|
||||
|
||||
# whether or not the household is private shouldn't affect food visibility
|
||||
if is_private_group:
|
||||
assert response.status_code == 404
|
||||
return
|
||||
|
|
|
@ -3,7 +3,6 @@ from enum import Enum
|
|||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.recipe.recipe_category import CategorySave, TagSave
|
||||
from mealie.schema.recipe.recipe_tool import RecipeToolSave
|
||||
from tests.utils import api_routes
|
||||
|
@ -17,53 +16,46 @@ class OrganizerType(Enum):
|
|||
tools = "tools"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"organizer_type, is_private_group",
|
||||
[
|
||||
(OrganizerType.categories, True),
|
||||
(OrganizerType.categories, False),
|
||||
(OrganizerType.tags, True),
|
||||
(OrganizerType.tags, False),
|
||||
(OrganizerType.tools, True),
|
||||
(OrganizerType.tools, False),
|
||||
],
|
||||
ids=[
|
||||
"private_group_categories",
|
||||
"public_group_categories",
|
||||
"private_group_tags",
|
||||
"public_group_tags",
|
||||
"private_group_tools",
|
||||
"public_group_tools",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("organizer_type", [OrganizerType.categories, OrganizerType.tags, OrganizerType.tools])
|
||||
@pytest.mark.parametrize("is_private_group", [True, False])
|
||||
@pytest.mark.parametrize("is_private_household", [True, False])
|
||||
def test_get_all_organizers(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
organizer_type: OrganizerType,
|
||||
is_private_group: bool,
|
||||
is_private_household: bool,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
## Set Up Group
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = is_private_group
|
||||
group.preferences.recipe_public = not is_private_group
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
## Set Up Household
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = is_private_household
|
||||
household.preferences.recipe_public = not is_private_household
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
## Set Up Organizers
|
||||
if organizer_type is OrganizerType.categories:
|
||||
item_class = CategorySave
|
||||
repo = database.categories # type: ignore
|
||||
route = api_routes.explore_organizers_group_slug_categories
|
||||
route = api_routes.explore_groups_group_slug_organizers_categories
|
||||
elif organizer_type is OrganizerType.tags:
|
||||
item_class = TagSave
|
||||
repo = database.tags # type: ignore
|
||||
route = api_routes.explore_organizers_group_slug_tags
|
||||
route = api_routes.explore_groups_group_slug_organizers_tags
|
||||
else:
|
||||
item_class = RecipeToolSave
|
||||
repo = database.tools # type: ignore
|
||||
route = api_routes.explore_organizers_group_slug_tools
|
||||
route = api_routes.explore_groups_group_slug_organizers_tools
|
||||
|
||||
organizers = repo.create_many(
|
||||
[item_class(name=random_string(), group_id=unique_user.group_id) for _ in range(random_int(15, 20))]
|
||||
|
@ -71,6 +63,8 @@ def test_get_all_organizers(
|
|||
|
||||
## Test Organizers
|
||||
response = api_client.get(route(unique_user.group_id))
|
||||
|
||||
# whether or not the household is private shouldn't affect food visibility
|
||||
if is_private_group:
|
||||
assert response.status_code == 404
|
||||
return
|
||||
|
@ -83,58 +77,53 @@ def test_get_all_organizers(
|
|||
assert str(organizer.id) in fetched_ids
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"organizer_type, is_private_group",
|
||||
[
|
||||
(OrganizerType.categories, True),
|
||||
(OrganizerType.categories, False),
|
||||
(OrganizerType.tags, True),
|
||||
(OrganizerType.tags, False),
|
||||
(OrganizerType.tools, True),
|
||||
(OrganizerType.tools, False),
|
||||
],
|
||||
ids=[
|
||||
"private_group_category",
|
||||
"public_group_category",
|
||||
"private_group_tag",
|
||||
"public_group_tag",
|
||||
"private_group_tool",
|
||||
"public_group_tool",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("organizer_type", [OrganizerType.categories, OrganizerType.tags, OrganizerType.tools])
|
||||
@pytest.mark.parametrize("is_private_group", [True, False])
|
||||
@pytest.mark.parametrize("is_private_household", [True, False])
|
||||
def test_get_one_organizer(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
organizer_type: OrganizerType,
|
||||
is_private_group: bool,
|
||||
is_private_household: bool,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
## Set Up Group
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = is_private_group
|
||||
group.preferences.recipe_public = not is_private_group
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
## Set Up Household
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = is_private_household
|
||||
household.preferences.recipe_public = not is_private_household
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
## Set Up Organizer
|
||||
if organizer_type is OrganizerType.categories:
|
||||
item_class = CategorySave
|
||||
repo = database.categories # type: ignore
|
||||
route = api_routes.explore_organizers_group_slug_categories_item_id
|
||||
route = api_routes.explore_groups_group_slug_organizers_categories_item_id
|
||||
elif organizer_type is OrganizerType.tags:
|
||||
item_class = TagSave
|
||||
repo = database.tags # type: ignore
|
||||
route = api_routes.explore_organizers_group_slug_tags_item_id
|
||||
route = api_routes.explore_groups_group_slug_organizers_tags_item_id
|
||||
else:
|
||||
item_class = RecipeToolSave
|
||||
repo = database.tools # type: ignore
|
||||
route = api_routes.explore_organizers_group_slug_tools_item_id
|
||||
route = api_routes.explore_groups_group_slug_organizers_tools_item_id
|
||||
|
||||
organizer = repo.create(item_class(name=random_string(), group_id=unique_user.group_id))
|
||||
|
||||
## Test Organizer
|
||||
response = api_client.get(route(unique_user.group_id, organizer.id))
|
||||
|
||||
# whether or not the household is private shouldn't affect food visibility
|
||||
if is_private_group:
|
||||
assert response.status_code == 404
|
||||
return
|
||||
|
|
|
@ -1,68 +1,79 @@
|
|||
import random
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.cookbook.cookbook import SaveCookBook
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from mealie.schema.recipe.recipe_category import TagSave
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.factories import random_int, random_string
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class PublicRecipeTestCase:
|
||||
private_group: bool
|
||||
public_recipe: bool
|
||||
status_code: int
|
||||
error: str | None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_private_group", [True, False], ids=["group_is_private", "group_is_public"])
|
||||
@pytest.mark.parametrize("is_private_group", [True, False])
|
||||
@pytest.mark.parametrize("is_household_1_private", [True, False])
|
||||
@pytest.mark.parametrize("is_household_2_private", [True, False])
|
||||
def test_get_all_public_recipes(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
h2_user: TestUser,
|
||||
is_private_group: bool,
|
||||
is_household_1_private: bool,
|
||||
is_household_2_private: bool,
|
||||
):
|
||||
## Set Up Public and Private Recipes
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
group = unique_user.repos.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = is_private_group
|
||||
group.preferences.recipe_public = not is_private_group
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
unique_user.repos.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
default_recipes = database.recipes.create_many(
|
||||
[
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=random_string(),
|
||||
)
|
||||
for _ in range(random_int(15, 20))
|
||||
],
|
||||
)
|
||||
household_private_map: dict[UUID4, bool] = {}
|
||||
public_recipes: list[Recipe] = []
|
||||
private_recipes: list[Recipe] = []
|
||||
for database, is_private_household in [
|
||||
(unique_user.repos, is_household_1_private),
|
||||
(h2_user.repos, is_household_2_private),
|
||||
]:
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
random.shuffle(default_recipes)
|
||||
split_index = random_int(6, 12)
|
||||
public_recipes = default_recipes[:split_index]
|
||||
private_recipes = default_recipes[split_index:]
|
||||
household_private_map[household.id] = is_private_household
|
||||
household.preferences.private_household = is_private_household
|
||||
household.preferences.recipe_public = not is_private_household
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
for recipe in public_recipes:
|
||||
assert recipe.settings
|
||||
recipe.settings.public = True
|
||||
default_recipes = database.recipes.create_many(
|
||||
[
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=random_string(),
|
||||
)
|
||||
for _ in range(random_int(15, 20))
|
||||
],
|
||||
)
|
||||
|
||||
for recipe in private_recipes:
|
||||
assert recipe.settings
|
||||
recipe.settings.public = False
|
||||
random.shuffle(default_recipes)
|
||||
split_index = random_int(6, 12)
|
||||
public_recipes.extend(default_recipes[:split_index])
|
||||
private_recipes.extend(default_recipes[split_index:])
|
||||
|
||||
database.recipes.update_many(public_recipes + private_recipes)
|
||||
for recipe in default_recipes[:split_index]:
|
||||
assert recipe.settings
|
||||
recipe.settings.public = True
|
||||
|
||||
for recipe in default_recipes[split_index:]:
|
||||
assert recipe.settings
|
||||
recipe.settings.public = False
|
||||
|
||||
database.recipes.update_many(default_recipes)
|
||||
|
||||
## Query All Recipes
|
||||
response = api_client.get(api_routes.explore_recipes_group_slug(group.slug))
|
||||
response = api_client.get(api_routes.explore_groups_group_slug_recipes(group.slug))
|
||||
if is_private_group:
|
||||
assert response.status_code == 404
|
||||
return
|
||||
|
@ -72,7 +83,11 @@ def test_get_all_public_recipes(
|
|||
fetched_ids: set[str] = {recipe["id"] for recipe in recipes_data["items"]}
|
||||
|
||||
for recipe in public_recipes:
|
||||
assert str(recipe.id) in fetched_ids
|
||||
is_private_household = household_private_map[recipe.household_id]
|
||||
if is_private_household:
|
||||
assert str(recipe.id) not in fetched_ids
|
||||
else:
|
||||
assert str(recipe.id) in fetched_ids
|
||||
|
||||
for recipe in private_recipes:
|
||||
assert str(recipe.id) not in fetched_ids
|
||||
|
@ -89,82 +104,222 @@ def test_get_all_public_recipes(
|
|||
ids=[
|
||||
"match_slug",
|
||||
"not_match_slug",
|
||||
"bypass_public_filter_1",
|
||||
"bypass_public_filter_2",
|
||||
"bypass_public_settings_filter_1",
|
||||
"bypass_public_settings_filter_2",
|
||||
],
|
||||
)
|
||||
def test_get_all_public_recipes_filtered(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
random_recipe: Recipe,
|
||||
database: AllRepositories,
|
||||
query_filter: str,
|
||||
recipe_data: dict[str, Any],
|
||||
should_fetch: bool,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
## Set Up Recipe
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = False
|
||||
group.preferences.recipe_public = True
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = False
|
||||
household.preferences.recipe_public = True
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
assert random_recipe.settings
|
||||
random_recipe.settings.public = True
|
||||
database.recipes.update(random_recipe.slug, random_recipe.model_dump() | recipe_data)
|
||||
|
||||
## Query All Recipes
|
||||
response = api_client.get(api_routes.explore_recipes_group_slug(group.slug), params={"queryFilter": query_filter})
|
||||
response = api_client.get(
|
||||
api_routes.explore_groups_group_slug_recipes(group.slug),
|
||||
params={"queryFilter": query_filter},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
recipes_data = response.json()
|
||||
fetched_ids: set[str] = {recipe["id"] for recipe in recipes_data["items"]}
|
||||
assert should_fetch is (str(random_recipe.id) in fetched_ids)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"test_case",
|
||||
(
|
||||
PublicRecipeTestCase(private_group=False, public_recipe=True, status_code=200, error=None),
|
||||
PublicRecipeTestCase(private_group=True, public_recipe=True, status_code=404, error="group not found"),
|
||||
PublicRecipeTestCase(private_group=False, public_recipe=False, status_code=404, error="recipe not found"),
|
||||
),
|
||||
ids=("is public", "group private", "recipe private"),
|
||||
)
|
||||
def test_public_recipe_success(
|
||||
@pytest.mark.parametrize("is_private_group", [True, False])
|
||||
@pytest.mark.parametrize("is_private_household", [True, False])
|
||||
@pytest.mark.parametrize("is_private_recipe", [True, False])
|
||||
def test_get_one_recipe(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
random_recipe: Recipe,
|
||||
database: AllRepositories,
|
||||
test_case: PublicRecipeTestCase,
|
||||
is_private_group: bool,
|
||||
is_private_household: bool,
|
||||
is_private_recipe: bool,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
## Set Up Group
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = test_case.private_group
|
||||
group.preferences.recipe_public = not test_case.private_group
|
||||
group.preferences.private_group = is_private_group
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
# Set Recipe `settings.public` attribute
|
||||
## Set Up Household
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = is_private_household
|
||||
household.preferences.recipe_public = not is_private_household
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
## Set Recipe `settings.public` attribute
|
||||
assert random_recipe.settings
|
||||
random_recipe.settings.public = test_case.public_recipe
|
||||
random_recipe.settings.public = not is_private_recipe
|
||||
database.recipes.update(random_recipe.slug, random_recipe)
|
||||
|
||||
# Try to access recipe
|
||||
## Try to access recipe
|
||||
recipe_group = database.groups.get_by_slug_or_id(random_recipe.group_id)
|
||||
recipe_household = database.households.get_by_slug_or_id(random_recipe.household_id)
|
||||
assert recipe_group
|
||||
assert recipe_household
|
||||
response = api_client.get(
|
||||
api_routes.explore_recipes_group_slug_recipe_slug(
|
||||
recipe_group.slug,
|
||||
random_recipe.slug,
|
||||
)
|
||||
api_routes.explore_groups_group_slug_recipes_recipe_slug(recipe_group.slug, random_recipe.slug)
|
||||
)
|
||||
assert response.status_code == test_case.status_code
|
||||
|
||||
if test_case.error:
|
||||
assert response.json()["detail"] == test_case.error
|
||||
if is_private_group or is_private_household or is_private_recipe:
|
||||
assert response.status_code == 404
|
||||
if is_private_group:
|
||||
assert response.json()["detail"] == "group not found"
|
||||
else:
|
||||
assert response.json()["detail"] == "recipe not found"
|
||||
return
|
||||
|
||||
as_json = response.json()
|
||||
assert as_json["name"] == random_recipe.name
|
||||
assert as_json["slug"] == random_recipe.slug
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_private_cookbook", [True, False])
|
||||
def test_public_recipe_cookbook_filter(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
is_private_cookbook: bool,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
## Set Up Group
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = False
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
## Set Up Household
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = False
|
||||
household.preferences.recipe_public = True
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
## Set Up Cookbook
|
||||
cookbook = database.cookbooks.create(
|
||||
SaveCookBook(
|
||||
name=random_string(),
|
||||
group_id=unique_user.group_id,
|
||||
household_id=unique_user.household_id,
|
||||
public=not is_private_cookbook,
|
||||
)
|
||||
)
|
||||
|
||||
## Try to access recipe query
|
||||
response = api_client.get(
|
||||
api_routes.explore_groups_group_slug_recipes(group.slug), params={"cookbook": cookbook.id}
|
||||
)
|
||||
if is_private_cookbook:
|
||||
assert response.status_code == 404
|
||||
else:
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_public_recipe_cookbook_filter_with_recipes(api_client: TestClient, unique_user: TestUser, h2_user: TestUser):
|
||||
database = unique_user.repos
|
||||
|
||||
# Create a public and private recipe with a known tag
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = False
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
household = database.households.get_one(unique_user.household_id)
|
||||
assert household and household.preferences
|
||||
|
||||
household.preferences.private_household = False
|
||||
household.preferences.recipe_public = True
|
||||
database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
tag = database.tags.create(TagSave(name=random_string(), group_id=unique_user.group_id))
|
||||
public_recipe, private_recipe = database.recipes.create_many(
|
||||
Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
name=random_string(),
|
||||
)
|
||||
for _ in range(2)
|
||||
)
|
||||
|
||||
assert public_recipe.settings
|
||||
public_recipe.settings.public = True
|
||||
public_recipe.tags = [tag]
|
||||
|
||||
assert private_recipe.settings
|
||||
private_recipe.settings.public = False
|
||||
private_recipe.tags = [tag]
|
||||
|
||||
database.recipes.update_many([public_recipe, private_recipe])
|
||||
|
||||
# Create a recipe in another household that's public with the same known tag
|
||||
other_database = h2_user.repos
|
||||
other_household = other_database.households.get_one(h2_user.household_id)
|
||||
assert other_household and other_household.preferences
|
||||
|
||||
other_household.preferences.private_household = False
|
||||
other_household.preferences.recipe_public = True
|
||||
other_database.household_preferences.update(household.id, household.preferences)
|
||||
|
||||
other_household_recipe = other_database.recipes.create(
|
||||
Recipe(
|
||||
user_id=h2_user.user_id,
|
||||
group_id=h2_user.group_id,
|
||||
name=random_string(),
|
||||
)
|
||||
)
|
||||
assert other_household_recipe.settings
|
||||
other_household_recipe.settings.public = True
|
||||
other_household_recipe.tags = [tag]
|
||||
other_database.recipes.update(other_household_recipe.slug, other_household_recipe)
|
||||
|
||||
# Create a public cookbook with tag
|
||||
cookbook = database.cookbooks.create(
|
||||
SaveCookBook(
|
||||
name=random_string(),
|
||||
group_id=unique_user.group_id,
|
||||
household_id=unique_user.household_id,
|
||||
public=True,
|
||||
tags=[tag],
|
||||
)
|
||||
)
|
||||
|
||||
# Get the cookbook's recipes and make sure we only get the public recipe from the correct household
|
||||
response = api_client.get(
|
||||
api_routes.explore_groups_group_slug_recipes(unique_user.group_id), params={"cookbook": cookbook.id}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
recipe_ids: set[str] = {recipe["id"] for recipe in response.json()["items"]}
|
||||
assert len(recipe_ids) == 1
|
||||
assert str(public_recipe.id) in recipe_ids
|
||||
assert str(private_recipe.id) not in recipe_ids
|
||||
assert str(other_household_recipe.id) not in recipe_ids
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue