mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-03 04:25:24 +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
|
@ -4,25 +4,25 @@ CWD = Path(__file__).parent
|
|||
|
||||
locale_dir = CWD / "locale"
|
||||
|
||||
backup_version_44e8d670719d_1 = CWD / "backups/backup_version_44e8d670719d_1.zip"
|
||||
backup_version_44e8d670719d_1 = CWD / "backups/backup-version-44e8d670719d-1.zip"
|
||||
"""44e8d670719d: add extras to shopping lists, list items, and ingredient foods"""
|
||||
|
||||
backup_version_44e8d670719d_2 = CWD / "backups/backup_version_44e8d670719d_2.zip"
|
||||
backup_version_44e8d670719d_2 = CWD / "backups/backup-version-44e8d670719d-2.zip"
|
||||
"""44e8d670719d: add extras to shopping lists, list items, and ingredient foods"""
|
||||
|
||||
backup_version_44e8d670719d_3 = CWD / "backups/backup_version_44e8d670719d_3.zip"
|
||||
backup_version_44e8d670719d_3 = CWD / "backups/backup-version-44e8d670719d-3.zip"
|
||||
"""44e8d670719d: add extras to shopping lists, list items, and ingredient foods"""
|
||||
|
||||
backup_version_44e8d670719d_4 = CWD / "backups/backup_version_44e8d670719d_4.zip"
|
||||
backup_version_44e8d670719d_4 = CWD / "backups/backup-version-44e8d670719d-4.zip"
|
||||
"""44e8d670719d: add extras to shopping lists, list items, and ingredient foods"""
|
||||
|
||||
backup_version_ba1e4a6cfe99_1 = CWD / "backups/backup_version_ba1e4a6cfe99_1.zip"
|
||||
backup_version_ba1e4a6cfe99_1 = CWD / "backups/backup-version-ba1e4a6cfe99-1.zip"
|
||||
"""ba1e4a6cfe99: added plural names and alias tables for foods and units"""
|
||||
|
||||
backup_version_bcfdad6b7355_1 = CWD / "backups/backup_version_bcfdad6b7355_1.zip"
|
||||
backup_version_bcfdad6b7355_1 = CWD / "backups/backup-version-bcfdad6b7355-1.zip"
|
||||
"""bcfdad6b7355: remove tool name and slug unique contraints"""
|
||||
|
||||
backup_version_09aba125b57a_1 = CWD / "backups/backup_version_09aba125b57a_1.zip"
|
||||
backup_version_09aba125b57a_1 = CWD / "backups/backup-version-09aba125b57a-1.zip"
|
||||
"""09aba125b57a: add OIDC auth method (Safari-mangled ZIP structure)"""
|
||||
|
||||
migrations_paprika = CWD / "migrations/paprika.zip"
|
||||
|
|
26
tests/fixtures/fixture_admin.py
vendored
26
tests/fixtures/fixture_admin.py
vendored
|
@ -1,7 +1,11 @@
|
|||
from uuid import UUID
|
||||
|
||||
from pytest import fixture
|
||||
from sqlalchemy.orm import Session
|
||||
from starlette.testclient import TestClient
|
||||
|
||||
from mealie.core.config import get_app_settings
|
||||
from mealie.repos.all_repositories import get_repositories
|
||||
from tests import utils
|
||||
from tests.utils import api_routes
|
||||
|
||||
|
@ -14,8 +18,8 @@ def admin_token(api_client: TestClient):
|
|||
return utils.login(form_data, api_client)
|
||||
|
||||
|
||||
@fixture(scope="session")
|
||||
def admin_user(api_client: TestClient):
|
||||
@fixture(scope="module")
|
||||
def admin_user(session: Session, api_client: TestClient):
|
||||
settings = get_app_settings()
|
||||
|
||||
form_data = {"username": settings._DEFAULT_EMAIL, "password": settings._DEFAULT_PASSWORD}
|
||||
|
@ -26,17 +30,27 @@ def admin_user(api_client: TestClient):
|
|||
assert token is not None
|
||||
|
||||
assert user_data.get("admin") is True
|
||||
assert user_data.get("groupId") is not None
|
||||
assert user_data.get("id") is not None
|
||||
assert (user_id := user_data.get("id")) is not None
|
||||
assert (group_id := user_data.get("groupId")) is not None
|
||||
assert (household_id := user_data.get("householdId")) is not None
|
||||
|
||||
if not isinstance(user_id, UUID):
|
||||
user_id = UUID(user_id)
|
||||
if not isinstance(group_id, UUID):
|
||||
group_id = UUID(group_id)
|
||||
if not isinstance(household_id, UUID):
|
||||
household_id = UUID(household_id)
|
||||
|
||||
try:
|
||||
yield utils.TestUser(
|
||||
_group_id=user_data.get("groupId"),
|
||||
user_id=user_data.get("id"),
|
||||
_group_id=group_id,
|
||||
_household_id=household_id,
|
||||
user_id=user_id,
|
||||
password=settings._DEFAULT_PASSWORD,
|
||||
username=user_data.get("username"),
|
||||
email=user_data.get("email"),
|
||||
token=token,
|
||||
repos=get_repositories(session, group_id=group_id, household_id=household_id),
|
||||
)
|
||||
finally:
|
||||
# TODO: Delete User after test
|
||||
|
|
19
tests/fixtures/fixture_database.py
vendored
19
tests/fixtures/fixture_database.py
vendored
|
@ -1,14 +1,21 @@
|
|||
from collections.abc import Generator
|
||||
|
||||
import pytest
|
||||
from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from mealie.db.db_setup import SessionLocal
|
||||
from mealie.repos.all_repositories import AllRepositories, get_repositories
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def database() -> AllRepositories:
|
||||
@pytest.fixture(scope="module")
|
||||
def session() -> Generator[sessionmaker[Session], None, None]:
|
||||
try:
|
||||
db = SessionLocal()
|
||||
yield get_repositories(db)
|
||||
|
||||
sess = SessionLocal()
|
||||
yield sess
|
||||
finally:
|
||||
db.close()
|
||||
sess.close()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def unfiltered_database(session: Session) -> Generator[AllRepositories, None, None]:
|
||||
yield get_repositories(session, group_id=None, household_id=None)
|
||||
|
|
7
tests/fixtures/fixture_multitenant.py
vendored
7
tests/fixtures/fixture_multitenant.py
vendored
|
@ -2,6 +2,7 @@ from dataclasses import dataclass
|
|||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from tests import utils
|
||||
from tests.fixtures.fixture_users import build_unique_user
|
||||
|
@ -15,8 +16,8 @@ class MultiTenant:
|
|||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def multitenants(api_client: TestClient) -> MultiTenant:
|
||||
def multitenants(session: Session, api_client: TestClient) -> MultiTenant:
|
||||
yield MultiTenant(
|
||||
user_one=build_unique_user(random_string(12), api_client),
|
||||
user_two=build_unique_user(random_string(12), api_client),
|
||||
user_one=build_unique_user(session, random_string(12), api_client),
|
||||
user_two=build_unique_user(session, random_string(12), api_client),
|
||||
)
|
||||
|
|
10
tests/fixtures/fixture_recipe.py
vendored
10
tests/fixtures/fixture_recipe.py
vendored
|
@ -4,7 +4,6 @@ from collections.abc import Generator
|
|||
import sqlalchemy
|
||||
from pytest import fixture
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from mealie.schema.recipe.recipe_category import CategoryOut, CategorySave
|
||||
from mealie.schema.recipe.recipe_ingredient import RecipeIngredient
|
||||
|
@ -30,7 +29,8 @@ def recipe_store():
|
|||
|
||||
|
||||
@fixture(scope="function")
|
||||
def recipe_ingredient_only(database: AllRepositories, unique_user: TestUser):
|
||||
def recipe_ingredient_only(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
# Create a recipe
|
||||
recipe = Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
|
@ -55,7 +55,8 @@ def recipe_ingredient_only(database: AllRepositories, unique_user: TestUser):
|
|||
|
||||
|
||||
@fixture(scope="function")
|
||||
def recipe_categories(database: AllRepositories, unique_user: TestUser) -> Generator[list[CategoryOut], None, None]:
|
||||
def recipe_categories(unique_user: TestUser) -> Generator[list[CategoryOut], None, None]:
|
||||
database = unique_user.repos
|
||||
models: list[CategoryOut] = []
|
||||
for _ in range(3):
|
||||
category = CategorySave(
|
||||
|
@ -73,7 +74,8 @@ def recipe_categories(database: AllRepositories, unique_user: TestUser) -> Gener
|
|||
|
||||
|
||||
@fixture(scope="function")
|
||||
def random_recipe(database: AllRepositories, unique_user: TestUser) -> Generator[Recipe, None, None]:
|
||||
def random_recipe(unique_user: TestUser) -> Generator[Recipe, None, None]:
|
||||
database = unique_user.repos
|
||||
recipe = Recipe(
|
||||
user_id=unique_user.user_id,
|
||||
group_id=unique_user.group_id,
|
||||
|
|
30
tests/fixtures/fixture_shopping_lists.py
vendored
30
tests/fixtures/fixture_shopping_lists.py
vendored
|
@ -2,8 +2,7 @@ import pytest
|
|||
import sqlalchemy
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.group.group_shopping_list import ShoppingListItemCreate, ShoppingListOut, ShoppingListSave
|
||||
from mealie.schema.household.group_shopping_list import ShoppingListItemCreate, ShoppingListOut, ShoppingListSave
|
||||
from tests.utils.factories import random_string
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
@ -24,12 +23,17 @@ def create_item(list_id: UUID4) -> dict:
|
|||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def shopping_lists(database: AllRepositories, unique_user: TestUser):
|
||||
def shopping_lists(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
models: list[ShoppingListOut] = []
|
||||
|
||||
for _ in range(3):
|
||||
model = database.group_shopping_lists.create(
|
||||
ShoppingListSave(name=random_string(10), group_id=unique_user.group_id, user_id=unique_user.user_id),
|
||||
ShoppingListSave(
|
||||
name=random_string(10),
|
||||
group_id=unique_user.group_id,
|
||||
user_id=unique_user.user_id,
|
||||
),
|
||||
)
|
||||
|
||||
models.append(model)
|
||||
|
@ -44,9 +48,14 @@ def shopping_lists(database: AllRepositories, unique_user: TestUser):
|
|||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def shopping_list(database: AllRepositories, unique_user: TestUser):
|
||||
def shopping_list(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
model = database.group_shopping_lists.create(
|
||||
ShoppingListSave(name=random_string(10), group_id=unique_user.group_id, user_id=unique_user.user_id),
|
||||
ShoppingListSave(
|
||||
name=random_string(10),
|
||||
group_id=unique_user.group_id,
|
||||
user_id=unique_user.user_id,
|
||||
),
|
||||
)
|
||||
|
||||
yield model
|
||||
|
@ -58,9 +67,14 @@ def shopping_list(database: AllRepositories, unique_user: TestUser):
|
|||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def list_with_items(database: AllRepositories, unique_user: TestUser):
|
||||
def list_with_items(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
list_model = database.group_shopping_lists.create(
|
||||
ShoppingListSave(name=random_string(10), group_id=unique_user.group_id, user_id=unique_user.user_id),
|
||||
ShoppingListSave(
|
||||
name=random_string(10),
|
||||
group_id=unique_user.group_id,
|
||||
user_id=unique_user.user_id,
|
||||
),
|
||||
)
|
||||
|
||||
for _ in range(10):
|
||||
|
|
149
tests/fixtures/fixture_users.py
vendored
149
tests/fixtures/fixture_users.py
vendored
|
@ -1,7 +1,9 @@
|
|||
import json
|
||||
from collections.abc import Generator
|
||||
from uuid import UUID
|
||||
|
||||
from pytest import fixture
|
||||
from sqlalchemy.orm import Session
|
||||
from starlette.testclient import TestClient
|
||||
|
||||
from mealie.db.db_setup import session_context
|
||||
|
@ -12,7 +14,7 @@ from tests.utils import api_routes
|
|||
from tests.utils.factories import random_string
|
||||
|
||||
|
||||
def build_unique_user(group: str, api_client: TestClient) -> utils.TestUser:
|
||||
def build_unique_user(session: Session, group: str, api_client: TestClient) -> utils.TestUser:
|
||||
group = group or random_string(12)
|
||||
|
||||
registration = utils.user_registration_factory()
|
||||
|
@ -26,19 +28,98 @@ def build_unique_user(group: str, api_client: TestClient) -> utils.TestUser:
|
|||
user_data = api_client.get(api_routes.users_self, headers=token).json()
|
||||
assert token is not None
|
||||
|
||||
user_id = user_data.get("id")
|
||||
group_id = user_data.get("groupId")
|
||||
household_id = user_data.get("householdId")
|
||||
|
||||
if not isinstance(user_id, UUID):
|
||||
user_id = UUID(user_id)
|
||||
if not isinstance(group_id, UUID):
|
||||
group_id = UUID(group_id)
|
||||
if not isinstance(household_id, UUID):
|
||||
household_id = UUID(household_id)
|
||||
|
||||
return utils.TestUser(
|
||||
_group_id=user_data.get("groupId"),
|
||||
user_id=user_data.get("id"),
|
||||
_group_id=group_id,
|
||||
_household_id=household_id,
|
||||
user_id=user_id,
|
||||
email=user_data.get("email"),
|
||||
username=user_data.get("username"),
|
||||
password=registration.password,
|
||||
token=token,
|
||||
repos=get_repositories(session, group_id=group_id, household_id=household_id),
|
||||
)
|
||||
|
||||
|
||||
@fixture(scope="module")
|
||||
def g2_user(admin_token, api_client: TestClient):
|
||||
def h2_user(session: Session, admin_token, api_client: TestClient, unique_user: utils.TestUser):
|
||||
"""Another user in the same group as `unique_user`, but in a different household"""
|
||||
group = api_client.get(api_routes.groups_self, headers=unique_user.token).json()
|
||||
household_name = random_string(12)
|
||||
api_client.post(
|
||||
api_routes.admin_households,
|
||||
json={
|
||||
"name": household_name,
|
||||
"groupId": group["id"],
|
||||
},
|
||||
headers=admin_token,
|
||||
)
|
||||
|
||||
user_data = {
|
||||
"fullName": utils.random_string(),
|
||||
"username": utils.random_string(),
|
||||
"email": utils.random_email(),
|
||||
"password": "useruser",
|
||||
"group": group["name"],
|
||||
"household": household_name,
|
||||
"admin": False,
|
||||
"tokens": [],
|
||||
}
|
||||
response = api_client.post(api_routes.users, json=user_data, headers=admin_token)
|
||||
assert response.status_code == 201
|
||||
|
||||
# Log in as this user
|
||||
form_data = {"username": user_data["email"], "password": "useruser"}
|
||||
token = utils.login(form_data, api_client)
|
||||
|
||||
self_response = api_client.get(api_routes.users_self, headers=token)
|
||||
assert self_response.status_code == 200
|
||||
|
||||
data = json.loads(self_response.text)
|
||||
user_id = data["id"]
|
||||
household_id = data["householdId"]
|
||||
group_id = data["groupId"]
|
||||
assert user_id
|
||||
assert group_id
|
||||
assert household_id
|
||||
|
||||
if not isinstance(user_id, UUID):
|
||||
user_id = UUID(user_id)
|
||||
if not isinstance(group_id, UUID):
|
||||
group_id = UUID(group_id)
|
||||
if not isinstance(household_id, UUID):
|
||||
household_id = UUID(household_id)
|
||||
|
||||
try:
|
||||
yield utils.TestUser(
|
||||
user_id=user_id,
|
||||
_group_id=group_id,
|
||||
_household_id=household_id,
|
||||
token=token,
|
||||
email=user_data["email"],
|
||||
username=user_data["username"],
|
||||
password=user_data["password"],
|
||||
repos=get_repositories(session, group_id=group_id, household_id=household_id),
|
||||
)
|
||||
finally:
|
||||
# TODO: Delete User after test
|
||||
pass
|
||||
|
||||
|
||||
@fixture(scope="module")
|
||||
def g2_user(session: Session, admin_token, api_client: TestClient):
|
||||
group = random_string(12)
|
||||
|
||||
# Create the user
|
||||
create_data = {
|
||||
"fullName": utils.random_string(),
|
||||
|
@ -46,11 +127,12 @@ def g2_user(admin_token, api_client: TestClient):
|
|||
"email": utils.random_email(),
|
||||
"password": "useruser",
|
||||
"group": group,
|
||||
"household": "Family",
|
||||
"admin": False,
|
||||
"tokens": [],
|
||||
}
|
||||
|
||||
response = api_client.post(api_routes.admin_groups, json={"name": group}, headers=admin_token)
|
||||
api_client.post(api_routes.admin_groups, json={"name": group}, headers=admin_token)
|
||||
response = api_client.post(api_routes.users, json=create_data, headers=admin_token)
|
||||
|
||||
assert response.status_code == 201
|
||||
|
@ -66,15 +148,25 @@ def g2_user(admin_token, api_client: TestClient):
|
|||
|
||||
user_id = json.loads(self_response.text).get("id")
|
||||
group_id = json.loads(self_response.text).get("groupId")
|
||||
household_id = json.loads(self_response.text).get("householdId")
|
||||
|
||||
if not isinstance(user_id, UUID):
|
||||
user_id = UUID(user_id)
|
||||
if not isinstance(group_id, UUID):
|
||||
group_id = UUID(group_id)
|
||||
if not isinstance(household_id, UUID):
|
||||
household_id = UUID(household_id)
|
||||
|
||||
try:
|
||||
yield utils.TestUser(
|
||||
user_id=user_id,
|
||||
_group_id=group_id,
|
||||
_household_id=household_id,
|
||||
token=token,
|
||||
email=create_data["email"], # type: ignore
|
||||
username=create_data.get("username"), # type: ignore
|
||||
password=create_data.get("password"), # type: ignore
|
||||
repos=get_repositories(session, group_id=group_id, household_id=household_id),
|
||||
)
|
||||
finally:
|
||||
# TODO: Delete User after test
|
||||
|
@ -82,7 +174,7 @@ def g2_user(admin_token, api_client: TestClient):
|
|||
|
||||
|
||||
@fixture(scope="module")
|
||||
def unique_user(api_client: TestClient):
|
||||
def unique_user(session: Session, api_client: TestClient):
|
||||
registration = utils.user_registration_factory()
|
||||
response = api_client.post("/api/users/register", json=registration.model_dump(by_alias=True))
|
||||
assert response.status_code == 201
|
||||
|
@ -94,14 +186,27 @@ def unique_user(api_client: TestClient):
|
|||
user_data = api_client.get(api_routes.users_self, headers=token).json()
|
||||
assert token is not None
|
||||
|
||||
assert (user_id := user_data.get("id")) is not None
|
||||
assert (group_id := user_data.get("groupId")) is not None
|
||||
assert (household_id := user_data.get("householdId")) is not None
|
||||
|
||||
if not isinstance(user_id, UUID):
|
||||
user_id = UUID(user_id)
|
||||
if not isinstance(group_id, UUID):
|
||||
group_id = UUID(group_id)
|
||||
if not isinstance(household_id, UUID):
|
||||
household_id = UUID(household_id)
|
||||
|
||||
try:
|
||||
yield utils.TestUser(
|
||||
_group_id=user_data.get("groupId"),
|
||||
user_id=user_data.get("id"),
|
||||
_group_id=group_id,
|
||||
_household_id=household_id,
|
||||
user_id=user_id,
|
||||
email=user_data.get("email"),
|
||||
username=user_data.get("username"),
|
||||
password=registration.password,
|
||||
token=token,
|
||||
repos=get_repositories(session, group_id=group_id, household_id=household_id),
|
||||
)
|
||||
finally:
|
||||
# TODO: Delete User after test
|
||||
|
@ -109,8 +214,9 @@ def unique_user(api_client: TestClient):
|
|||
|
||||
|
||||
@fixture(scope="module")
|
||||
def user_tuple(admin_token, api_client: TestClient) -> Generator[list[utils.TestUser], None, None]:
|
||||
def user_tuple(session: Session, admin_token, api_client: TestClient) -> Generator[list[utils.TestUser], None, None]:
|
||||
group_name = utils.random_string()
|
||||
|
||||
# Create the user
|
||||
create_data_1 = {
|
||||
"fullName": utils.random_string(),
|
||||
|
@ -118,6 +224,7 @@ def user_tuple(admin_token, api_client: TestClient) -> Generator[list[utils.Test
|
|||
"email": utils.random_email(),
|
||||
"password": "useruser",
|
||||
"group": group_name,
|
||||
"household": "Family",
|
||||
"admin": False,
|
||||
"tokens": [],
|
||||
}
|
||||
|
@ -128,6 +235,7 @@ def user_tuple(admin_token, api_client: TestClient) -> Generator[list[utils.Test
|
|||
"email": utils.random_email(),
|
||||
"password": "useruser",
|
||||
"group": group_name,
|
||||
"household": "Family",
|
||||
"admin": False,
|
||||
"tokens": [],
|
||||
}
|
||||
|
@ -147,14 +255,27 @@ def user_tuple(admin_token, api_client: TestClient) -> Generator[list[utils.Test
|
|||
assert response.status_code == 200
|
||||
user_data = json.loads(response.text)
|
||||
|
||||
user_id = user_data.get("id")
|
||||
group_id = user_data.get("groupId")
|
||||
household_id = user_data.get("householdId")
|
||||
|
||||
if not isinstance(user_id, UUID):
|
||||
user_id = UUID(user_id)
|
||||
if not isinstance(group_id, UUID):
|
||||
group_id = UUID(group_id)
|
||||
if not isinstance(household_id, UUID):
|
||||
household_id = UUID(household_id)
|
||||
|
||||
users_out.append(
|
||||
utils.TestUser(
|
||||
_group_id=user_data.get("groupId"),
|
||||
user_id=user_data.get("id"),
|
||||
_group_id=group_id,
|
||||
_household_id=household_id,
|
||||
user_id=user_id,
|
||||
username=user_data.get("username"),
|
||||
email=user_data.get("email"),
|
||||
password="useruser",
|
||||
token=token,
|
||||
repos=get_repositories(session, group_id=group_id, household_id=household_id),
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -164,7 +285,7 @@ def user_tuple(admin_token, api_client: TestClient) -> Generator[list[utils.Test
|
|||
pass
|
||||
|
||||
|
||||
@fixture(scope="session")
|
||||
@fixture(scope="module")
|
||||
def user_token(admin_token, api_client: TestClient):
|
||||
# Create the user
|
||||
create_data = {
|
||||
|
@ -191,7 +312,7 @@ def ldap_user():
|
|||
# Create an LDAP user directly instead of using TestClient since we don't have
|
||||
# a LDAP service set up
|
||||
with session_context() as session:
|
||||
db = get_repositories(session)
|
||||
db = get_repositories(session, group_id=None, household_id=None)
|
||||
user = db.users.create(
|
||||
{
|
||||
"username": utils.random_string(10),
|
||||
|
@ -204,5 +325,5 @@ def ldap_user():
|
|||
)
|
||||
yield user
|
||||
with session_context() as session:
|
||||
db = get_repositories(session)
|
||||
db = get_repositories(session, group_id=None, household_id=None)
|
||||
db.users.delete(user.id)
|
||||
|
|
|
@ -9,13 +9,15 @@ from tests.utils.fixture_schemas import TestUser
|
|||
|
||||
|
||||
@pytest.mark.parametrize("is_private_group", [True, False], ids=["private group", "public group"])
|
||||
def test_public_about_get_app_info(api_client: TestClient, is_private_group: bool, database: AllRepositories):
|
||||
def test_public_about_get_app_info(
|
||||
api_client: TestClient, is_private_group: bool, unfiltered_database: AllRepositories
|
||||
):
|
||||
settings = get_app_settings()
|
||||
group = database.groups.get_by_name(settings.DEFAULT_GROUP)
|
||||
group = unfiltered_database.groups.get_by_name(settings.DEFAULT_GROUP)
|
||||
assert group and group.preferences
|
||||
|
||||
group.preferences.private_group = is_private_group
|
||||
database.group_preferences.update(group.id, group.preferences)
|
||||
unfiltered_database.group_preferences.update(group.id, group.preferences)
|
||||
|
||||
response = api_client.get(api_routes.app_about)
|
||||
as_dict = response.json()
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.core.config import get_app_settings
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.user.user import GroupInDB
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.assertion_helpers import assert_ignore_keys
|
||||
from tests.utils.factories import random_bool, random_string
|
||||
|
@ -29,21 +32,34 @@ def test_admin_create_group(api_client: TestClient, admin_user: TestUser):
|
|||
response = api_client.post(api_routes.admin_groups, json={"name": random_string()}, headers=admin_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
# verify preferences are set and the default household is created
|
||||
group = GroupInDB.model_validate(response.json())
|
||||
assert group.preferences and len(group.households) == 1
|
||||
created_household = group.households[0]
|
||||
assert created_household.name == get_app_settings().DEFAULT_HOUSEHOLD
|
||||
|
||||
response = api_client.get(api_routes.admin_households_item_id(created_household.id), headers=admin_user.token)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["id"] == str(created_household.id)
|
||||
|
||||
# verify no extra households are created
|
||||
response = api_client.get(api_routes.admin_households, headers=admin_user.token, params={"page": 1, "perPage": -1})
|
||||
assert response.status_code == 200
|
||||
items = response.json()["items"]
|
||||
filtered_item_ids: list[str] = []
|
||||
for item in items:
|
||||
if item["groupId"] == str(group.id):
|
||||
filtered_item_ids.append(item["id"])
|
||||
|
||||
assert len(filtered_item_ids) == 1
|
||||
assert filtered_item_ids[0] == str(created_household.id)
|
||||
|
||||
|
||||
def test_admin_update_group(api_client: TestClient, admin_user: TestUser, unique_user: TestUser):
|
||||
update_payload = {
|
||||
"id": unique_user.group_id,
|
||||
"name": "New Name",
|
||||
"preferences": {
|
||||
"privateGroup": random_bool(),
|
||||
"firstDayOfWeek": 2,
|
||||
"recipePublic": random_bool(),
|
||||
"recipeShowNutrition": random_bool(),
|
||||
"recipeShowAssets": random_bool(),
|
||||
"recipeLandscapeView": random_bool(),
|
||||
"recipeDisableComments": random_bool(),
|
||||
"recipeDisableAmount": random_bool(),
|
||||
},
|
||||
"preferences": {"privateGroup": random_bool()},
|
||||
}
|
||||
|
||||
response = api_client.put(
|
||||
|
@ -57,18 +73,13 @@ def test_admin_update_group(api_client: TestClient, admin_user: TestUser, unique
|
|||
as_json = response.json()
|
||||
|
||||
assert as_json["name"] == update_payload["name"]
|
||||
assert_ignore_keys(as_json["preferences"], update_payload["preferences"])
|
||||
assert_ignore_keys(as_json["preferences"], update_payload["preferences"]) # type: ignore
|
||||
|
||||
|
||||
def test_admin_delete_group(api_client: TestClient, admin_user: TestUser, unique_user: TestUser):
|
||||
# Delete User
|
||||
response = api_client.delete(api_routes.admin_users_item_id(unique_user.user_id), headers=admin_user.token)
|
||||
def test_admin_delete_group(unfiltered_database: AllRepositories, api_client: TestClient, admin_user: TestUser):
|
||||
group = unfiltered_database.groups.create({"name": random_string()})
|
||||
response = api_client.delete(api_routes.admin_groups_item_id(group.id), headers=admin_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Delete Group
|
||||
response = api_client.delete(api_routes.admin_groups_item_id(unique_user.group_id), headers=admin_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Ensure Group is Deleted
|
||||
response = api_client.get(api_routes.admin_groups_item_id(unique_user.group_id), headers=admin_user.token)
|
||||
response = api_client.get(api_routes.admin_groups_item_id(group.id), headers=admin_user.token)
|
||||
assert response.status_code == 404
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.assertion_helpers import assert_ignore_keys
|
||||
from tests.utils.factories import random_bool, random_string
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
def test_home_household_not_deletable(api_client: TestClient, admin_user: TestUser):
|
||||
response = api_client.delete(api_routes.admin_households_item_id(admin_user.household_id), headers=admin_user.token)
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_admin_household_routes_are_restricted(api_client: TestClient, unique_user: TestUser, admin_user: TestUser):
|
||||
response = api_client.get(api_routes.admin_households, headers=unique_user.token)
|
||||
assert response.status_code == 403
|
||||
|
||||
response = api_client.post(api_routes.admin_households, json={}, headers=unique_user.token)
|
||||
assert response.status_code == 403
|
||||
|
||||
response = api_client.get(api_routes.admin_households_item_id(admin_user.household_id), headers=unique_user.token)
|
||||
assert response.status_code == 403
|
||||
|
||||
response = api_client.get(api_routes.admin_households_item_id(admin_user.household_id), headers=unique_user.token)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_admin_create_household(api_client: TestClient, admin_user: TestUser):
|
||||
response = api_client.post(
|
||||
api_routes.admin_households,
|
||||
json={"name": random_string(), "groupId": admin_user.group_id},
|
||||
headers=admin_user.token,
|
||||
)
|
||||
assert response.status_code == 201
|
||||
|
||||
|
||||
def test_admin_update_household(api_client: TestClient, admin_user: TestUser, unique_user: TestUser):
|
||||
update_payload = {
|
||||
"id": unique_user.household_id,
|
||||
"groupId": admin_user.group_id,
|
||||
"name": "New Name",
|
||||
"preferences": {
|
||||
"privateHousehold": random_bool(),
|
||||
"firstDayOfWeek": 2,
|
||||
"recipePublic": random_bool(),
|
||||
"recipeShowNutrition": random_bool(),
|
||||
"recipeShowAssets": random_bool(),
|
||||
"recipeLandscapeView": random_bool(),
|
||||
"recipeDisableComments": random_bool(),
|
||||
"recipeDisableAmount": random_bool(),
|
||||
},
|
||||
}
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.admin_households_item_id(unique_user.household_id),
|
||||
json=update_payload,
|
||||
headers=admin_user.token,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
as_json = response.json()
|
||||
|
||||
assert as_json["name"] == update_payload["name"]
|
||||
assert_ignore_keys(as_json["preferences"], update_payload["preferences"]) # type: ignore
|
||||
|
||||
|
||||
def test_admin_delete_household(unfiltered_database: AllRepositories, api_client: TestClient, admin_user: TestUser):
|
||||
group = unfiltered_database.groups.create({"name": random_string()})
|
||||
household = unfiltered_database.households.create({"name": random_string(), "group_id": group.id})
|
||||
response = api_client.delete(api_routes.admin_households_item_id(household.id), headers=admin_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(api_routes.admin_households_item_id(household.id), headers=admin_user.token)
|
||||
assert response.status_code == 404
|
|
@ -32,7 +32,7 @@ def test_init_superuser(api_client: TestClient, admin_user: TestUser):
|
|||
|
||||
admin_data = response.json()
|
||||
|
||||
assert admin_data["id"] == admin_user.user_id
|
||||
assert admin_data["id"] == str(admin_user.user_id)
|
||||
assert admin_data["groupId"] == admin_user.group_id
|
||||
|
||||
assert admin_data["fullName"] == "Change Me"
|
||||
|
@ -93,7 +93,7 @@ def test_update_other_user_as_not_admin(api_client: TestClient, unique_user: Tes
|
|||
settings = get_app_settings()
|
||||
|
||||
update_data = {
|
||||
"id": unique_user.user_id,
|
||||
"id": str(unique_user.user_id),
|
||||
"fullName": "Updated Name",
|
||||
"email": settings._DEFAULT_EMAIL,
|
||||
"group": "Home",
|
||||
|
@ -122,7 +122,7 @@ def test_self_demote_admin(api_client: TestClient, admin_user: TestUser):
|
|||
|
||||
def test_self_promote_admin(api_client: TestClient, unique_user: TestUser):
|
||||
update_data = {
|
||||
"id": unique_user.user_id,
|
||||
"id": str(unique_user.user_id),
|
||||
"fullName": "Updated Name",
|
||||
"email": "user@example.com",
|
||||
"group": "Home",
|
||||
|
|
|
@ -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
|
||||
|
|
364
tests/integration_tests/test_repository_factory.py
Normal file
364
tests/integration_tests/test_repository_factory.py
Normal file
|
@ -0,0 +1,364 @@
|
|||
import inspect
|
||||
import time
|
||||
from functools import cached_property
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from pydantic import UUID4
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from mealie.db.models._model_base import SqlAlchemyBase
|
||||
from mealie.repos._utils import NOT_SET, NotSet
|
||||
from mealie.repos.all_repositories import get_repositories
|
||||
from mealie.repos.repository_generic import GroupRepositoryGeneric, HouseholdRepositoryGeneric, RepositoryGeneric
|
||||
from mealie.schema._mealie.mealie_model import MealieModel
|
||||
from mealie.schema.household.group_shopping_list import ShoppingListCreate
|
||||
from mealie.schema.household.webhook import SaveWebhook
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from mealie.schema.recipe.recipe_ingredient import SaveIngredientFood
|
||||
from mealie.schema.response.pagination import PaginationQuery
|
||||
from mealie.services.household_services.shopping_lists import ShoppingListService
|
||||
from tests.utils.factories import random_email, random_string
|
||||
|
||||
|
||||
@pytest.mark.parametrize("group_id", [uuid4(), None, NOT_SET])
|
||||
@pytest.mark.parametrize("household_id", [uuid4(), None, NOT_SET])
|
||||
def test_get_repositories_sets_ids(
|
||||
session: Session, group_id: UUID4 | None | NotSet, household_id: UUID4 | None | NotSet
|
||||
):
|
||||
kwargs = {}
|
||||
if not isinstance(group_id, NotSet):
|
||||
kwargs["group_id"] = group_id
|
||||
if not isinstance(household_id, NotSet):
|
||||
kwargs["household_id"] = household_id
|
||||
|
||||
repositories = get_repositories(session, **kwargs)
|
||||
assert repositories.group_id == group_id
|
||||
assert repositories.household_id == household_id
|
||||
|
||||
# test that sentinel is used correctly
|
||||
if isinstance(group_id, NotSet):
|
||||
assert repositories.group_id is NOT_SET
|
||||
if isinstance(household_id, NotSet):
|
||||
assert repositories.household_id is NOT_SET
|
||||
|
||||
|
||||
def test_repository_generic_constructor(session: Session):
|
||||
RepositoryGeneric(session, "id", MealieModel, SqlAlchemyBase)
|
||||
|
||||
|
||||
def test_repository_group_constructor(session: Session):
|
||||
BASE_ARGS = (session, "id", MealieModel, SqlAlchemyBase)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
GroupRepositoryGeneric(*BASE_ARGS, group_id=NOT_SET)
|
||||
|
||||
GroupRepositoryGeneric(*BASE_ARGS, group_id=None)
|
||||
GroupRepositoryGeneric(*BASE_ARGS, group_id=uuid4())
|
||||
|
||||
|
||||
def test_repository_household_constructor(session: Session):
|
||||
BASE_ARGS = (session, "id", MealieModel, SqlAlchemyBase)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
HouseholdRepositoryGeneric(*BASE_ARGS, group_id=NOT_SET, household_id=NOT_SET)
|
||||
HouseholdRepositoryGeneric(*BASE_ARGS, group_id=uuid4(), household_id=NOT_SET)
|
||||
HouseholdRepositoryGeneric(*BASE_ARGS, group_id=NOT_SET, household_id=uuid4())
|
||||
|
||||
HouseholdRepositoryGeneric(*BASE_ARGS, group_id=None, household_id=None)
|
||||
HouseholdRepositoryGeneric(*BASE_ARGS, group_id=uuid4(), household_id=None)
|
||||
HouseholdRepositoryGeneric(*BASE_ARGS, group_id=None, household_id=uuid4())
|
||||
HouseholdRepositoryGeneric(*BASE_ARGS, group_id=uuid4(), household_id=uuid4())
|
||||
|
||||
|
||||
@pytest.mark.parametrize("use_group_id", [True, False])
|
||||
@pytest.mark.parametrize("use_household_id", [True, False])
|
||||
def test_all_repositories_constructors(session: Session, use_group_id: bool, use_household_id: bool):
|
||||
kwargs = {}
|
||||
if use_group_id:
|
||||
kwargs["group_id"] = uuid4()
|
||||
if use_household_id:
|
||||
kwargs["household_id"] = uuid4()
|
||||
repositories = get_repositories(session, **kwargs)
|
||||
for name, member in inspect.getmembers(repositories.__class__):
|
||||
if not isinstance(member, cached_property):
|
||||
continue
|
||||
signature = inspect.signature(member.func)
|
||||
repo_type = signature.return_annotation
|
||||
try:
|
||||
if not issubclass(repo_type, RepositoryGeneric):
|
||||
continue
|
||||
except TypeError:
|
||||
continue
|
||||
|
||||
if issubclass(repo_type, HouseholdRepositoryGeneric):
|
||||
if not (use_group_id and use_household_id):
|
||||
with pytest.raises(ValueError):
|
||||
getattr(repositories, name)
|
||||
else:
|
||||
repo = getattr(repositories, name)
|
||||
assert repo.group_id == kwargs["group_id"]
|
||||
assert repo.household_id == kwargs["household_id"]
|
||||
elif issubclass(repo_type, GroupRepositoryGeneric):
|
||||
if not use_group_id:
|
||||
with pytest.raises(ValueError):
|
||||
getattr(repositories, name)
|
||||
else:
|
||||
repo = getattr(repositories, name)
|
||||
assert repo.group_id == kwargs["group_id"]
|
||||
assert repo.household_id is None
|
||||
else:
|
||||
repo = getattr(repositories, name)
|
||||
assert repo.group_id is None
|
||||
assert repo.household_id is None
|
||||
|
||||
|
||||
def test_group_repositories_filter_by_group(session: Session):
|
||||
unfiltered_repos = get_repositories(session, group_id=None, household_id=None)
|
||||
group_1 = unfiltered_repos.groups.create({"name": random_string()})
|
||||
group_2 = unfiltered_repos.groups.create({"name": random_string()})
|
||||
|
||||
group_1_repos = get_repositories(session, group_id=group_1.id, household_id=None)
|
||||
group_2_repos = get_repositories(session, group_id=group_2.id, household_id=None)
|
||||
food_1 = group_1_repos.ingredient_foods.create(
|
||||
SaveIngredientFood(id=uuid4(), group_id=group_1.id, name=random_string())
|
||||
)
|
||||
food_2 = group_2_repos.ingredient_foods.create(
|
||||
SaveIngredientFood(id=uuid4(), group_id=group_2.id, name=random_string())
|
||||
)
|
||||
|
||||
# unfiltered_repos should find both foods
|
||||
assert food_1 == unfiltered_repos.ingredient_foods.get_one(food_1.id)
|
||||
assert food_2 == unfiltered_repos.ingredient_foods.get_one(food_2.id)
|
||||
all_foods = unfiltered_repos.ingredient_foods.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert food_1 in all_foods
|
||||
assert food_2 in all_foods
|
||||
|
||||
# group_repos should only find foods with the correct group_id
|
||||
assert food_1 == group_1_repos.ingredient_foods.get_one(food_1.id)
|
||||
assert group_1_repos.ingredient_foods.get_one(food_2.id) is None
|
||||
assert [food_1] == group_1_repos.ingredient_foods.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
|
||||
assert group_2_repos.ingredient_foods.get_one(food_1.id) is None
|
||||
assert food_2 == group_2_repos.ingredient_foods.get_one(food_2.id)
|
||||
assert [food_2] == group_2_repos.ingredient_foods.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
|
||||
|
||||
def test_household_repositories_filter_by_household(session: Session):
|
||||
unfiltered_repos = get_repositories(session, group_id=None, household_id=None)
|
||||
group = unfiltered_repos.groups.create({"name": random_string()})
|
||||
group_repos = get_repositories(session, group_id=group.id, household_id=None)
|
||||
household_1 = group_repos.households.create({"name": random_string(), "group_id": group.id})
|
||||
household_2 = group_repos.households.create({"name": random_string(), "group_id": group.id})
|
||||
|
||||
household_1_repos = get_repositories(session, group_id=group.id, household_id=household_1.id)
|
||||
household_2_repos = get_repositories(session, group_id=group.id, household_id=household_2.id)
|
||||
webhook_1 = household_1_repos.webhooks.create(
|
||||
SaveWebhook(group_id=group.id, household_id=household_1.id, scheduled_time=time.time())
|
||||
)
|
||||
webhook_2 = household_2_repos.webhooks.create(
|
||||
SaveWebhook(group_id=group.id, household_id=household_2.id, scheduled_time=time.time())
|
||||
)
|
||||
|
||||
# unfiltered_repos and group_repos should find both webhooks
|
||||
for repos in [unfiltered_repos, group_repos]:
|
||||
assert webhook_1 == repos.webhooks.get_one(webhook_1.id)
|
||||
assert webhook_2 == repos.webhooks.get_one(webhook_2.id)
|
||||
all_webhooks = repos.webhooks.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert webhook_1 in all_webhooks
|
||||
assert webhook_2 in all_webhooks
|
||||
|
||||
# household_repos should only find webhooks with the correct household_id
|
||||
assert webhook_1 == household_1_repos.webhooks.get_one(webhook_1.id)
|
||||
assert household_1_repos.webhooks.get_one(webhook_2.id) is None
|
||||
assert [webhook_1] == household_1_repos.webhooks.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
|
||||
assert household_2_repos.webhooks.get_one(webhook_1.id) is None
|
||||
assert webhook_2 == household_2_repos.webhooks.get_one(webhook_2.id)
|
||||
assert [webhook_2] == household_2_repos.webhooks.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
|
||||
# a different group's repos shouldn't find anything
|
||||
other_group = unfiltered_repos.groups.create({"name": random_string()})
|
||||
for household_id in [household_1.id, household_2.id]:
|
||||
other_group_repos = get_repositories(session, group_id=other_group.id, household_id=household_id)
|
||||
assert other_group_repos.webhooks.get_one(webhook_1.id) is None
|
||||
assert other_group_repos.webhooks.get_one(webhook_2.id) is None
|
||||
assert other_group_repos.webhooks.page_all(PaginationQuery(page=1, per_page=-1)).items == []
|
||||
|
||||
|
||||
def test_recipe_repo_filter_by_household_with_proxy(session: Session):
|
||||
unfiltered_repos = get_repositories(session, group_id=None, household_id=None)
|
||||
group = unfiltered_repos.groups.create({"name": random_string()})
|
||||
group_repos = get_repositories(session, group_id=group.id, household_id=None)
|
||||
household_1 = group_repos.households.create({"name": random_string(), "group_id": group.id})
|
||||
household_2 = group_repos.households.create({"name": random_string(), "group_id": group.id})
|
||||
|
||||
user_1 = group_repos.users.create(
|
||||
{
|
||||
"username": random_string(),
|
||||
"email": random_email(),
|
||||
"group": group.name,
|
||||
"household": household_1.name,
|
||||
"full_name": random_string(),
|
||||
"password": random_string(),
|
||||
"admin": False,
|
||||
}
|
||||
)
|
||||
user_2 = group_repos.users.create(
|
||||
{
|
||||
"username": random_string(),
|
||||
"email": random_email(),
|
||||
"group": group.name,
|
||||
"household": household_2.name,
|
||||
"full_name": random_string(),
|
||||
"password": random_string(),
|
||||
"admin": False,
|
||||
}
|
||||
)
|
||||
|
||||
household_1_repos = get_repositories(session, group_id=group.id, household_id=household_1.id)
|
||||
household_2_repos = get_repositories(session, group_id=group.id, household_id=household_2.id)
|
||||
recipe_1 = household_1_repos.recipes.create(
|
||||
Recipe(
|
||||
user_id=user_1.id,
|
||||
group_id=group.id,
|
||||
name=random_string(),
|
||||
)
|
||||
)
|
||||
recipe_2 = household_2_repos.recipes.create(
|
||||
Recipe(
|
||||
user_id=user_2.id,
|
||||
group_id=group.id,
|
||||
name=random_string(),
|
||||
)
|
||||
)
|
||||
assert recipe_1.id and recipe_2.id
|
||||
|
||||
assert household_1_repos.recipes.get_one(recipe_1.slug) == recipe_1
|
||||
assert household_1_repos.recipes.get_one(recipe_2.slug) is None
|
||||
result = household_1_repos.recipes.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(result) == 1
|
||||
assert result[0].id == recipe_1.id
|
||||
|
||||
assert household_2_repos.recipes.get_one(recipe_1.slug) is None
|
||||
assert household_2_repos.recipes.get_one(recipe_2.slug) == recipe_2
|
||||
result = household_2_repos.recipes.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(result) == 1
|
||||
assert result[0].id == recipe_2.id
|
||||
|
||||
|
||||
def test_generic_repo_filter_by_household_with_proxy(session: Session):
|
||||
unfiltered_repos = get_repositories(session, group_id=None, household_id=None)
|
||||
group = unfiltered_repos.groups.create({"name": random_string()})
|
||||
group_repos = get_repositories(session, group_id=group.id, household_id=None)
|
||||
household_1 = group_repos.households.create({"name": random_string(), "group_id": group.id})
|
||||
household_2 = group_repos.households.create({"name": random_string(), "group_id": group.id})
|
||||
|
||||
user_1 = group_repos.users.create(
|
||||
{
|
||||
"username": random_string(),
|
||||
"email": random_email(),
|
||||
"group": group.name,
|
||||
"household": household_1.name,
|
||||
"full_name": random_string(),
|
||||
"password": random_string(),
|
||||
"admin": False,
|
||||
}
|
||||
)
|
||||
user_2 = group_repos.users.create(
|
||||
{
|
||||
"username": random_string(),
|
||||
"email": random_email(),
|
||||
"group": group.name,
|
||||
"household": household_2.name,
|
||||
"full_name": random_string(),
|
||||
"password": random_string(),
|
||||
"admin": False,
|
||||
}
|
||||
)
|
||||
|
||||
household_1_repos = get_repositories(session, group_id=group.id, household_id=household_1.id)
|
||||
household_2_repos = get_repositories(session, group_id=group.id, household_id=household_2.id)
|
||||
shopping_list_service_1 = ShoppingListService(household_1_repos)
|
||||
shopping_list_service_2 = ShoppingListService(household_2_repos)
|
||||
shopping_list_1 = shopping_list_service_1.create_one_list(ShoppingListCreate(name=random_string()), user_1.id)
|
||||
shopping_list_2 = shopping_list_service_2.create_one_list(ShoppingListCreate(name=random_string()), user_2.id)
|
||||
|
||||
assert household_1_repos.group_shopping_lists.get_one(shopping_list_1.id) == shopping_list_1
|
||||
assert household_1_repos.group_shopping_lists.get_one(shopping_list_2.id) is None
|
||||
result = household_1_repos.group_shopping_lists.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(result) == 1
|
||||
assert result[0].id == shopping_list_1.id
|
||||
|
||||
assert household_2_repos.group_shopping_lists.get_one(shopping_list_1.id) is None
|
||||
assert household_2_repos.group_shopping_lists.get_one(shopping_list_2.id) == shopping_list_2
|
||||
result = household_2_repos.group_shopping_lists.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(result) == 1
|
||||
assert result[0].id == shopping_list_2.id
|
||||
|
||||
|
||||
def test_changing_user_changes_household(session: Session):
|
||||
unfiltered_repos = get_repositories(session, group_id=None, household_id=None)
|
||||
group = unfiltered_repos.groups.create({"name": random_string()})
|
||||
group_repos = get_repositories(session, group_id=group.id, household_id=None)
|
||||
household_1 = group_repos.households.create({"name": random_string(), "group_id": group.id})
|
||||
household_2 = group_repos.households.create({"name": random_string(), "group_id": group.id})
|
||||
|
||||
user_1 = group_repos.users.create(
|
||||
{
|
||||
"username": random_string(),
|
||||
"email": random_email(),
|
||||
"group": group.name,
|
||||
"household": household_1.name,
|
||||
"full_name": random_string(),
|
||||
"password": random_string(),
|
||||
"admin": False,
|
||||
}
|
||||
)
|
||||
user_2 = group_repos.users.create(
|
||||
{
|
||||
"username": random_string(),
|
||||
"email": random_email(),
|
||||
"group": group.name,
|
||||
"household": household_2.name,
|
||||
"full_name": random_string(),
|
||||
"password": random_string(),
|
||||
"admin": False,
|
||||
}
|
||||
)
|
||||
|
||||
household_1_repos = get_repositories(session, group_id=group.id, household_id=household_1.id)
|
||||
household_2_repos = get_repositories(session, group_id=group.id, household_id=household_2.id)
|
||||
|
||||
# create shopping list with user_1/household_1
|
||||
shopping_list = ShoppingListService(household_1_repos).create_one_list(
|
||||
ShoppingListCreate(name=random_string()), user_1.id
|
||||
)
|
||||
|
||||
# only household_1_repos should find the list
|
||||
response = household_1_repos.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert response
|
||||
assert response.user_id == user_1.id
|
||||
response = household_2_repos.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert response is None
|
||||
|
||||
items = household_1_repos.group_shopping_lists.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(items) == 1
|
||||
assert items[0].id == shopping_list.id
|
||||
assert household_2_repos.group_shopping_lists.page_all(PaginationQuery(page=1, per_page=-1)).items == []
|
||||
|
||||
# update shopping list to user_2/household_2 using household_1_repos
|
||||
shopping_list.user_id = user_2.id
|
||||
household_1_repos.group_shopping_lists.update(shopping_list.id, shopping_list)
|
||||
|
||||
# now only household_2_repos should find the list
|
||||
response = household_1_repos.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert response is None
|
||||
response = household_2_repos.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert response
|
||||
assert response.user_id == user_2.id
|
||||
|
||||
items = household_2_repos.group_shopping_lists.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(items) == 1
|
||||
assert items[0].id == shopping_list.id
|
||||
assert household_1_repos.group_shopping_lists.page_all(PaginationQuery(page=1, per_page=-1)).items == []
|
|
@ -3,13 +3,12 @@ from uuid import UUID
|
|||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from tests.utils import api_routes, random_string
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
@dataclass()
|
||||
class SimpleCase:
|
||||
value: str
|
||||
is_valid: bool
|
||||
|
@ -41,8 +40,10 @@ def test_validators_email(api_client: TestClient, unique_user: TestUser):
|
|||
assert response_data["valid"] == user.is_valid
|
||||
|
||||
|
||||
def test_validators_group_name(api_client: TestClient, unique_user: TestUser, database: AllRepositories):
|
||||
def test_validators_group_name(api_client: TestClient, unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group
|
||||
|
||||
groups = [
|
||||
SimpleCase(value=group.name, is_valid=False),
|
||||
|
@ -65,7 +66,7 @@ class RecipeValidators:
|
|||
|
||||
def test_validators_recipe(api_client: TestClient, random_recipe: Recipe):
|
||||
recipes = [
|
||||
RecipeValidators(name=random_recipe.name, group=random_recipe.group_id, is_valid=False),
|
||||
RecipeValidators(name=random_recipe.name or "", group=random_recipe.group_id, is_valid=False),
|
||||
RecipeValidators(name=random_string(), group=random_recipe.group_id, is_valid=True),
|
||||
RecipeValidators(name=random_string(), group=random_recipe.group_id, is_valid=True),
|
||||
]
|
||||
|
|
|
@ -3,6 +3,7 @@ from fastapi.testclient import TestClient
|
|||
from mealie.schema.group.group_preferences import UpdateGroupPreferences
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.assertion_helpers import assert_ignore_keys
|
||||
from tests.utils.factories import random_bool
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
|
@ -12,8 +13,7 @@ def test_get_preferences(api_client: TestClient, unique_user: TestUser) -> None:
|
|||
|
||||
preferences = response.json()
|
||||
|
||||
assert preferences["recipePublic"] in {True, False}
|
||||
assert preferences["recipeShowNutrition"] in {True, False}
|
||||
assert preferences["privateGroup"] in {True, False}
|
||||
|
||||
|
||||
def test_preferences_in_group(api_client: TestClient, unique_user: TestUser) -> None:
|
||||
|
@ -26,12 +26,11 @@ def test_preferences_in_group(api_client: TestClient, unique_user: TestUser) ->
|
|||
assert group["preferences"] is not None
|
||||
|
||||
# Spot Check
|
||||
assert group["preferences"]["recipePublic"] in {True, False}
|
||||
assert group["preferences"]["recipeShowNutrition"] in {True, False}
|
||||
assert group["preferences"]["privateGroup"] in {True, False}
|
||||
|
||||
|
||||
def test_update_preferences(api_client: TestClient, unique_user: TestUser) -> None:
|
||||
new_data = UpdateGroupPreferences(recipe_public=False, recipe_show_nutrition=True)
|
||||
new_data = UpdateGroupPreferences(private_group=random_bool())
|
||||
|
||||
response = api_client.put(api_routes.groups_preferences, json=new_data.model_dump(), headers=unique_user.token)
|
||||
|
||||
|
@ -40,7 +39,6 @@ def test_update_preferences(api_client: TestClient, unique_user: TestUser) -> No
|
|||
preferences = response.json()
|
||||
|
||||
assert preferences is not None
|
||||
assert preferences["recipePublic"] is False
|
||||
assert preferences["recipeShowNutrition"] is True
|
||||
assert preferences["privateGroup"] == new_data.private_group
|
||||
|
||||
assert_ignore_keys(new_data.model_dump(by_alias=True), preferences, ["id", "groupId"])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.response.pagination import PaginationQuery
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
@ -11,46 +11,49 @@ def test_seed_invalid_locale(api_client: TestClient, unique_user: TestUser):
|
|||
assert resp.status_code == 422
|
||||
|
||||
|
||||
def test_seed_foods(api_client: TestClient, unique_user: TestUser, database: AllRepositories):
|
||||
def test_seed_foods(api_client: TestClient, unique_user: TestUser):
|
||||
CREATED_FOODS = 220
|
||||
database = unique_user.repos
|
||||
|
||||
# Check that the foods was created
|
||||
foods = database.ingredient_foods.by_group(unique_user.group_id).get_all()
|
||||
foods = database.ingredient_foods.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(foods) == 0
|
||||
|
||||
resp = api_client.post(api_routes.groups_seeders_foods, json={"locale": "en-US"}, headers=unique_user.token)
|
||||
assert resp.status_code == 200
|
||||
|
||||
# Check that the foods was created
|
||||
foods = database.ingredient_foods.by_group(unique_user.group_id).get_all()
|
||||
foods = database.ingredient_foods.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(foods) == CREATED_FOODS
|
||||
|
||||
|
||||
def test_seed_units(api_client: TestClient, unique_user: TestUser, database: AllRepositories):
|
||||
def test_seed_units(api_client: TestClient, unique_user: TestUser):
|
||||
CREATED_UNITS = 23
|
||||
database = unique_user.repos
|
||||
|
||||
# Check that the foods was created
|
||||
units = database.ingredient_units.by_group(unique_user.group_id).get_all()
|
||||
units = database.ingredient_units.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(units) == 0
|
||||
|
||||
resp = api_client.post(api_routes.groups_seeders_units, json={"locale": "en-US"}, headers=unique_user.token)
|
||||
assert resp.status_code == 200
|
||||
|
||||
# Check that the foods was created
|
||||
units = database.ingredient_units.by_group(unique_user.group_id).get_all()
|
||||
units = database.ingredient_units.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(units) == CREATED_UNITS
|
||||
|
||||
|
||||
def test_seed_labels(api_client: TestClient, unique_user: TestUser, database: AllRepositories):
|
||||
def test_seed_labels(api_client: TestClient, unique_user: TestUser):
|
||||
CREATED_LABELS = 21
|
||||
database = unique_user.repos
|
||||
|
||||
# Check that the foods was created
|
||||
labels = database.group_multi_purpose_labels.by_group(unique_user.group_id).get_all()
|
||||
labels = database.group_multi_purpose_labels.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(labels) == 0
|
||||
|
||||
resp = api_client.post(api_routes.groups_seeders_labels, json={"locale": "en-US"}, headers=unique_user.token)
|
||||
assert resp.status_code == 200
|
||||
|
||||
# Check that the foods was created
|
||||
labels = database.group_multi_purpose_labels.by_group(unique_user.group_id).get_all()
|
||||
labels = database.group_multi_purpose_labels.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
assert len(labels) == CREATED_LABELS
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from tests.utils import api_routes, random_int, random_string
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
def test_get_group_members(api_client: TestClient, unique_user: TestUser, h2_user: TestUser):
|
||||
response = api_client.get(api_routes.groups_members, headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
members = response.json()
|
||||
assert len(members) >= 2
|
||||
|
||||
all_ids = [x["id"] for x in members]
|
||||
|
||||
assert str(unique_user.user_id) in all_ids
|
||||
assert str(h2_user.user_id) in all_ids
|
||||
|
||||
|
||||
def test_get_group_members_filtered(api_client: TestClient, unique_user: TestUser, h2_user: TestUser):
|
||||
response = api_client.get(
|
||||
api_routes.groups_members, params={"householdId": h2_user.household_id}, headers=unique_user.token
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
members = response.json()
|
||||
assert len(members) >= 1
|
||||
|
||||
all_ids = [x["id"] for x in members]
|
||||
|
||||
assert str(unique_user.user_id) not in all_ids
|
||||
assert str(h2_user.user_id) in all_ids
|
||||
|
||||
|
||||
def test_get_households(api_client: TestClient, admin_user: TestUser):
|
||||
households = [admin_user.repos.households.create({"name": random_string()}) for _ in range(5)]
|
||||
response = api_client.get(api_routes.groups_households, headers=admin_user.token)
|
||||
response_ids = [item["id"] for item in response.json()]
|
||||
for household in households:
|
||||
assert str(household.id) in response_ids
|
||||
|
||||
|
||||
def test_get_households_filtered(unfiltered_database: AllRepositories, api_client: TestClient, admin_user: TestUser):
|
||||
group_1_id = admin_user.group_id
|
||||
group_2_id = str(unfiltered_database.groups.create({"name": random_string()}).id)
|
||||
|
||||
group_1_households = [
|
||||
unfiltered_database.households.create({"name": random_string(), "group_id": group_1_id})
|
||||
for _ in range(random_int(2, 5))
|
||||
]
|
||||
group_2_households = [
|
||||
unfiltered_database.households.create({"name": random_string(), "group_id": group_2_id})
|
||||
for _ in range(random_int(2, 5))
|
||||
]
|
||||
|
||||
response = api_client.get(api_routes.groups_households, headers=admin_user.token)
|
||||
response_ids = [item["id"] for item in response.json()]
|
||||
for household in group_1_households:
|
||||
assert str(household.id) in response_ids
|
||||
for household in group_2_households:
|
||||
assert str(household.id) not in response_ids
|
|
@ -6,7 +6,6 @@ import pytest
|
|||
from fastapi.testclient import TestClient
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.cookbook.cookbook import ReadCookBook, SaveCookBook
|
||||
from tests import utils
|
||||
from tests.utils import api_routes
|
||||
|
@ -14,7 +13,7 @@ from tests.utils.factories import random_string
|
|||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
def get_page_data(group_id: UUID | str):
|
||||
def get_page_data(group_id: UUID | str, household_id: UUID4 | str):
|
||||
name_and_slug = random_string(10)
|
||||
return {
|
||||
"name": name_and_slug,
|
||||
|
@ -23,6 +22,7 @@ def get_page_data(group_id: UUID | str):
|
|||
"position": 0,
|
||||
"categories": [],
|
||||
"group_id": str(group_id),
|
||||
"household_id": str(household_id),
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,11 +35,13 @@ class TestCookbook:
|
|||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def cookbooks(database: AllRepositories, unique_user: TestUser) -> list[TestCookbook]:
|
||||
def cookbooks(unique_user: TestUser) -> list[TestCookbook]:
|
||||
database = unique_user.repos
|
||||
|
||||
data: list[ReadCookBook] = []
|
||||
yield_data: list[TestCookbook] = []
|
||||
for _ in range(3):
|
||||
cb = database.cookbooks.create(SaveCookBook(**get_page_data(unique_user.group_id)))
|
||||
cb = database.cookbooks.create(SaveCookBook(**get_page_data(unique_user.group_id, unique_user.household_id)))
|
||||
data.append(cb)
|
||||
yield_data.append(TestCookbook(id=cb.id, slug=cb.slug, name=cb.name, data=cb.model_dump()))
|
||||
|
||||
|
@ -53,14 +55,14 @@ def cookbooks(database: AllRepositories, unique_user: TestUser) -> list[TestCook
|
|||
|
||||
|
||||
def test_create_cookbook(api_client: TestClient, unique_user: TestUser):
|
||||
page_data = get_page_data(unique_user.group_id)
|
||||
response = api_client.post(api_routes.groups_cookbooks, json=page_data, headers=unique_user.token)
|
||||
page_data = get_page_data(unique_user.group_id, unique_user.household_id)
|
||||
response = api_client.post(api_routes.households_cookbooks, json=page_data, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
|
||||
def test_read_cookbook(api_client: TestClient, unique_user: TestUser, cookbooks: list[TestCookbook]):
|
||||
sample = random.choice(cookbooks)
|
||||
response = api_client.get(api_routes.groups_cookbooks_item_id(sample.id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_cookbooks_item_id(sample.id), headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
page_data = response.json()
|
||||
|
@ -74,16 +76,16 @@ def test_read_cookbook(api_client: TestClient, unique_user: TestUser, cookbooks:
|
|||
def test_update_cookbook(api_client: TestClient, unique_user: TestUser, cookbooks: list[TestCookbook]):
|
||||
cookbook = random.choice(cookbooks)
|
||||
|
||||
update_data = get_page_data(unique_user.group_id)
|
||||
update_data = get_page_data(unique_user.group_id, unique_user.household_id)
|
||||
|
||||
update_data["name"] = random_string(10)
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_cookbooks_item_id(cookbook.id), json=update_data, headers=unique_user.token
|
||||
api_routes.households_cookbooks_item_id(cookbook.id), json=update_data, headers=unique_user.token
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(api_routes.groups_cookbooks_item_id(cookbook.id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_cookbooks_item_id(cookbook.id), headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
page_data = response.json()
|
||||
|
@ -99,10 +101,12 @@ def test_update_cookbooks_many(api_client: TestClient, unique_user: TestUser, co
|
|||
page["position"] = x
|
||||
page["group_id"] = str(unique_user.group_id)
|
||||
|
||||
response = api_client.put(api_routes.groups_cookbooks, json=utils.jsonify(reverse_order), headers=unique_user.token)
|
||||
response = api_client.put(
|
||||
api_routes.households_cookbooks, json=utils.jsonify(reverse_order), headers=unique_user.token
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(api_routes.groups_cookbooks, headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_cookbooks, headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
known_ids = [x.id for x in cookbooks]
|
||||
|
@ -115,9 +119,9 @@ def test_update_cookbooks_many(api_client: TestClient, unique_user: TestUser, co
|
|||
|
||||
def test_delete_cookbook(api_client: TestClient, unique_user: TestUser, cookbooks: list[TestCookbook]):
|
||||
sample = random.choice(cookbooks)
|
||||
response = api_client.delete(api_routes.groups_cookbooks_item_id(sample.id), headers=unique_user.token)
|
||||
response = api_client.delete(api_routes.households_cookbooks_item_id(sample.id), headers=unique_user.token)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(api_routes.groups_cookbooks_item_id(sample.slug), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_cookbooks_item_id(sample.slug), headers=unique_user.token)
|
||||
assert response.status_code == 404
|
|
@ -9,7 +9,7 @@ from tests.utils.fixture_schemas import TestUser
|
|||
@pytest.fixture(scope="function")
|
||||
def invite(api_client: TestClient, unique_user: TestUser) -> None:
|
||||
# Test Creation
|
||||
r = api_client.post(api_routes.groups_invitations, json={"uses": 2}, headers=unique_user.token)
|
||||
r = api_client.post(api_routes.households_invitations, json={"uses": 2}, headers=unique_user.token)
|
||||
assert r.status_code == 201
|
||||
invitation = r.json()
|
||||
return invitation["token"]
|
||||
|
@ -17,7 +17,7 @@ def invite(api_client: TestClient, unique_user: TestUser) -> None:
|
|||
|
||||
def test_get_all_invitation(api_client: TestClient, unique_user: TestUser, invite: str) -> None:
|
||||
# Get All Invites
|
||||
r = api_client.get(api_routes.groups_invitations, headers=unique_user.token)
|
||||
r = api_client.get(api_routes.households_invitations, headers=unique_user.token)
|
||||
|
||||
assert r.status_code == 200
|
||||
|
||||
|
@ -27,13 +27,15 @@ def test_get_all_invitation(api_client: TestClient, unique_user: TestUser, invit
|
|||
|
||||
for item in items:
|
||||
assert item["groupId"] == unique_user.group_id
|
||||
assert item["householdId"] == unique_user.household_id
|
||||
assert item["token"] == invite
|
||||
|
||||
|
||||
def register_user(api_client, invite):
|
||||
def register_user(api_client: TestClient, invite: str):
|
||||
# Test User can Join Group
|
||||
registration = user_registration_factory()
|
||||
registration.group = ""
|
||||
registration.household = ""
|
||||
registration.group_token = invite
|
||||
|
||||
response = api_client.post(api_routes.users_register, json=registration.model_dump(by_alias=True))
|
||||
|
@ -52,11 +54,12 @@ def test_group_invitation_link(api_client: TestClient, unique_user: TestUser, in
|
|||
token = r.json().get("access_token")
|
||||
assert token is not None
|
||||
|
||||
# Check user Group is Same
|
||||
# Check user Group and Household match
|
||||
r = api_client.get(api_routes.users_self, headers={"Authorization": f"Bearer {token}"})
|
||||
|
||||
assert r.status_code == 200
|
||||
assert r.json()["groupId"] == unique_user.group_id
|
||||
assert r.json()["householdId"] == unique_user.household_id
|
||||
|
||||
|
||||
def test_group_invitation_delete_after_uses(api_client: TestClient, invite: str) -> None:
|
|
@ -9,7 +9,9 @@ from tests.utils.fixture_schemas import TestUser
|
|||
|
||||
|
||||
def route_all_slice(page: int, perPage: int, start_date: str, end_date: str):
|
||||
return f"{api_routes.groups_mealplans}?page={page}&perPage={perPage}&start_date={start_date}&end_date={end_date}"
|
||||
return (
|
||||
f"{api_routes.households_mealplans}?page={page}&perPage={perPage}&start_date={start_date}&end_date={end_date}"
|
||||
)
|
||||
|
||||
|
||||
def test_create_mealplan_no_recipe(api_client: TestClient, unique_user: TestUser):
|
||||
|
@ -20,7 +22,7 @@ def test_create_mealplan_no_recipe(api_client: TestClient, unique_user: TestUser
|
|||
).model_dump()
|
||||
new_plan["date"] = datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
|
||||
|
||||
response = api_client.post(api_routes.groups_mealplans, json=new_plan, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
|
||||
|
||||
assert response.status_code == 201
|
||||
|
||||
|
@ -44,7 +46,7 @@ def test_create_mealplan_with_recipe(api_client: TestClient, unique_user: TestUs
|
|||
new_plan["date"] = datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
|
||||
new_plan["recipeId"] = str(recipe_id)
|
||||
|
||||
response = api_client.post(api_routes.groups_mealplans, json=new_plan, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
|
||||
response_json = response.json()
|
||||
assert response.status_code == 201
|
||||
|
||||
|
@ -61,7 +63,7 @@ def test_crud_mealplan(api_client: TestClient, unique_user: TestUser):
|
|||
|
||||
# Create
|
||||
new_plan["date"] = datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
|
||||
response = api_client.post(api_routes.groups_mealplans, json=new_plan, headers=unique_user.token)
|
||||
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"]
|
||||
|
@ -71,7 +73,7 @@ def test_crud_mealplan(api_client: TestClient, unique_user: TestUser):
|
|||
response_json["text"] = random_string()
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_mealplans_item_id(plan_id), headers=unique_user.token, json=response_json
|
||||
api_routes.households_mealplans_item_id(plan_id), headers=unique_user.token, json=response_json
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
@ -80,11 +82,11 @@ def test_crud_mealplan(api_client: TestClient, unique_user: TestUser):
|
|||
assert response.json()["text"] == response_json["text"]
|
||||
|
||||
# Delete
|
||||
response = api_client.delete(api_routes.groups_mealplans_item_id(plan_id), headers=unique_user.token)
|
||||
response = api_client.delete(api_routes.households_mealplans_item_id(plan_id), headers=unique_user.token)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(api_routes.groups_mealplans_item_id(plan_id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_mealplans_item_id(plan_id), headers=unique_user.token)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
|
@ -98,10 +100,12 @@ def test_get_all_mealplans(api_client: TestClient, unique_user: TestUser):
|
|||
).model_dump()
|
||||
|
||||
new_plan["date"] = datetime.now(timezone.utc).date().strftime("%Y-%m-%d")
|
||||
response = api_client.post(api_routes.groups_mealplans, json=new_plan, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
response = api_client.get(api_routes.groups_mealplans, headers=unique_user.token, params={"page": 1, "perPage": -1})
|
||||
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
|
||||
|
@ -120,7 +124,7 @@ def test_get_slice_mealplans(api_client: TestClient, unique_user: TestUser):
|
|||
# Add the meal plans to the database
|
||||
for meal_plan in meal_plans:
|
||||
meal_plan["date"] = meal_plan["date"].strftime("%Y-%m-%d")
|
||||
response = api_client.post(api_routes.groups_mealplans, json=meal_plan, headers=unique_user.token)
|
||||
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
|
||||
|
@ -151,11 +155,11 @@ def test_get_mealplan_today(api_client: TestClient, unique_user: TestUser):
|
|||
# Add the meal plans to the database
|
||||
for meal_plan in test_meal_plans:
|
||||
meal_plan["date"] = meal_plan["date"].strftime("%Y-%m-%d")
|
||||
response = api_client.post(api_routes.groups_mealplans, json=meal_plan, headers=unique_user.token)
|
||||
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
|
||||
response = api_client.get(api_routes.groups_mealplans_today, headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_mealplans_today, headers=unique_user.token)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
|
@ -3,8 +3,7 @@ from uuid import UUID
|
|||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.all_repositories import AllRepositories
|
||||
from mealie.schema.meal_plan.plan_rules import PlanRulesOut, PlanRulesSave
|
||||
from mealie.schema.meal_plan.plan_rules import PlanRulesOut
|
||||
from mealie.schema.recipe.recipe import RecipeCategory
|
||||
from mealie.schema.recipe.recipe_category import CategorySave
|
||||
from tests import utils
|
||||
|
@ -13,10 +12,8 @@ from tests.utils.fixture_schemas import TestUser
|
|||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def category(
|
||||
database: AllRepositories,
|
||||
unique_user: TestUser,
|
||||
):
|
||||
def category(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
slug = utils.random_string(length=10)
|
||||
model = database.categories.create(CategorySave(group_id=unique_user.group_id, slug=slug, name=slug))
|
||||
|
||||
|
@ -29,42 +26,45 @@ def category(
|
|||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def plan_rule(database: AllRepositories, unique_user: TestUser):
|
||||
schema = PlanRulesSave(
|
||||
group_id=unique_user.group_id,
|
||||
day="monday",
|
||||
entry_type="breakfast",
|
||||
categories=[],
|
||||
)
|
||||
|
||||
model = database.group_meal_plan_rules.create(schema)
|
||||
|
||||
yield model
|
||||
|
||||
try:
|
||||
database.group_meal_plan_rules.delete(model.id)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def test_group_mealplan_rules_create(
|
||||
api_client: TestClient, unique_user: TestUser, category: RecipeCategory, database: AllRepositories
|
||||
):
|
||||
def plan_rule(api_client: TestClient, unique_user: TestUser):
|
||||
payload = {
|
||||
"groupId": unique_user.group_id,
|
||||
"householdId": unique_user.household_id,
|
||||
"day": "monday",
|
||||
"entryType": "breakfast",
|
||||
"categories": [],
|
||||
}
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.households_mealplans_rules, json=utils.jsonify(payload), headers=unique_user.token
|
||||
)
|
||||
assert response.status_code == 201
|
||||
plan_rule = PlanRulesOut.model_validate(response.json())
|
||||
yield plan_rule
|
||||
|
||||
# cleanup
|
||||
api_client.delete(api_routes.households_mealplans_rules_item_id(plan_rule.id), headers=unique_user.token)
|
||||
|
||||
|
||||
def test_group_mealplan_rules_create(api_client: TestClient, unique_user: TestUser, category: RecipeCategory):
|
||||
database = unique_user.repos
|
||||
payload = {
|
||||
"groupId": unique_user.group_id,
|
||||
"householdId": unique_user.household_id,
|
||||
"day": "monday",
|
||||
"entryType": "breakfast",
|
||||
"categories": [category.model_dump()],
|
||||
}
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_mealplans_rules, json=utils.jsonify(payload), headers=unique_user.token
|
||||
api_routes.households_mealplans_rules, json=utils.jsonify(payload), headers=unique_user.token
|
||||
)
|
||||
assert response.status_code == 201
|
||||
|
||||
# Validate the response data
|
||||
response_data = response.json()
|
||||
assert response_data["groupId"] == str(unique_user.group_id)
|
||||
assert response_data["householdId"] == str(unique_user.household_id)
|
||||
assert response_data["day"] == "monday"
|
||||
assert response_data["entryType"] == "breakfast"
|
||||
assert len(response_data["categories"]) == 1
|
||||
|
@ -72,8 +72,10 @@ def test_group_mealplan_rules_create(
|
|||
|
||||
# Validate database entry
|
||||
rule = database.group_meal_plan_rules.get_one(UUID(response_data["id"]))
|
||||
assert rule
|
||||
|
||||
assert str(rule.group_id) == unique_user.group_id
|
||||
assert str(rule.household_id) == unique_user.household_id
|
||||
assert rule.day == "monday"
|
||||
assert rule.entry_type == "breakfast"
|
||||
assert len(rule.categories) == 1
|
||||
|
@ -84,13 +86,14 @@ def test_group_mealplan_rules_create(
|
|||
|
||||
|
||||
def test_group_mealplan_rules_read(api_client: TestClient, unique_user: TestUser, plan_rule: PlanRulesOut):
|
||||
response = api_client.get(api_routes.groups_mealplans_rules_item_id(plan_rule.id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_mealplans_rules_item_id(plan_rule.id), headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Validate the response data
|
||||
response_data = response.json()
|
||||
assert response_data["id"] == str(plan_rule.id)
|
||||
assert response_data["groupId"] == str(unique_user.group_id)
|
||||
assert response_data["householdId"] == str(unique_user.household_id)
|
||||
assert response_data["day"] == "monday"
|
||||
assert response_data["entryType"] == "breakfast"
|
||||
assert len(response_data["categories"]) == 0
|
||||
|
@ -99,12 +102,13 @@ def test_group_mealplan_rules_read(api_client: TestClient, unique_user: TestUser
|
|||
def test_group_mealplan_rules_update(api_client: TestClient, unique_user: TestUser, plan_rule: PlanRulesOut):
|
||||
payload = {
|
||||
"groupId": unique_user.group_id,
|
||||
"householdId": unique_user.household_id,
|
||||
"day": "tuesday",
|
||||
"entryType": "lunch",
|
||||
}
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_mealplans_rules_item_id(plan_rule.id), json=payload, headers=unique_user.token
|
||||
api_routes.households_mealplans_rules_item_id(plan_rule.id), json=payload, headers=unique_user.token
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
@ -112,16 +116,18 @@ def test_group_mealplan_rules_update(api_client: TestClient, unique_user: TestUs
|
|||
response_data = response.json()
|
||||
assert response_data["id"] == str(plan_rule.id)
|
||||
assert response_data["groupId"] == str(unique_user.group_id)
|
||||
assert response_data["householdId"] == str(unique_user.household_id)
|
||||
assert response_data["day"] == "tuesday"
|
||||
assert response_data["entryType"] == "lunch"
|
||||
assert len(response_data["categories"]) == 0
|
||||
|
||||
|
||||
def test_group_mealplan_rules_delete(
|
||||
api_client: TestClient, unique_user: TestUser, plan_rule: PlanRulesOut, database: AllRepositories
|
||||
):
|
||||
response = api_client.delete(api_routes.groups_mealplans_rules_item_id(plan_rule.id), headers=unique_user.token)
|
||||
def test_group_mealplan_rules_delete(api_client: TestClient, unique_user: TestUser, plan_rule: PlanRulesOut):
|
||||
response = api_client.get(api_routes.households_mealplans_rules_item_id(plan_rule.id), headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Validate no entry in database
|
||||
assert database.group_meal_plan_rules.get_one(plan_rule.id) is None
|
||||
response = api_client.delete(api_routes.households_mealplans_rules_item_id(plan_rule.id), headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(api_routes.households_mealplans_rules_item_id(plan_rule.id), headers=unique_user.token)
|
||||
assert response.status_code == 404
|
|
@ -1,6 +1,6 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.schema.group.group_events import GroupEventNotifierCreate, GroupEventNotifierOptions
|
||||
from mealie.schema.household.group_events import GroupEventNotifierCreate, GroupEventNotifierOptions
|
||||
from mealie.services.event_bus_service.event_bus_listeners import AppriseEventListener
|
||||
from mealie.services.event_bus_service.event_bus_service import Event
|
||||
from mealie.services.event_bus_service.event_types import (
|
||||
|
@ -59,7 +59,7 @@ def event_generator():
|
|||
|
||||
def test_create_notification(api_client: TestClient, unique_user: TestUser):
|
||||
payload = notifier_generator()
|
||||
response = api_client.post(api_routes.groups_events_notifications, json=payload, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_events_notifications, json=payload, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
payload_as_dict = response.json()
|
||||
|
@ -72,13 +72,13 @@ def test_create_notification(api_client: TestClient, unique_user: TestUser):
|
|||
|
||||
# Cleanup
|
||||
response = api_client.delete(
|
||||
api_routes.groups_events_notifications_item_id(payload_as_dict["id"]), headers=unique_user.token
|
||||
api_routes.households_events_notifications_item_id(payload_as_dict["id"]), headers=unique_user.token
|
||||
)
|
||||
|
||||
|
||||
def test_ensure_apprise_url_is_secret(api_client: TestClient, unique_user: TestUser):
|
||||
payload = notifier_generator()
|
||||
response = api_client.post(api_routes.groups_events_notifications, json=payload, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_events_notifications, json=payload, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
payload_as_dict = response.json()
|
||||
|
@ -89,7 +89,7 @@ def test_ensure_apprise_url_is_secret(api_client: TestClient, unique_user: TestU
|
|||
|
||||
def test_update_apprise_notification(api_client: TestClient, unique_user: TestUser):
|
||||
payload = notifier_generator()
|
||||
response = api_client.post(api_routes.groups_events_notifications, json=payload, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_events_notifications, json=payload, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
update_payload = response.json()
|
||||
|
@ -100,7 +100,7 @@ def test_update_apprise_notification(api_client: TestClient, unique_user: TestUs
|
|||
update_payload["options"] = preferences_generator()
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_events_notifications_item_id(update_payload["id"]),
|
||||
api_routes.households_events_notifications_item_id(update_payload["id"]),
|
||||
json=update_payload,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -109,7 +109,7 @@ def test_update_apprise_notification(api_client: TestClient, unique_user: TestUs
|
|||
|
||||
# Re-Get The Item
|
||||
response = api_client.get(
|
||||
api_routes.groups_events_notifications_item_id(update_payload["id"]), headers=unique_user.token
|
||||
api_routes.households_events_notifications_item_id(update_payload["id"]), headers=unique_user.token
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
@ -122,24 +122,24 @@ def test_update_apprise_notification(api_client: TestClient, unique_user: TestUs
|
|||
|
||||
# Cleanup
|
||||
response = api_client.delete(
|
||||
api_routes.groups_events_notifications_item_id(update_payload["id"]), headers=unique_user.token
|
||||
api_routes.households_events_notifications_item_id(update_payload["id"]), headers=unique_user.token
|
||||
)
|
||||
|
||||
|
||||
def test_delete_apprise_notification(api_client: TestClient, unique_user: TestUser):
|
||||
payload = notifier_generator()
|
||||
response = api_client.post(api_routes.groups_events_notifications, json=payload, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_events_notifications, json=payload, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
payload_as_dict = response.json()
|
||||
|
||||
response = api_client.delete(
|
||||
api_routes.groups_events_notifications_item_id(payload_as_dict["id"]), headers=unique_user.token
|
||||
api_routes.households_events_notifications_item_id(payload_as_dict["id"]), headers=unique_user.token
|
||||
)
|
||||
assert response.status_code == 204
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_events_notifications_item_id(payload_as_dict["id"]), headers=unique_user.token
|
||||
api_routes.households_events_notifications_item_id(payload_as_dict["id"]), headers=unique_user.token
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.schema.group.group_recipe_action import (
|
||||
from mealie.schema.household.group_recipe_action import (
|
||||
CreateGroupRecipeAction,
|
||||
GroupRecipeActionOut,
|
||||
GroupRecipeActionType,
|
||||
|
@ -22,7 +22,7 @@ def new_link_action() -> CreateGroupRecipeAction:
|
|||
def test_group_recipe_actions_create_one(api_client: TestClient, unique_user: TestUser):
|
||||
action_in = new_link_action()
|
||||
response = api_client.post(
|
||||
api_routes.groups_recipe_actions,
|
||||
api_routes.households_recipe_actions,
|
||||
json=action_in.model_dump(),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -31,6 +31,7 @@ def test_group_recipe_actions_create_one(api_client: TestClient, unique_user: Te
|
|||
action_out = GroupRecipeActionOut(**data)
|
||||
assert action_out.id
|
||||
assert str(action_out.group_id) == unique_user.group_id
|
||||
assert str(action_out.household_id) == unique_user.household_id
|
||||
assert action_out.action_type == action_in.action_type
|
||||
assert action_out.title == action_in.title
|
||||
assert action_out.url == action_in.url
|
||||
|
@ -40,14 +41,14 @@ def test_group_recipe_actions_get_all(api_client: TestClient, unique_user: TestU
|
|||
expected_ids: set[str] = set()
|
||||
for _ in range(random_int(3, 5)):
|
||||
response = api_client.post(
|
||||
api_routes.groups_recipe_actions,
|
||||
api_routes.households_recipe_actions,
|
||||
json=new_link_action().model_dump(),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
data = assert_deserialize(response, 201)
|
||||
expected_ids.add(data["id"])
|
||||
|
||||
response = api_client.get(api_routes.groups_recipe_actions, headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_recipe_actions, headers=unique_user.token)
|
||||
data = assert_deserialize(response, 200)
|
||||
fetched_ids = {item["id"] for item in data["items"]}
|
||||
for expected_id in expected_ids:
|
||||
|
@ -60,7 +61,7 @@ def test_group_recipe_actions_get_one(
|
|||
):
|
||||
action_in = new_link_action()
|
||||
response = api_client.post(
|
||||
api_routes.groups_recipe_actions,
|
||||
api_routes.households_recipe_actions,
|
||||
json=action_in.model_dump(),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -73,7 +74,7 @@ def test_group_recipe_actions_get_one(
|
|||
fetch_user = g2_user
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_recipe_actions_item_id(expected_action_out.id),
|
||||
api_routes.households_recipe_actions_item_id(expected_action_out.id),
|
||||
headers=fetch_user.token,
|
||||
)
|
||||
if not is_own_group:
|
||||
|
@ -88,7 +89,7 @@ def test_group_recipe_actions_get_one(
|
|||
def test_group_recipe_actions_update_one(api_client: TestClient, unique_user: TestUser):
|
||||
action_in = new_link_action()
|
||||
response = api_client.post(
|
||||
api_routes.groups_recipe_actions,
|
||||
api_routes.households_recipe_actions,
|
||||
json=action_in.model_dump(),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -98,7 +99,7 @@ def test_group_recipe_actions_update_one(api_client: TestClient, unique_user: Te
|
|||
new_title = random_string()
|
||||
data["title"] = new_title
|
||||
response = api_client.put(
|
||||
api_routes.groups_recipe_actions_item_id(action_id),
|
||||
api_routes.households_recipe_actions_item_id(action_id),
|
||||
json=data,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -111,15 +112,15 @@ def test_group_recipe_actions_update_one(api_client: TestClient, unique_user: Te
|
|||
def test_group_recipe_actions_delete_one(api_client: TestClient, unique_user: TestUser):
|
||||
action_in = new_link_action()
|
||||
response = api_client.post(
|
||||
api_routes.groups_recipe_actions,
|
||||
api_routes.households_recipe_actions,
|
||||
json=action_in.model_dump(),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
data = assert_deserialize(response, 201)
|
||||
action_id = data["id"]
|
||||
|
||||
response = api_client.delete(api_routes.groups_recipe_actions_item_id(action_id), headers=unique_user.token)
|
||||
response = api_client.delete(api_routes.households_recipe_actions_item_id(action_id), headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(api_routes.groups_recipe_actions_item_id(action_id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_recipe_actions_item_id(action_id), headers=unique_user.token)
|
||||
assert response.status_code == 404
|
|
@ -7,7 +7,7 @@ from fastapi.testclient import TestClient
|
|||
from pydantic import UUID4
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.group.group_shopping_list import ShoppingListItemOut, ShoppingListOut
|
||||
from mealie.schema.household.group_shopping_list import ShoppingListItemOut, ShoppingListOut
|
||||
from mealie.schema.recipe.recipe_ingredient import SaveIngredientFood
|
||||
from tests import utils
|
||||
from tests.utils import api_routes
|
||||
|
@ -42,14 +42,14 @@ def test_shopping_list_items_create_one(
|
|||
) -> None:
|
||||
item = create_item(shopping_list.id)
|
||||
|
||||
response = api_client.post(api_routes.groups_shopping_items, json=item, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_shopping_items, json=item, headers=unique_user.token)
|
||||
as_json = utils.assert_deserialize(response, 201)
|
||||
assert len(as_json["createdItems"]) == 1
|
||||
|
||||
# Test Item is Getable
|
||||
created_item_id = as_json["createdItems"][0]["id"]
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_items_item_id(created_item_id),
|
||||
api_routes.households_shopping_items_item_id(created_item_id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -59,7 +59,7 @@ def test_shopping_list_items_create_one(
|
|||
|
||||
# Test Item In List
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
response_list = utils.assert_deserialize(response, 200)
|
||||
|
@ -76,7 +76,7 @@ def test_shopping_list_items_create_many(
|
|||
items = [create_item(shopping_list.id) for _ in range(10)]
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_items_create_bulk,
|
||||
api_routes.households_shopping_items_create_bulk,
|
||||
json=items,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -88,7 +88,7 @@ def test_shopping_list_items_create_many(
|
|||
# test items in list
|
||||
created_item_ids = [item["id"] for item in as_json["createdItems"]]
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -107,15 +107,13 @@ def test_shopping_list_items_create_many(
|
|||
|
||||
|
||||
def test_shopping_list_items_auto_assign_label_with_food_without_label(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
shopping_list: ShoppingListOut,
|
||||
database: AllRepositories,
|
||||
api_client: TestClient, unique_user: TestUser, shopping_list: ShoppingListOut
|
||||
):
|
||||
database = unique_user.repos
|
||||
food = database.ingredient_foods.create(SaveIngredientFood(name=random_string(10), group_id=unique_user.group_id))
|
||||
|
||||
item = create_item(shopping_list.id, food_id=str(food.id))
|
||||
response = api_client.post(api_routes.groups_shopping_items, json=item, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_shopping_items, json=item, headers=unique_user.token)
|
||||
as_json = utils.assert_deserialize(response, 201)
|
||||
assert len(as_json["createdItems"]) == 1
|
||||
|
||||
|
@ -125,18 +123,16 @@ def test_shopping_list_items_auto_assign_label_with_food_without_label(
|
|||
|
||||
|
||||
def test_shopping_list_items_auto_assign_label_with_food_with_label(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
shopping_list: ShoppingListOut,
|
||||
database: AllRepositories,
|
||||
api_client: TestClient, unique_user: TestUser, shopping_list: ShoppingListOut
|
||||
):
|
||||
database = unique_user.repos
|
||||
label = database.group_multi_purpose_labels.create({"name": random_string(10), "group_id": unique_user.group_id})
|
||||
food = database.ingredient_foods.create(
|
||||
SaveIngredientFood(name=random_string(10), group_id=unique_user.group_id, label_id=label.id)
|
||||
)
|
||||
|
||||
item = create_item(shopping_list.id, food_id=str(food.id))
|
||||
response = api_client.post(api_routes.groups_shopping_items, json=item, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_shopping_items, json=item, headers=unique_user.token)
|
||||
as_json = utils.assert_deserialize(response, 201)
|
||||
assert len(as_json["createdItems"]) == 1
|
||||
|
||||
|
@ -151,9 +147,9 @@ def test_shopping_list_items_auto_assign_label_with_food_search(
|
|||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
shopping_list: ShoppingListOut,
|
||||
database: AllRepositories,
|
||||
use_fuzzy_name: bool,
|
||||
):
|
||||
database = unique_user.repos
|
||||
label = database.group_multi_purpose_labels.create({"name": random_string(10), "group_id": unique_user.group_id})
|
||||
food = database.ingredient_foods.create(
|
||||
SaveIngredientFood(name=random_string(20), group_id=unique_user.group_id, label_id=label.id)
|
||||
|
@ -165,7 +161,7 @@ def test_shopping_list_items_auto_assign_label_with_food_search(
|
|||
name = name + random_string(2)
|
||||
item["note"] = name
|
||||
|
||||
response = api_client.post(api_routes.groups_shopping_items, json=item, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_shopping_items, json=item, headers=unique_user.token)
|
||||
as_json = utils.assert_deserialize(response, 201)
|
||||
assert len(as_json["createdItems"]) == 1
|
||||
|
||||
|
@ -183,7 +179,7 @@ def test_shopping_list_items_get_one(
|
|||
for _ in range(3):
|
||||
item = random.choice(list_with_items.list_items)
|
||||
|
||||
response = api_client.get(api_routes.groups_shopping_items_item_id(item.id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_shopping_items_item_id(item.id), headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
|
@ -197,13 +193,13 @@ def test_shopping_list_items_get_all(
|
|||
"perPage": -1,
|
||||
"queryFilter": f"shopping_list_id={list_with_items.id}",
|
||||
}
|
||||
response = api_client.get(api_routes.groups_shopping_items, params=params, headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_shopping_items, params=params, headers=unique_user.token)
|
||||
pagination_json = utils.assert_deserialize(response, 200)
|
||||
assert len(pagination_json["items"]) == len(list_with_items.list_items)
|
||||
|
||||
|
||||
def test_shopping_list_items_get_one_404(api_client: TestClient, unique_user: TestUser) -> None:
|
||||
response = api_client.get(api_routes.groups_shopping_items_item_id(uuid4()), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_shopping_items_item_id(uuid4()), headers=unique_user.token)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
|
@ -221,7 +217,7 @@ def test_shopping_list_items_update_one(
|
|||
update_data["id"] = str(item.id)
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items_item_id(item.id),
|
||||
api_routes.households_shopping_items_item_id(item.id),
|
||||
json=update_data,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -235,7 +231,7 @@ def test_shopping_list_items_update_one(
|
|||
|
||||
# make sure the list didn't change sizes
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(list_with_items.id),
|
||||
api_routes.households_shopping_lists_item_id(list_with_items.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -251,7 +247,7 @@ def test_shopping_list_items_update_many(
|
|||
item["quantity"] += 10
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_items_create_bulk,
|
||||
api_routes.households_shopping_items_create_bulk,
|
||||
json=items,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -265,7 +261,7 @@ def test_shopping_list_items_update_many(
|
|||
item_quantity_map[update_item["id"]] = update_item["quantity"]
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items,
|
||||
api_routes.households_shopping_items,
|
||||
json=as_json["createdItems"],
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -277,7 +273,7 @@ def test_shopping_list_items_update_many(
|
|||
|
||||
# make sure the list didn't change sizes
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -306,12 +302,12 @@ def test_shopping_list_items_update_many_reorder(
|
|||
# update list
|
||||
# the default serializer fails on certain complex objects, so we use FastAPI's serializer first
|
||||
as_dict = utils.jsonify(as_dict)
|
||||
response = api_client.put(api_routes.groups_shopping_items, json=as_dict, headers=unique_user.token)
|
||||
response = api_client.put(api_routes.households_shopping_items, json=as_dict, headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
# retrieve list and check positions against list
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(list_with_items.id),
|
||||
api_routes.households_shopping_lists_item_id(list_with_items.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
response_list = utils.assert_deserialize(response, 200)
|
||||
|
@ -329,11 +325,11 @@ def test_shopping_list_items_delete_one(
|
|||
item = random.choice(list_with_items.list_items)
|
||||
|
||||
# Delete Item
|
||||
response = api_client.delete(api_routes.groups_shopping_items_item_id(item.id), headers=unique_user.token)
|
||||
response = api_client.delete(api_routes.households_shopping_items_item_id(item.id), headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Validate Get Item Returns 404
|
||||
response = api_client.get(api_routes.groups_shopping_items_item_id(item.id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_shopping_items_item_id(item.id), headers=unique_user.token)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
|
@ -353,7 +349,7 @@ def test_shopping_list_items_update_many_consolidates_common_items(
|
|||
|
||||
# update list
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items,
|
||||
api_routes.households_shopping_items,
|
||||
json=serialize_list_items(list_items),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -361,7 +357,7 @@ def test_shopping_list_items_update_many_consolidates_common_items(
|
|||
|
||||
# retrieve list and check positions against list
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(list_with_items.id),
|
||||
api_routes.households_shopping_lists_item_id(list_with_items.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
response_list = utils.assert_deserialize(response, 200)
|
||||
|
@ -385,7 +381,7 @@ def test_shopping_list_items_add_mergeable(
|
|||
merged_qty = sum([item["quantity"] for item in duplicate_items]) # type: ignore
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_items_create_bulk,
|
||||
api_routes.households_shopping_items_create_bulk,
|
||||
json=items + duplicate_items,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -409,7 +405,7 @@ def test_shopping_list_items_add_mergeable(
|
|||
new_item["note"] = item_to_merge_into["note"]
|
||||
updated_quantity = new_item["quantity"] + item_to_merge_into["quantity"]
|
||||
|
||||
response = api_client.post(api_routes.groups_shopping_items, json=new_item, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_shopping_items, json=new_item, headers=unique_user.token)
|
||||
item_json = utils.assert_deserialize(response, 201)
|
||||
|
||||
# we should have received an updated item, not a created item
|
||||
|
@ -421,7 +417,7 @@ def test_shopping_list_items_add_mergeable(
|
|||
|
||||
# fetch the list and make sure we have the correct number of items
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
list_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -439,7 +435,7 @@ def test_shopping_list_items_update_mergable(
|
|||
item.note = list_with_items.list_items[i - 1].note
|
||||
|
||||
payload = utils.jsonify([item.model_dump() for item in list_with_items.list_items])
|
||||
response = api_client.put(api_routes.groups_shopping_items, json=payload, headers=unique_user.token)
|
||||
response = api_client.put(api_routes.households_shopping_items, json=payload, headers=unique_user.token)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
||||
assert len(as_json["createdItems"]) == 0
|
||||
|
@ -458,7 +454,7 @@ def test_shopping_list_items_update_mergable(
|
|||
|
||||
# confirm the number of items on the list matches
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(list_with_items.id),
|
||||
api_routes.households_shopping_lists_item_id(list_with_items.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -474,7 +470,7 @@ def test_shopping_list_items_update_mergable(
|
|||
merged_quantity = sum([item["quantity"] for item in items_to_merge])
|
||||
|
||||
payload = utils.jsonify(items_to_merge)
|
||||
response = api_client.put(api_routes.groups_shopping_items, json=payload, headers=unique_user.token)
|
||||
response = api_client.put(api_routes.households_shopping_items, json=payload, headers=unique_user.token)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
||||
assert len(as_json["createdItems"]) == 0
|
||||
|
@ -503,7 +499,7 @@ def test_shopping_list_items_checked_off(
|
|||
checked_item.checked = True
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items_item_id(checked_item.id),
|
||||
api_routes.households_shopping_items_item_id(checked_item.id),
|
||||
json=utils.jsonify(checked_item.model_dump()),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -517,7 +513,7 @@ def test_shopping_list_items_checked_off(
|
|||
|
||||
# get the reference item and make sure it didn't change
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_items_item_id(reference_item.id),
|
||||
api_routes.households_shopping_items_item_id(reference_item.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -531,7 +527,7 @@ def test_shopping_list_items_checked_off(
|
|||
|
||||
# rename an item to match another item and check both off, and make sure they are not merged
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(list_with_items.id),
|
||||
api_routes.households_shopping_lists_item_id(list_with_items.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -543,7 +539,7 @@ def test_shopping_list_items_checked_off(
|
|||
item_2.note = item_1.note
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items,
|
||||
api_routes.households_shopping_items,
|
||||
json=utils.jsonify([item_1.model_dump(), item_2.model_dump()]),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -571,7 +567,7 @@ def test_shopping_list_items_with_zero_quantity(
|
|||
item["quantity"] = 0
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_items_create_bulk,
|
||||
api_routes.households_shopping_items_create_bulk,
|
||||
json=normal_items + zero_qty_items,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -580,7 +576,7 @@ def test_shopping_list_items_with_zero_quantity(
|
|||
|
||||
# confirm the number of items on the list matches
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -594,7 +590,7 @@ def test_shopping_list_items_with_zero_quantity(
|
|||
new_item_to_merge["note"] = target_item["note"]
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_items,
|
||||
api_routes.households_shopping_items,
|
||||
json=new_item_to_merge,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -610,7 +606,7 @@ def test_shopping_list_items_with_zero_quantity(
|
|||
|
||||
# confirm the number of items on the list stayed the same
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -622,7 +618,7 @@ def test_shopping_list_items_with_zero_quantity(
|
|||
update_item_to_merge["quantity"] = 0
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items_item_id(update_item_to_merge["id"]),
|
||||
api_routes.households_shopping_items_item_id(update_item_to_merge["id"]),
|
||||
json=update_item_to_merge,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -639,7 +635,7 @@ def test_shopping_list_items_with_zero_quantity(
|
|||
|
||||
# confirm the number of items on the list shrunk by one
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -659,7 +655,7 @@ def test_shopping_list_item_extras(
|
|||
new_item_data = create_item(shopping_list.id)
|
||||
new_item_data["extras"] = {key_str_1: val_str_1}
|
||||
|
||||
response = api_client.post(api_routes.groups_shopping_items, json=new_item_data, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_shopping_items, json=new_item_data, headers=unique_user.token)
|
||||
collection = utils.assert_deserialize(response, 201)
|
||||
item_as_json = collection["createdItems"][0]
|
||||
|
||||
|
@ -672,7 +668,7 @@ def test_shopping_list_item_extras(
|
|||
item_as_json["extras"][key_str_2] = val_str_2
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items_item_id(item_as_json["id"]),
|
||||
api_routes.households_shopping_items_item_id(item_as_json["id"]),
|
||||
json=item_as_json,
|
||||
headers=unique_user.token,
|
||||
)
|
|
@ -2,8 +2,7 @@ import random
|
|||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.group.group_shopping_list import (
|
||||
from mealie.schema.household.group_shopping_list import (
|
||||
ShoppingListItemOut,
|
||||
ShoppingListItemUpdate,
|
||||
ShoppingListItemUpdateBulk,
|
||||
|
@ -18,7 +17,7 @@ from tests.utils.fixture_schemas import TestUser
|
|||
|
||||
|
||||
def test_shopping_lists_get_all(api_client: TestClient, unique_user: TestUser, shopping_lists: list[ShoppingListOut]):
|
||||
response = api_client.get(api_routes.groups_shopping_lists, headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_shopping_lists, headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
all_lists = response.json()["items"]
|
||||
|
||||
|
@ -35,11 +34,12 @@ def test_shopping_lists_create_one(api_client: TestClient, unique_user: TestUser
|
|||
"name": random_string(10),
|
||||
}
|
||||
|
||||
response = api_client.post(api_routes.groups_shopping_lists, json=payload, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_shopping_lists, json=payload, headers=unique_user.token)
|
||||
response_list = utils.assert_deserialize(response, 201)
|
||||
|
||||
assert response_list["name"] == payload["name"]
|
||||
assert response_list["groupId"] == str(unique_user.group_id)
|
||||
assert response_list["householdId"] == str(unique_user.household_id)
|
||||
assert response_list["userId"] == str(unique_user.user_id)
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ def test_shopping_lists_get_one(api_client: TestClient, unique_user: TestUser, s
|
|||
shopping_list = shopping_lists[0]
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
@ -57,6 +57,7 @@ def test_shopping_lists_get_one(api_client: TestClient, unique_user: TestUser, s
|
|||
assert response_list["id"] == str(shopping_list.id)
|
||||
assert response_list["name"] == shopping_list.name
|
||||
assert response_list["groupId"] == str(shopping_list.group_id)
|
||||
assert response_list["householdId"] == str(unique_user.household_id)
|
||||
assert response_list["userId"] == str(shopping_list.user_id)
|
||||
|
||||
|
||||
|
@ -69,12 +70,13 @@ def test_shopping_lists_update_one(
|
|||
"name": random_string(10),
|
||||
"id": str(sample_list.id),
|
||||
"groupId": str(sample_list.group_id),
|
||||
"householdId": str(sample_list.household_id),
|
||||
"userId": str(sample_list.user_id),
|
||||
"listItems": [],
|
||||
}
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
json=payload,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -85,6 +87,7 @@ def test_shopping_lists_update_one(
|
|||
assert response_list["id"] == str(sample_list.id)
|
||||
assert response_list["name"] == payload["name"]
|
||||
assert response_list["groupId"] == str(sample_list.group_id)
|
||||
assert response_list["householdId"] == str(sample_list.household_id)
|
||||
assert response_list["userId"] == str(sample_list.user_id)
|
||||
|
||||
|
||||
|
@ -94,13 +97,13 @@ def test_shopping_lists_delete_one(
|
|||
sample_list = random.choice(shopping_lists)
|
||||
|
||||
response = api_client.delete(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
@ -116,14 +119,14 @@ def test_shopping_lists_add_recipe(
|
|||
recipe = recipe_ingredient_only
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
# get list and verify items against ingredients
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -144,13 +147,13 @@ def test_shopping_lists_add_recipe(
|
|||
|
||||
# add the recipe again and check the resulting items
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -206,12 +209,12 @@ def test_shopping_lists_add_one_with_zero_quantity(
|
|||
|
||||
# add the recipe to the list and make sure there are three list items
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
shopping_list_out = ShoppingListOut.model_validate(utils.assert_deserialize(response, 200))
|
||||
|
@ -239,14 +242,14 @@ def test_shopping_lists_add_custom_recipe_items(
|
|||
recipe = recipe_ingredient_only
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
custom_items = random.sample(recipe_ingredient_only.recipe_ingredient, k=3)
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
json={"recipeIngredients": utils.jsonify(custom_items)},
|
||||
)
|
||||
|
@ -254,7 +257,7 @@ def test_shopping_lists_add_custom_recipe_items(
|
|||
|
||||
# get list and verify items against ingredients
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -288,13 +291,13 @@ def test_shopping_list_ref_removes_itself(
|
|||
# add a recipe to a list, then check off all recipe items and make sure the recipe ref is deleted
|
||||
recipe = recipe_ingredient_only
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
utils.assert_deserialize(response, 200)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
shopping_list_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -305,14 +308,14 @@ def test_shopping_list_ref_removes_itself(
|
|||
item["checked"] = True
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items,
|
||||
api_routes.households_shopping_items,
|
||||
json=shopping_list_json["listItems"],
|
||||
headers=unique_user.token,
|
||||
)
|
||||
utils.assert_deserialize(response, 200)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
shopping_list_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -362,12 +365,12 @@ def test_shopping_lists_add_recipe_with_merge(
|
|||
|
||||
# add the recipe to the list and make sure there are only three list items, and their quantities/refs are correct
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
shopping_list_out = ShoppingListOut.model_validate(utils.assert_deserialize(response, 200))
|
||||
|
@ -410,12 +413,12 @@ def test_shopping_list_add_recipe_scale(
|
|||
recipe = recipe_ingredient_only
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -440,13 +443,13 @@ def test_shopping_list_add_recipe_scale(
|
|||
payload = {"recipeIncrementQuantity": recipe_scale}
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
json=payload,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -475,7 +478,7 @@ def test_shopping_lists_remove_recipe(
|
|||
# add two instances of the recipe
|
||||
payload = {"recipeIncrementQuantity": 2}
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
json=payload,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -483,14 +486,14 @@ def test_shopping_lists_remove_recipe(
|
|||
|
||||
# remove one instance of the recipe
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
# get list and verify items against ingredients
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -511,13 +514,13 @@ def test_shopping_lists_remove_recipe(
|
|||
|
||||
# remove the recipe again and check if the list is empty
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -536,13 +539,13 @@ def test_shopping_lists_remove_recipe_multiple_quantity(
|
|||
|
||||
for _ in range(3):
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -556,13 +559,13 @@ def test_shopping_lists_remove_recipe_multiple_quantity(
|
|||
|
||||
# Remove Recipe
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
||||
# Get List and Check for Ingredients
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -593,13 +596,13 @@ def test_shopping_list_remove_recipe_scale(
|
|||
|
||||
# first add a bunch of quantity to the list
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
json=payload,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -621,13 +624,13 @@ def test_shopping_list_remove_recipe_scale(
|
|||
|
||||
# remove some of the recipes
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
json=payload,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -658,13 +661,13 @@ def test_recipe_decrement_max(
|
|||
|
||||
# first add a bunch of quantity to the list
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
json=payload,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -686,7 +689,7 @@ def test_recipe_decrement_max(
|
|||
item_json["quantity"] += item_additional_quantity
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items_item_id(item_json["id"]),
|
||||
api_routes.households_shopping_items_item_id(item_json["id"]),
|
||||
json=item_json,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -697,13 +700,13 @@ def test_recipe_decrement_max(
|
|||
# now remove way too many instances of the recipe
|
||||
payload = {"recipeDecrementQuantity": recipe_scale * 100}
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id_delete(sample_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
json=payload,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(sample_list.id),
|
||||
api_routes.households_shopping_lists_item_id(sample_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
as_json = utils.assert_deserialize(response, 200)
|
||||
|
@ -754,19 +757,19 @@ def test_recipe_manipulation_with_zero_quantities(
|
|||
|
||||
# add the recipe to the list twice and make sure the quantity is still zero
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
utils.assert_deserialize(response, 200)
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id(shopping_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
utils.assert_deserialize(response, 200)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
updated_list = ShoppingListOut.model_validate_json(response.content)
|
||||
|
@ -790,12 +793,12 @@ def test_recipe_manipulation_with_zero_quantities(
|
|||
|
||||
# remove the recipe once and make sure the item is still on the list
|
||||
api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id_delete(shopping_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id_delete(shopping_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
updated_list = ShoppingListOut.model_validate_json(response.content)
|
||||
|
@ -819,12 +822,12 @@ def test_recipe_manipulation_with_zero_quantities(
|
|||
|
||||
# remove the recipe one more time and make sure the item is gone and the list is empty
|
||||
api_client.post(
|
||||
api_routes.groups_shopping_lists_item_id_recipe_recipe_id_delete(shopping_list.id, recipe.id),
|
||||
api_routes.households_shopping_lists_item_id_recipe_recipe_id_delete(shopping_list.id, recipe.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
||||
response = api_client.get(
|
||||
api_routes.groups_shopping_lists_item_id(shopping_list.id),
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
updated_list = ShoppingListOut.model_validate_json(response.content)
|
||||
|
@ -845,7 +848,7 @@ def test_shopping_list_extras(
|
|||
new_list_data: dict = {"name": random_string()}
|
||||
new_list_data["extras"] = {key_str_1: val_str_1}
|
||||
|
||||
response = api_client.post(api_routes.groups_shopping_lists, json=new_list_data, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_shopping_lists, json=new_list_data, headers=unique_user.token)
|
||||
list_as_json = utils.assert_deserialize(response, 201)
|
||||
|
||||
# make sure the extra persists
|
||||
|
@ -857,7 +860,7 @@ def test_shopping_list_extras(
|
|||
list_as_json["extras"][key_str_2] = val_str_2
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_lists_item_id(list_as_json["id"]),
|
||||
api_routes.households_shopping_lists_item_id(list_as_json["id"]),
|
||||
json=list_as_json,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -872,60 +875,68 @@ def test_shopping_list_extras(
|
|||
|
||||
|
||||
def test_modify_shopping_list_items_updates_shopping_list(
|
||||
database: AllRepositories,
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
shopping_lists: list[ShoppingListOut],
|
||||
api_client: TestClient, unique_user: TestUser, shopping_lists: list[ShoppingListOut]
|
||||
):
|
||||
shopping_list = random.choice(shopping_lists)
|
||||
last_update_at = shopping_list.update_at
|
||||
last_update_at = shopping_list.updated_at
|
||||
assert last_update_at
|
||||
|
||||
# Create
|
||||
new_item_data = {"note": random_string(), "shopping_list_id": str(shopping_list.id)}
|
||||
response = api_client.post(api_routes.groups_shopping_items, json=new_item_data, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_shopping_items, json=new_item_data, headers=unique_user.token)
|
||||
data = assert_deserialize(response, 201)
|
||||
updated_list = database.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert updated_list and updated_list.update_at
|
||||
assert updated_list.update_at > last_update_at
|
||||
last_update_at = updated_list.update_at
|
||||
updated_list = ShoppingListOut.model_validate_json(
|
||||
api_client.get(
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id), headers=unique_user.token
|
||||
).content
|
||||
)
|
||||
assert updated_list and updated_list.updated_at
|
||||
assert updated_list.updated_at > last_update_at
|
||||
last_update_at = updated_list.updated_at
|
||||
|
||||
list_item_id = data["createdItems"][0]["id"]
|
||||
list_item = database.group_shopping_list_item.get_one(list_item_id)
|
||||
list_item = ShoppingListItemOut.model_validate_json(
|
||||
api_client.get(api_routes.households_shopping_items_item_id(list_item_id), headers=unique_user.token).content
|
||||
)
|
||||
assert list_item
|
||||
|
||||
# Update
|
||||
list_item.note = random_string()
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_items_item_id(list_item_id),
|
||||
api_routes.households_shopping_items_item_id(list_item_id),
|
||||
json=utils.jsonify(list_item.cast(ShoppingListItemUpdate).model_dump()),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
updated_list = database.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert updated_list and updated_list.update_at
|
||||
assert updated_list.update_at > last_update_at
|
||||
last_update_at = updated_list.update_at
|
||||
updated_list = ShoppingListOut.model_validate_json(
|
||||
api_client.get(
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id), headers=unique_user.token
|
||||
).content
|
||||
)
|
||||
assert updated_list and updated_list.updated_at
|
||||
assert updated_list.updated_at > last_update_at
|
||||
last_update_at = updated_list.updated_at
|
||||
|
||||
# Delete
|
||||
response = api_client.delete(
|
||||
api_routes.groups_shopping_items_item_id(list_item_id),
|
||||
api_routes.households_shopping_items_item_id(list_item_id),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
updated_list = database.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert updated_list and updated_list.update_at
|
||||
assert updated_list.update_at > last_update_at
|
||||
updated_list = ShoppingListOut.model_validate_json(
|
||||
api_client.get(
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id), headers=unique_user.token
|
||||
).content
|
||||
)
|
||||
assert updated_list and updated_list.updated_at
|
||||
assert updated_list.updated_at > last_update_at
|
||||
|
||||
|
||||
def test_bulk_modify_shopping_list_items_updates_shopping_list(
|
||||
database: AllRepositories,
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
shopping_lists: list[ShoppingListOut],
|
||||
api_client: TestClient, unique_user: TestUser, shopping_lists: list[ShoppingListOut]
|
||||
):
|
||||
shopping_list = random.choice(shopping_lists)
|
||||
last_update_at = shopping_list.update_at
|
||||
last_update_at = shopping_list.updated_at
|
||||
assert last_update_at
|
||||
|
||||
# Create
|
||||
|
@ -933,40 +944,57 @@ def test_bulk_modify_shopping_list_items_updates_shopping_list(
|
|||
{"note": random_string(), "shopping_list_id": str(shopping_list.id)} for _ in range(random_int(3, 5))
|
||||
]
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_items_create_bulk,
|
||||
api_routes.households_shopping_items_create_bulk,
|
||||
json=new_item_data,
|
||||
headers=unique_user.token,
|
||||
)
|
||||
data = assert_deserialize(response, 201)
|
||||
updated_list = database.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert updated_list and updated_list.update_at
|
||||
assert updated_list.update_at > last_update_at
|
||||
last_update_at = updated_list.update_at
|
||||
updated_list = ShoppingListOut.model_validate_json(
|
||||
api_client.get(
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id), headers=unique_user.token
|
||||
).content
|
||||
)
|
||||
assert updated_list and updated_list.updated_at
|
||||
assert updated_list.updated_at > last_update_at
|
||||
last_update_at = updated_list.updated_at
|
||||
|
||||
# Update
|
||||
list_item_ids = [item["id"] for item in data["createdItems"]]
|
||||
list_items: list[ShoppingListItemOut] = []
|
||||
for list_item_id in list_item_ids:
|
||||
list_item = database.group_shopping_list_item.get_one(list_item_id)
|
||||
list_item = ShoppingListItemOut.model_validate_json(
|
||||
api_client.get(
|
||||
api_routes.households_shopping_items_item_id(list_item_id), headers=unique_user.token
|
||||
).content
|
||||
)
|
||||
assert list_item
|
||||
assert list_item
|
||||
list_item.note = random_string()
|
||||
list_items.append(list_item)
|
||||
|
||||
payload = [utils.jsonify(list_item.cast(ShoppingListItemUpdateBulk).model_dump()) for list_item in list_items]
|
||||
response = api_client.put(api_routes.groups_shopping_items, json=payload, headers=unique_user.token)
|
||||
response = api_client.put(api_routes.households_shopping_items, json=payload, headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
updated_list = database.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert updated_list and updated_list.update_at
|
||||
assert updated_list.update_at > last_update_at
|
||||
last_update_at = updated_list.update_at
|
||||
updated_list = ShoppingListOut.model_validate_json(
|
||||
api_client.get(
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id), headers=unique_user.token
|
||||
).content
|
||||
)
|
||||
assert updated_list and updated_list.updated_at
|
||||
assert updated_list.updated_at > last_update_at
|
||||
last_update_at = updated_list.updated_at
|
||||
|
||||
# Delete
|
||||
response = api_client.delete(
|
||||
api_routes.groups_shopping_items,
|
||||
api_routes.households_shopping_items,
|
||||
params={"ids": [str(list_item.id) for list_item in list_items]},
|
||||
headers=unique_user.token,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
updated_list = database.group_shopping_lists.get_one(shopping_list.id)
|
||||
assert updated_list and updated_list.update_at
|
||||
assert updated_list.update_at > last_update_at
|
||||
updated_list = ShoppingListOut.model_validate_json(
|
||||
api_client.get(
|
||||
api_routes.households_shopping_lists_item_id(shopping_list.id), headers=unique_user.token
|
||||
).content
|
||||
)
|
||||
assert updated_list and updated_list.updated_at
|
||||
assert updated_list.updated_at > last_update_at
|
|
@ -20,7 +20,7 @@ def webhook_data():
|
|||
|
||||
def test_create_webhook(api_client: TestClient, unique_user: TestUser, webhook_data):
|
||||
response = api_client.post(
|
||||
api_routes.groups_webhooks,
|
||||
api_routes.households_webhooks,
|
||||
json=jsonify(webhook_data),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -29,13 +29,13 @@ def test_create_webhook(api_client: TestClient, unique_user: TestUser, webhook_d
|
|||
|
||||
def test_read_webhook(api_client: TestClient, unique_user: TestUser, webhook_data):
|
||||
response = api_client.post(
|
||||
api_routes.groups_webhooks,
|
||||
api_routes.households_webhooks,
|
||||
json=jsonify(webhook_data),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
item_id = response.json()["id"]
|
||||
|
||||
response = api_client.get(api_routes.groups_webhooks_item_id(item_id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_webhooks_item_id(item_id), headers=unique_user.token)
|
||||
webhook = assert_deserialize(response, 200)
|
||||
|
||||
assert webhook["id"] == item_id
|
||||
|
@ -47,7 +47,7 @@ def test_read_webhook(api_client: TestClient, unique_user: TestUser, webhook_dat
|
|||
|
||||
def test_update_webhook(api_client: TestClient, webhook_data, unique_user: TestUser):
|
||||
response = api_client.post(
|
||||
api_routes.groups_webhooks,
|
||||
api_routes.households_webhooks,
|
||||
json=jsonify(webhook_data),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -59,7 +59,7 @@ def test_update_webhook(api_client: TestClient, webhook_data, unique_user: TestU
|
|||
webhook_data["enabled"] = False
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_webhooks_item_id(item_id),
|
||||
api_routes.households_webhooks_item_id(item_id),
|
||||
json=jsonify(webhook_data),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -72,15 +72,15 @@ def test_update_webhook(api_client: TestClient, webhook_data, unique_user: TestU
|
|||
|
||||
def test_delete_webhook(api_client: TestClient, webhook_data, unique_user: TestUser):
|
||||
response = api_client.post(
|
||||
api_routes.groups_webhooks,
|
||||
api_routes.households_webhooks,
|
||||
json=jsonify(webhook_data),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
item_dict = assert_deserialize(response, 201)
|
||||
item_id = item_dict["id"]
|
||||
|
||||
response = api_client.delete(api_routes.groups_webhooks_item_id(item_id), headers=unique_user.token)
|
||||
response = api_client.delete(api_routes.households_webhooks_item_id(item_id), headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
response = api_client.get(api_routes.groups_webhooks_item_id(item_id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_webhooks_item_id(item_id), headers=unique_user.token)
|
||||
assert response.status_code == 404
|
|
@ -0,0 +1,47 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.schema.household.household_preferences import UpdateHouseholdPreferences
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.assertion_helpers import assert_ignore_keys
|
||||
from tests.utils.factories import random_bool
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
def test_get_preferences(api_client: TestClient, unique_user: TestUser) -> None:
|
||||
response = api_client.get(api_routes.households_preferences, headers=unique_user.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
preferences = response.json()
|
||||
|
||||
assert preferences["recipePublic"] in {True, False}
|
||||
assert preferences["recipeShowNutrition"] in {True, False}
|
||||
|
||||
|
||||
def test_preferences_in_household(api_client: TestClient, unique_user: TestUser) -> None:
|
||||
response = api_client.get(api_routes.households_self, headers=unique_user.token)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
household = response.json()
|
||||
|
||||
assert household["preferences"] is not None
|
||||
|
||||
# Spot Check
|
||||
assert household["preferences"]["recipePublic"] in {True, False}
|
||||
assert household["preferences"]["recipeShowNutrition"] in {True, False}
|
||||
|
||||
|
||||
def test_update_preferences(api_client: TestClient, unique_user: TestUser) -> None:
|
||||
new_data = UpdateHouseholdPreferences(recipe_public=random_bool(), recipe_show_nutrition=random_bool())
|
||||
|
||||
response = api_client.put(api_routes.households_preferences, json=new_data.model_dump(), headers=unique_user.token)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
preferences = response.json()
|
||||
|
||||
assert preferences is not None
|
||||
assert preferences["recipePublic"] == new_data.recipe_public
|
||||
assert preferences["recipeShowNutrition"] == new_data.recipe_show_nutrition
|
||||
|
||||
assert_ignore_keys(new_data.model_dump(by_alias=True), preferences, ["id", "householdId"])
|
|
@ -2,7 +2,6 @@ from uuid import uuid4
|
|||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.factories import random_bool
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
@ -17,39 +16,28 @@ def get_permissions_payload(user_id: str, can_manage=None) -> dict:
|
|||
}
|
||||
|
||||
|
||||
def test_get_group_members(api_client: TestClient, user_tuple: list[TestUser]):
|
||||
usr_1, usr_2 = user_tuple
|
||||
|
||||
response = api_client.get(api_routes.groups_members, headers=usr_1.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
members = response.json()
|
||||
assert len(members) >= 2
|
||||
|
||||
all_ids = [x["id"] for x in members]
|
||||
|
||||
assert str(usr_1.user_id) in all_ids
|
||||
assert str(usr_2.user_id) in all_ids
|
||||
|
||||
|
||||
def test_set_memeber_permissions(api_client: TestClient, user_tuple: list[TestUser], database: AllRepositories):
|
||||
def test_set_member_permissions(api_client: TestClient, user_tuple: list[TestUser]):
|
||||
usr_1, usr_2 = user_tuple
|
||||
|
||||
# Set Acting User
|
||||
acting_user = database.users.get_one(usr_1.user_id)
|
||||
acting_user = usr_1.repos.users.get_one(usr_1.user_id)
|
||||
assert acting_user
|
||||
acting_user.can_manage = True
|
||||
database.users.update(acting_user.id, acting_user)
|
||||
usr_1.repos.users.update(acting_user.id, acting_user)
|
||||
|
||||
payload = get_permissions_payload(str(usr_2.user_id))
|
||||
|
||||
# Test
|
||||
response = api_client.put(api_routes.groups_permissions, json=payload, headers=usr_1.token)
|
||||
response = api_client.put(api_routes.households_permissions, json=payload, headers=usr_1.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_set_memeber_permissions_unauthorized(api_client: TestClient, unique_user: TestUser, database: AllRepositories):
|
||||
def test_set_member_permissions_unauthorized(api_client: TestClient, unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
|
||||
# Setup
|
||||
user = database.users.get_one(unique_user.user_id)
|
||||
assert user
|
||||
user.can_manage = False
|
||||
database.users.update(user.id, user)
|
||||
|
||||
|
@ -62,34 +50,38 @@ def test_set_memeber_permissions_unauthorized(api_client: TestClient, unique_use
|
|||
}
|
||||
|
||||
# Test
|
||||
response = api_client.put(api_routes.groups_permissions, json=payload, headers=unique_user.token)
|
||||
response = api_client.put(api_routes.households_permissions, json=payload, headers=unique_user.token)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_set_memeber_permissions_other_group(
|
||||
def test_set_member_permissions_other_household(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
g2_user: TestUser,
|
||||
database: AllRepositories,
|
||||
h2_user: TestUser,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
user = database.users.get_one(unique_user.user_id)
|
||||
assert user
|
||||
user.can_manage = True
|
||||
database.users.update(user.id, user)
|
||||
|
||||
payload = get_permissions_payload(str(g2_user.user_id))
|
||||
response = api_client.put(api_routes.groups_permissions, json=payload, headers=unique_user.token)
|
||||
payload = get_permissions_payload(str(h2_user.user_id))
|
||||
response = api_client.put(api_routes.households_permissions, json=payload, headers=unique_user.token)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_set_memeber_permissions_no_user(
|
||||
def test_set_member_permissions_no_user(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
user = database.users.get_one(unique_user.user_id)
|
||||
assert user
|
||||
user.can_manage = True
|
||||
database.users.update(user.id, user)
|
||||
|
||||
payload = get_permissions_payload(str(uuid4()))
|
||||
response = api_client.put(api_routes.groups_permissions, json=payload, headers=unique_user.token)
|
||||
response = api_client.put(api_routes.households_permissions, json=payload, headers=unique_user.token)
|
||||
assert response.status_code == 404
|
|
@ -0,0 +1,20 @@
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
def test_get_household_members(api_client: TestClient, user_tuple: list[TestUser], h2_user: TestUser):
|
||||
usr_1, usr_2 = user_tuple
|
||||
|
||||
response = api_client.get(api_routes.households_members, headers=usr_1.token)
|
||||
assert response.status_code == 200
|
||||
|
||||
members = response.json()
|
||||
assert len(members) >= 2
|
||||
|
||||
all_ids = [x["id"] for x in members]
|
||||
|
||||
assert str(usr_1.user_id) in all_ids
|
||||
assert str(usr_2.user_id) in all_ids
|
||||
assert str(h2_user.user_id) not in all_ids
|
|
@ -3,7 +3,7 @@ import random
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.group.group_shopping_list import ShoppingListOut
|
||||
from mealie.schema.household.group_shopping_list import ShoppingListOut
|
||||
from mealie.schema.labels.multi_purpose_label import MultiPurposeLabelOut
|
||||
from mealie.services.seeder.seeder_service import SeederService
|
||||
from tests.utils import api_routes, jsonify
|
||||
|
@ -23,7 +23,7 @@ def create_labels(api_client: TestClient, unique_user: TestUser, count: int = 10
|
|||
def test_new_list_creates_list_labels(api_client: TestClient, unique_user: TestUser):
|
||||
labels = create_labels(api_client, unique_user)
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
api_routes.households_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
)
|
||||
new_list = ShoppingListOut.model_validate(response.json())
|
||||
|
||||
|
@ -37,14 +37,14 @@ def test_new_label_creates_list_labels(api_client: TestClient, unique_user: Test
|
|||
# create a list with some labels
|
||||
create_labels(api_client, unique_user)
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
api_routes.households_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
)
|
||||
new_list = ShoppingListOut.model_validate(response.json())
|
||||
existing_label_settings = new_list.label_settings
|
||||
|
||||
# create more labels and make sure they were added to the list's label settings
|
||||
new_labels = create_labels(api_client, unique_user)
|
||||
response = api_client.get(api_routes.groups_shopping_lists_item_id(new_list.id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_shopping_lists_item_id(new_list.id), headers=unique_user.token)
|
||||
updated_list = ShoppingListOut.model_validate(response.json())
|
||||
updated_label_settings = updated_list.label_settings
|
||||
assert len(updated_label_settings) == len(existing_label_settings) + len(new_labels)
|
||||
|
@ -58,23 +58,66 @@ def test_new_label_creates_list_labels(api_client: TestClient, unique_user: Test
|
|||
assert label.id in label_settings_label_ids
|
||||
|
||||
|
||||
def test_seed_label_creates_list_labels(database: AllRepositories, api_client: TestClient, unique_user: TestUser):
|
||||
def test_new_label_creates_list_labels_in_all_households(
|
||||
api_client: TestClient, unique_user: TestUser, h2_user: TestUser
|
||||
):
|
||||
# unique_user and h2_user are in the same group, so these labels should be for both of them
|
||||
create_labels(api_client, unique_user)
|
||||
|
||||
# create a list with some labels for each user
|
||||
response = api_client.post(
|
||||
api_routes.households_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
)
|
||||
new_list_h1 = ShoppingListOut.model_validate(response.json())
|
||||
existing_label_settings_h1 = new_list_h1.label_settings
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.households_shopping_lists, json={"name": random_string()}, headers=h2_user.token
|
||||
)
|
||||
new_list_h2 = ShoppingListOut.model_validate(response.json())
|
||||
existing_label_settings_h2 = new_list_h2.label_settings
|
||||
|
||||
# create more labels and make sure they were added to both lists' label settings
|
||||
new_labels = create_labels(api_client, unique_user)
|
||||
|
||||
for user, new_list, existing_label_settings in [
|
||||
(unique_user, new_list_h1, existing_label_settings_h1),
|
||||
(h2_user, new_list_h2, existing_label_settings_h2),
|
||||
]:
|
||||
response = api_client.get(api_routes.households_shopping_lists_item_id(new_list.id), headers=user.token)
|
||||
updated_list = ShoppingListOut.model_validate(response.json())
|
||||
updated_label_settings = updated_list.label_settings
|
||||
assert len(updated_label_settings) == len(existing_label_settings) + len(new_labels)
|
||||
|
||||
label_settings_ids = [setting.id for setting in updated_list.label_settings]
|
||||
for label_setting in existing_label_settings:
|
||||
assert label_setting.id in label_settings_ids
|
||||
|
||||
label_settings_label_ids = [setting.label_id for setting in updated_list.label_settings]
|
||||
for label in new_labels:
|
||||
assert label.id in label_settings_label_ids
|
||||
|
||||
|
||||
def test_seed_label_creates_list_labels(api_client: TestClient, unique_user: TestUser):
|
||||
CREATED_LABELS = 21
|
||||
database = unique_user.repos
|
||||
|
||||
# create a list with some labels
|
||||
create_labels(api_client, unique_user)
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
api_routes.households_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
)
|
||||
new_list = ShoppingListOut.model_validate(response.json())
|
||||
existing_label_settings = new_list.label_settings
|
||||
|
||||
# seed labels and make sure they were added to the list's label settings
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
seeder = SeederService(database, None, group) # type: ignore
|
||||
assert group
|
||||
database = AllRepositories(database.session, group_id=group.id)
|
||||
seeder = SeederService(database)
|
||||
seeder.seed_labels("en-US")
|
||||
|
||||
response = api_client.get(api_routes.groups_shopping_lists_item_id(new_list.id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_shopping_lists_item_id(new_list.id), headers=unique_user.token)
|
||||
updated_list = ShoppingListOut.model_validate(response.json())
|
||||
updated_label_settings = updated_list.label_settings
|
||||
assert len(updated_label_settings) == len(existing_label_settings) + CREATED_LABELS
|
||||
|
@ -87,7 +130,7 @@ def test_seed_label_creates_list_labels(database: AllRepositories, api_client: T
|
|||
def test_delete_label_deletes_list_labels(api_client: TestClient, unique_user: TestUser):
|
||||
new_labels = create_labels(api_client, unique_user)
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
api_routes.households_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
)
|
||||
new_list = ShoppingListOut.model_validate(response.json())
|
||||
|
||||
|
@ -95,7 +138,7 @@ def test_delete_label_deletes_list_labels(api_client: TestClient, unique_user: T
|
|||
label_to_delete = random.choice(new_labels)
|
||||
api_client.delete(api_routes.groups_labels_item_id(label_to_delete.id), headers=unique_user.token)
|
||||
|
||||
response = api_client.get(api_routes.groups_shopping_lists_item_id(new_list.id), headers=unique_user.token)
|
||||
response = api_client.get(api_routes.households_shopping_lists_item_id(new_list.id), headers=unique_user.token)
|
||||
updated_list = ShoppingListOut.model_validate(response.json())
|
||||
assert len(updated_list.label_settings) == len(existing_label_settings) - 1
|
||||
|
||||
|
@ -114,7 +157,7 @@ def test_update_list_doesnt_change_list_labels(api_client: TestClient, unique_us
|
|||
updated_name = random_string()
|
||||
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists, json={"name": original_name}, headers=unique_user.token
|
||||
api_routes.households_shopping_lists, json={"name": original_name}, headers=unique_user.token
|
||||
)
|
||||
new_list = ShoppingListOut.model_validate(response.json())
|
||||
assert new_list.name == original_name
|
||||
|
@ -122,13 +165,13 @@ def test_update_list_doesnt_change_list_labels(api_client: TestClient, unique_us
|
|||
|
||||
updated_list_data = new_list.model_dump()
|
||||
updated_list_data.pop("created_at", None)
|
||||
updated_list_data.pop("update_at", None)
|
||||
updated_list_data.pop("updated_at", None)
|
||||
|
||||
updated_list_data["name"] = updated_name
|
||||
updated_list_data["label_settings"][0]["position"] = random_int(999, 9999)
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_lists_item_id(new_list.id),
|
||||
api_routes.households_shopping_lists_item_id(new_list.id),
|
||||
json=jsonify(updated_list_data),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -140,14 +183,14 @@ def test_update_list_doesnt_change_list_labels(api_client: TestClient, unique_us
|
|||
def test_update_list_labels(api_client: TestClient, unique_user: TestUser):
|
||||
create_labels(api_client, unique_user)
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
api_routes.households_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
)
|
||||
new_list = ShoppingListOut.model_validate(response.json())
|
||||
changed_setting = random.choice(new_list.label_settings)
|
||||
changed_setting.position = random_int(999, 9999)
|
||||
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_lists_item_id_label_settings(new_list.id),
|
||||
api_routes.households_shopping_lists_item_id_label_settings(new_list.id),
|
||||
json=jsonify(new_list.label_settings),
|
||||
headers=unique_user.token,
|
||||
)
|
||||
|
@ -168,7 +211,7 @@ def test_update_list_labels(api_client: TestClient, unique_user: TestUser):
|
|||
|
||||
def test_list_label_order(api_client: TestClient, unique_user: TestUser):
|
||||
response = api_client.post(
|
||||
api_routes.groups_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
api_routes.households_shopping_lists, json={"name": random_string()}, headers=unique_user.token
|
||||
)
|
||||
new_list = ShoppingListOut.model_validate(response.json())
|
||||
for i, setting in enumerate(new_list.label_settings):
|
||||
|
@ -179,7 +222,7 @@ def test_list_label_order(api_client: TestClient, unique_user: TestUser):
|
|||
|
||||
random.shuffle(new_list.label_settings)
|
||||
response = api_client.put(
|
||||
api_routes.groups_shopping_lists_item_id_label_settings(new_list.id),
|
||||
api_routes.households_shopping_lists_item_id_label_settings(new_list.id),
|
||||
json=jsonify(new_list.label_settings),
|
||||
headers=unique_user.token,
|
||||
)
|
|
@ -16,9 +16,8 @@ from tests.utils.fixture_schemas import TestUser
|
|||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def ten_slugs(
|
||||
api_client: TestClient, unique_user: TestUser, database: AllRepositories
|
||||
) -> Generator[list[str], None, None]:
|
||||
def ten_slugs(api_client: TestClient, unique_user: TestUser) -> Generator[list[str], None, None]:
|
||||
database = unique_user.repos
|
||||
slugs: list[str] = []
|
||||
|
||||
for _ in range(10):
|
||||
|
@ -38,9 +37,9 @@ def ten_slugs(
|
|||
pass
|
||||
|
||||
|
||||
def test_bulk_tag_recipes(
|
||||
api_client: TestClient, unique_user: TestUser, database: AllRepositories, ten_slugs: list[str]
|
||||
):
|
||||
def test_bulk_tag_recipes(api_client: TestClient, unique_user: TestUser, ten_slugs: list[str]):
|
||||
database = unique_user.repos
|
||||
|
||||
# Setup Tags
|
||||
tags = []
|
||||
for _ in range(3):
|
||||
|
@ -66,9 +65,10 @@ def test_bulk_tag_recipes(
|
|||
def test_bulk_categorize_recipes(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
ten_slugs: list[str],
|
||||
):
|
||||
database = unique_user.repos
|
||||
|
||||
# Setup Tags
|
||||
categories = []
|
||||
for _ in range(3):
|
||||
|
@ -94,9 +94,9 @@ def test_bulk_categorize_recipes(
|
|||
def test_bulk_delete_recipes(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
ten_slugs: list[str],
|
||||
):
|
||||
database = unique_user.repos
|
||||
payload = {"recipes": ten_slugs}
|
||||
|
||||
response = api_client.post(api_routes.recipes_bulk_actions_delete, json=payload, headers=unique_user.token)
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
from uuid import UUID
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.factories import random_string
|
||||
|
@ -39,7 +42,7 @@ def test_create_comment(api_client: TestClient, unique_recipe: Recipe, unique_us
|
|||
|
||||
assert response_data["recipeId"] == str(unique_recipe.id)
|
||||
assert response_data["text"] == create_data["text"]
|
||||
assert response_data["userId"] == unique_user.user_id
|
||||
assert response_data["userId"] == str(unique_user.user_id)
|
||||
|
||||
# Check for Proper Association
|
||||
response = api_client.get(api_routes.recipes_slug_comments(unique_recipe.slug), headers=unique_user.token)
|
||||
|
@ -50,7 +53,7 @@ def test_create_comment(api_client: TestClient, unique_recipe: Recipe, unique_us
|
|||
assert len(response_data) == 1
|
||||
assert response_data[0]["recipeId"] == str(unique_recipe.id)
|
||||
assert response_data[0]["text"] == create_data["text"]
|
||||
assert response_data[0]["userId"] == unique_user.user_id
|
||||
assert response_data[0]["userId"] == str(unique_user.user_id)
|
||||
|
||||
|
||||
def test_update_comment(api_client: TestClient, unique_recipe: Recipe, unique_user: TestUser):
|
||||
|
@ -73,7 +76,7 @@ def test_update_comment(api_client: TestClient, unique_recipe: Recipe, unique_us
|
|||
|
||||
assert response_data["recipeId"] == str(unique_recipe.id)
|
||||
assert response_data["text"] == update_data["text"]
|
||||
assert response_data["userId"] == unique_user.user_id
|
||||
assert response_data["userId"] == str(unique_user.user_id)
|
||||
|
||||
|
||||
def test_delete_comment(api_client: TestClient, unique_recipe: Recipe, unique_user: TestUser):
|
||||
|
@ -93,7 +96,20 @@ def test_delete_comment(api_client: TestClient, unique_recipe: Recipe, unique_us
|
|||
assert response.status_code == 404
|
||||
|
||||
|
||||
def test_admin_can_delete(api_client: TestClient, unique_recipe: Recipe, unique_user: TestUser, admin_user: TestUser):
|
||||
def test_admin_can_delete(
|
||||
unfiltered_database: AllRepositories,
|
||||
api_client: TestClient,
|
||||
unique_recipe: Recipe,
|
||||
unique_user: TestUser,
|
||||
admin_user: TestUser,
|
||||
):
|
||||
# Make sure admin belongs to same group/household as user
|
||||
admin_data = unfiltered_database.users.get_one(admin_user.user_id)
|
||||
assert admin_data
|
||||
admin_data.group_id = UUID(unique_user.group_id)
|
||||
admin_data.household_id = UUID(unique_user.household_id)
|
||||
unfiltered_database.users.update(admin_user.user_id, admin_data)
|
||||
|
||||
# Create Comment
|
||||
create_data = random_comment(unique_recipe.id)
|
||||
response = api_client.post(api_routes.comments, json=create_data, headers=unique_user.token)
|
||||
|
|
|
@ -9,10 +9,10 @@ from pathlib import Path
|
|||
from uuid import uuid4
|
||||
from zipfile import ZipFile
|
||||
|
||||
from httpx import Response
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup
|
||||
from fastapi.testclient import TestClient
|
||||
from httpx import Response
|
||||
from pytest import MonkeyPatch
|
||||
from recipe_scrapers._abstract import AbstractScraper
|
||||
from recipe_scrapers._schemaorg import SchemaOrg
|
||||
|
@ -20,14 +20,13 @@ from recipe_scrapers.plugins import SchemaOrgFillPlugin
|
|||
from slugify import slugify
|
||||
|
||||
from mealie.pkgs.safehttp.transport import AsyncSafeTransport
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.recipe.recipe import Recipe, RecipeCategory, RecipeSummary, RecipeTag
|
||||
from mealie.schema.recipe.recipe_category import CategorySave, TagSave
|
||||
from mealie.schema.recipe.recipe_notes import RecipeNote
|
||||
from mealie.schema.recipe.recipe_tool import RecipeToolSave
|
||||
from mealie.services.recipe.recipe_data_service import RecipeDataService
|
||||
from mealie.services.scraper.recipe_scraper import DEFAULT_SCRAPER_STRATEGIES
|
||||
from tests import data, utils
|
||||
from tests import utils
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.factories import random_int, random_string
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
@ -82,7 +81,7 @@ def get_init(html_path: Path):
|
|||
current_method = getattr(self.__class__, name)
|
||||
current_method = SchemaOrgFillPlugin.run(current_method)
|
||||
setattr(self.__class__, name, current_method)
|
||||
setattr(self.__class__, "plugins_initialized", True)
|
||||
self.__class__.plugins_initialized = True
|
||||
|
||||
return init_override
|
||||
|
||||
|
@ -162,7 +161,8 @@ def test_create_by_url(
|
|||
assert tag["name"] in expected_tags
|
||||
|
||||
|
||||
def test_create_recipe_from_zip(database: AllRepositories, api_client: TestClient, unique_user: TestUser, tempdir: str):
|
||||
def test_create_recipe_from_zip(api_client: TestClient, unique_user: TestUser, tempdir: str):
|
||||
database = unique_user.repos
|
||||
recipe_name = random_string()
|
||||
recipe = RecipeSummary(
|
||||
id=uuid4(),
|
||||
|
@ -181,9 +181,8 @@ def test_create_recipe_from_zip(database: AllRepositories, api_client: TestClien
|
|||
assert fetched_recipe
|
||||
|
||||
|
||||
def test_create_recipe_from_zip_invalid_group(
|
||||
database: AllRepositories, api_client: TestClient, unique_user: TestUser, tempdir: str
|
||||
):
|
||||
def test_create_recipe_from_zip_invalid_group(api_client: TestClient, unique_user: TestUser, tempdir: str):
|
||||
database = unique_user.repos
|
||||
recipe_name = random_string()
|
||||
recipe = RecipeSummary(
|
||||
id=uuid4(),
|
||||
|
@ -205,9 +204,8 @@ def test_create_recipe_from_zip_invalid_group(
|
|||
assert str(fetched_recipe.group_id) == str(unique_user.group_id)
|
||||
|
||||
|
||||
def test_create_recipe_from_zip_invalid_user(
|
||||
database: AllRepositories, api_client: TestClient, unique_user: TestUser, tempdir: str
|
||||
):
|
||||
def test_create_recipe_from_zip_invalid_user(api_client: TestClient, unique_user: TestUser, tempdir: str):
|
||||
database = unique_user.repos
|
||||
recipe_name = random_string()
|
||||
recipe = RecipeSummary(
|
||||
id=uuid4(),
|
||||
|
@ -229,10 +227,9 @@ def test_create_recipe_from_zip_invalid_user(
|
|||
assert str(fetched_recipe.user_id) == str(unique_user.user_id)
|
||||
|
||||
|
||||
def test_create_recipe_from_zip_existing_category(
|
||||
database: AllRepositories, api_client: TestClient, unique_user: TestUser, tempdir: str
|
||||
):
|
||||
categories = database.categories.by_group(unique_user.group_id).create_many(
|
||||
def test_create_recipe_from_zip_existing_category(api_client: TestClient, unique_user: TestUser, tempdir: str):
|
||||
database = unique_user.repos
|
||||
categories = database.categories.create_many(
|
||||
[{"name": random_string(), "group_id": unique_user.group_id} for _ in range(random_int(5, 10))]
|
||||
)
|
||||
category = random.choice(categories)
|
||||
|
@ -259,10 +256,9 @@ def test_create_recipe_from_zip_existing_category(
|
|||
assert str(fetched_recipe.recipe_category[0].id) == str(category.id)
|
||||
|
||||
|
||||
def test_create_recipe_from_zip_existing_tag(
|
||||
database: AllRepositories, api_client: TestClient, unique_user: TestUser, tempdir: str
|
||||
):
|
||||
tags = database.tags.by_group(unique_user.group_id).create_many(
|
||||
def test_create_recipe_from_zip_existing_tag(api_client: TestClient, unique_user: TestUser, tempdir: str):
|
||||
database = unique_user.repos
|
||||
tags = database.tags.create_many(
|
||||
[{"name": random_string(), "group_id": unique_user.group_id} for _ in range(random_int(5, 10))]
|
||||
)
|
||||
tag = random.choice(tags)
|
||||
|
@ -290,9 +286,10 @@ def test_create_recipe_from_zip_existing_tag(
|
|||
|
||||
|
||||
def test_create_recipe_from_zip_existing_category_wrong_ids(
|
||||
database: AllRepositories, api_client: TestClient, unique_user: TestUser, tempdir: str
|
||||
api_client: TestClient, unique_user: TestUser, tempdir: str
|
||||
):
|
||||
categories = database.categories.by_group(unique_user.group_id).create_many(
|
||||
database = unique_user.repos
|
||||
categories = database.categories.create_many(
|
||||
[{"name": random_string(), "group_id": unique_user.group_id} for _ in range(random_int(5, 10))]
|
||||
)
|
||||
category = random.choice(categories)
|
||||
|
@ -320,10 +317,9 @@ def test_create_recipe_from_zip_existing_category_wrong_ids(
|
|||
assert str(fetched_recipe.recipe_category[0].id) == str(category.id)
|
||||
|
||||
|
||||
def test_create_recipe_from_zip_existing_tag_wrong_ids(
|
||||
database: AllRepositories, api_client: TestClient, unique_user: TestUser, tempdir: str
|
||||
):
|
||||
tags = database.tags.by_group(unique_user.group_id).create_many(
|
||||
def test_create_recipe_from_zip_existing_tag_wrong_ids(api_client: TestClient, unique_user: TestUser, tempdir: str):
|
||||
database = unique_user.repos
|
||||
tags = database.tags.create_many(
|
||||
[{"name": random_string(), "group_id": unique_user.group_id} for _ in range(random_int(5, 10))]
|
||||
)
|
||||
tag = random.choice(tags)
|
||||
|
@ -351,9 +347,8 @@ def test_create_recipe_from_zip_existing_tag_wrong_ids(
|
|||
assert str(fetched_recipe.tags[0].id) == str(tag.id)
|
||||
|
||||
|
||||
def test_create_recipe_from_zip_invalid_category(
|
||||
database: AllRepositories, api_client: TestClient, unique_user: TestUser, tempdir: str
|
||||
):
|
||||
def test_create_recipe_from_zip_invalid_category(api_client: TestClient, unique_user: TestUser, tempdir: str):
|
||||
database = unique_user.repos
|
||||
invalid_name = random_string()
|
||||
invalid_category = RecipeCategory(id=uuid4(), name=invalid_name, slug=invalid_name)
|
||||
|
||||
|
@ -382,9 +377,8 @@ def test_create_recipe_from_zip_invalid_category(
|
|||
assert fetched_recipe.recipe_category[0].slug == invalid_name
|
||||
|
||||
|
||||
def test_create_recipe_from_zip_invalid_tag(
|
||||
database: AllRepositories, api_client: TestClient, unique_user: TestUser, tempdir: str
|
||||
):
|
||||
def test_create_recipe_from_zip_invalid_tag(api_client: TestClient, unique_user: TestUser, tempdir: str):
|
||||
database = unique_user.repos
|
||||
invalid_name = random_string()
|
||||
invalid_tag = RecipeTag(id=uuid4(), name=invalid_name, slug=invalid_name)
|
||||
|
||||
|
@ -713,17 +707,15 @@ def test_get_recipe_by_slug_or_id(api_client: TestClient, unique_user: utils.Tes
|
|||
|
||||
|
||||
@pytest.mark.parametrize("organizer_type", ["tags", "categories", "tools"])
|
||||
def test_get_recipes_organizer_filter(
|
||||
api_client: TestClient, unique_user: utils.TestUser, organizer_type: str, database: AllRepositories
|
||||
):
|
||||
def test_get_recipes_organizer_filter(api_client: TestClient, unique_user: utils.TestUser, organizer_type: str):
|
||||
database = unique_user.repos
|
||||
|
||||
# create recipes with different organizers
|
||||
tags = database.tags.by_group(unique_user.group_id).create_many(
|
||||
[TagSave(name=random_string(), group_id=unique_user.group_id) for _ in range(3)]
|
||||
)
|
||||
categories = database.categories.by_group(unique_user.group_id).create_many(
|
||||
tags = database.tags.create_many([TagSave(name=random_string(), group_id=unique_user.group_id) for _ in range(3)])
|
||||
categories = database.categories.create_many(
|
||||
[CategorySave(name=random_string(), group_id=unique_user.group_id) for _ in range(3)]
|
||||
)
|
||||
tools = database.tools.by_group(unique_user.group_id).create_many(
|
||||
tools = database.tools.create_many(
|
||||
[RecipeToolSave(name=random_string(), group_id=unique_user.group_id) for _ in range(3)]
|
||||
)
|
||||
|
||||
|
@ -743,7 +735,7 @@ def test_get_recipes_organizer_filter(
|
|||
)
|
||||
)
|
||||
|
||||
recipes = database.recipes.by_group(unique_user.group_id).create_many(new_recipes_data) # type: ignore
|
||||
recipes = database.recipes.create_many(new_recipes_data) # type: ignore
|
||||
|
||||
# get recipes by organizer
|
||||
if organizer_type == "tags":
|
||||
|
|
|
@ -14,8 +14,8 @@ def test_ownership_on_new_with_admin(api_client: TestClient, admin_user: TestUse
|
|||
|
||||
recipe = api_client.get(api_routes.recipes + f"/{recipe_name}", headers=admin_user.token).json()
|
||||
|
||||
assert recipe["userId"] == admin_user.user_id
|
||||
assert recipe["groupId"] == admin_user.group_id
|
||||
assert recipe["userId"] == str(admin_user.user_id)
|
||||
assert recipe["groupId"] == str(admin_user.group_id)
|
||||
|
||||
|
||||
def test_ownership_on_new_with_user(api_client: TestClient, g2_user: TestUser):
|
||||
|
@ -29,8 +29,8 @@ def test_ownership_on_new_with_user(api_client: TestClient, g2_user: TestUser):
|
|||
|
||||
recipe = response.json()
|
||||
|
||||
assert recipe["userId"] == g2_user.user_id
|
||||
assert recipe["groupId"] == g2_user.group_id
|
||||
assert recipe["userId"] == str(g2_user.user_id)
|
||||
assert recipe["groupId"] == str(g2_user.group_id)
|
||||
|
||||
|
||||
def test_get_all_only_includes_group_recipes(api_client: TestClient, unique_user: TestUser):
|
||||
|
@ -47,8 +47,8 @@ def test_get_all_only_includes_group_recipes(api_client: TestClient, unique_user
|
|||
assert len(recipes) == 5
|
||||
|
||||
for recipe in recipes:
|
||||
assert recipe["groupId"] == unique_user.group_id
|
||||
assert recipe["userId"] == unique_user.user_id
|
||||
assert recipe["groupId"] == str(unique_user.group_id)
|
||||
assert recipe["userId"] == str(unique_user.user_id)
|
||||
|
||||
|
||||
def test_unique_slug_by_group(api_client: TestClient, unique_user: TestUser, g2_user: TestUser) -> None:
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import random
|
||||
from collections.abc import Generator
|
||||
from uuid import UUID
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from mealie.schema.user.user import UserRatingUpdate
|
||||
from tests.utils import api_routes
|
||||
|
@ -14,9 +12,10 @@ from tests.utils.fixture_schemas import TestUser
|
|||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def recipes(database: AllRepositories, user_tuple: tuple[TestUser, TestUser]) -> Generator[list[Recipe], None, None]:
|
||||
def recipes(user_tuple: tuple[TestUser, TestUser]) -> Generator[list[Recipe], None, None]:
|
||||
unique_user = random.choice(user_tuple)
|
||||
recipes_repo = database.recipes.by_group(UUID(unique_user.group_id))
|
||||
database = unique_user.repos
|
||||
recipes_repo = database.recipes
|
||||
|
||||
recipes: list[Recipe] = []
|
||||
for _ in range(random_int(10, 20)):
|
||||
|
@ -51,7 +50,6 @@ def test_user_recipe_favorites(
|
|||
unique_user = user_tuple[1]
|
||||
|
||||
response = api_client.get(api_routes.users_id_favorites(unique_user.user_id), headers=unique_user.token)
|
||||
assert response.json()["ratings"] == []
|
||||
|
||||
recipes_to_favorite = random.sample(recipes, random_int(5, len(recipes)))
|
||||
|
||||
|
@ -89,7 +87,11 @@ def test_user_recipe_favorites(
|
|||
assert len(ratings) == len(recipes_to_favorite) - len(recipe_favorites_to_remove)
|
||||
fetched_recipe_ids = {rating["recipeId"] for rating in ratings}
|
||||
removed_recipe_ids = {str(recipe.id) for recipe in recipe_favorites_to_remove}
|
||||
assert fetched_recipe_ids == favorited_recipe_ids - removed_recipe_ids
|
||||
|
||||
for recipe_id in removed_recipe_ids:
|
||||
assert recipe_id not in fetched_recipe_ids
|
||||
for recipe_id in fetched_recipe_ids:
|
||||
assert recipe_id in favorited_recipe_ids
|
||||
|
||||
|
||||
@pytest.mark.parametrize("add_favorite", [True, False])
|
||||
|
@ -119,8 +121,6 @@ def test_set_user_recipe_ratings(
|
|||
unique_user = user_tuple[1]
|
||||
|
||||
response = api_client.get(api_routes.users_id_ratings(unique_user.user_id), headers=unique_user.token)
|
||||
assert response.json()["ratings"] == []
|
||||
|
||||
recipes_to_rate = random.sample(recipes, random_int(8, len(recipes)))
|
||||
|
||||
expected_ratings_by_recipe_id: dict[str, UserRatingUpdate] = {}
|
||||
|
@ -144,12 +144,16 @@ def test_set_user_recipe_ratings(
|
|||
response = api_client.get(get_url, headers=unique_user.token)
|
||||
ratings = response.json()["ratings"]
|
||||
|
||||
assert len(ratings) == len(recipes_to_rate)
|
||||
for rating in ratings:
|
||||
recipe_id = rating["recipeId"]
|
||||
assert rating["rating"] == expected_ratings_by_recipe_id[recipe_id].rating
|
||||
if recipe_id not in expected_ratings_by_recipe_id:
|
||||
continue
|
||||
|
||||
assert rating["rating"] == expected_ratings_by_recipe_id.pop(recipe_id).rating
|
||||
assert not rating["isFavorite"]
|
||||
|
||||
assert not expected_ratings_by_recipe_id # we should have popped all of them
|
||||
|
||||
|
||||
def test_set_user_rating_invalid_recipe_404(api_client: TestClient, user_tuple: tuple[TestUser, TestUser]):
|
||||
unique_user = random.choice(user_tuple)
|
||||
|
@ -289,9 +293,10 @@ def test_set_rating_to_zero(api_client: TestClient, user_tuple: tuple[TestUser,
|
|||
|
||||
|
||||
def test_delete_recipe_deletes_ratings(
|
||||
database: AllRepositories, api_client: TestClient, user_tuple: tuple[TestUser, TestUser], recipes: list[Recipe]
|
||||
api_client: TestClient, user_tuple: tuple[TestUser, TestUser], recipes: list[Recipe]
|
||||
):
|
||||
unique_user = random.choice(user_tuple)
|
||||
database = unique_user.repos
|
||||
recipe = random.choice(recipes)
|
||||
rating = UserRatingUpdate(rating=random.uniform(1, 5), is_favorite=random.choice([True, False, None]))
|
||||
response = api_client.post(
|
||||
|
@ -306,6 +311,7 @@ def test_delete_recipe_deletes_ratings(
|
|||
assert response.json()
|
||||
|
||||
database.recipes.delete(recipe.id, match_key="id")
|
||||
database.session.commit()
|
||||
response = api_client.get(api_routes.users_self_ratings_recipe_id(recipe.id), headers=unique_user.token)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
|
|
@ -4,15 +4,15 @@ import pytest
|
|||
import sqlalchemy
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.recipe.recipe_share_token import RecipeShareTokenSave
|
||||
from mealie.schema.recipe.recipe_share_token import RecipeShareToken, RecipeShareTokenSave
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.factories import random_string
|
||||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def slug(api_client: TestClient, unique_user: TestUser, database: AllRepositories) -> Generator[str, None, None]:
|
||||
def slug(api_client: TestClient, unique_user: TestUser) -> Generator[str, None, None]:
|
||||
database = unique_user.repos
|
||||
payload = {"name": random_string(length=20)}
|
||||
response = api_client.post(api_routes.recipes, json=payload, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
@ -27,14 +27,13 @@ def slug(api_client: TestClient, unique_user: TestUser, database: AllRepositorie
|
|||
pass
|
||||
|
||||
|
||||
def test_recipe_share_tokens_get_all(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
slug: str,
|
||||
):
|
||||
def test_recipe_share_tokens_get_all(api_client: TestClient, unique_user: TestUser, slug: str):
|
||||
database = unique_user.repos
|
||||
|
||||
# Create 5 Tokens
|
||||
recipe = database.recipes.get_one(slug)
|
||||
assert recipe
|
||||
|
||||
tokens = []
|
||||
for _ in range(5):
|
||||
token = database.recipe_share_tokens.create(
|
||||
|
@ -50,14 +49,13 @@ def test_recipe_share_tokens_get_all(
|
|||
assert len(response_data) == 5
|
||||
|
||||
|
||||
def test_recipe_share_tokens_get_all_with_id(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
slug: str,
|
||||
):
|
||||
def test_recipe_share_tokens_get_all_with_id(api_client: TestClient, unique_user: TestUser, slug: str):
|
||||
database = unique_user.repos
|
||||
|
||||
# Create 5 Tokens
|
||||
recipe = database.recipes.get_one(slug)
|
||||
assert recipe
|
||||
|
||||
tokens = []
|
||||
for _ in range(3):
|
||||
token = database.recipe_share_tokens.create(
|
||||
|
@ -73,13 +71,10 @@ def test_recipe_share_tokens_get_all_with_id(
|
|||
assert len(response_data) == 3
|
||||
|
||||
|
||||
def test_recipe_share_tokens_create_and_get_one(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
slug: str,
|
||||
):
|
||||
def test_recipe_share_tokens_create_and_get_one(api_client: TestClient, unique_user: TestUser, slug: str):
|
||||
database = unique_user.repos
|
||||
recipe = database.recipes.get_one(slug)
|
||||
assert recipe
|
||||
|
||||
payload = {
|
||||
"recipeId": str(recipe.id),
|
||||
|
@ -95,14 +90,13 @@ def test_recipe_share_tokens_create_and_get_one(
|
|||
assert response_data["recipe"]["id"] == str(recipe.id)
|
||||
|
||||
|
||||
def test_recipe_share_tokens_delete_one(
|
||||
api_client: TestClient,
|
||||
unique_user: TestUser,
|
||||
database: AllRepositories,
|
||||
slug: str,
|
||||
):
|
||||
def test_recipe_share_tokens_delete_one(api_client: TestClient, unique_user: TestUser, slug: str):
|
||||
database = unique_user.repos
|
||||
|
||||
# Create Token
|
||||
token: RecipeShareToken | None = None
|
||||
recipe = database.recipes.get_one(slug)
|
||||
assert recipe
|
||||
|
||||
token = database.recipe_share_tokens.create(
|
||||
RecipeShareTokenSave(recipe_id=recipe.id, group_id=unique_user.group_id)
|
||||
|
|
|
@ -15,7 +15,7 @@ def test_associate_ingredient_with_step(api_client: TestClient, unique_user: Tes
|
|||
# Associate an ingredient with a step
|
||||
steps = {} # key=step_id, value=ingredient_id
|
||||
|
||||
for idx, step in enumerate(recipe.recipe_instructions):
|
||||
for idx, step in enumerate(recipe.recipe_instructions or []):
|
||||
ingredients = random.choices(recipe.recipe_ingredient, k=2)
|
||||
|
||||
step.ingredient_references = [
|
||||
|
@ -39,7 +39,7 @@ def test_associate_ingredient_with_step(api_client: TestClient, unique_user: Tes
|
|||
|
||||
data: dict = json.loads(response.text)
|
||||
|
||||
for idx, stp in enumerate(data.get("recipeInstructions")):
|
||||
for idx, stp in enumerate(data.get("recipeInstructions") or []):
|
||||
all_refs = [ref["referenceId"] for ref in stp.get("ingredientReferences")]
|
||||
|
||||
assert len(all_refs) == 2
|
||||
|
|
|
@ -39,7 +39,7 @@ def test_create_timeline_event(api_client: TestClient, unique_user: TestUser, re
|
|||
recipe = recipes[0]
|
||||
new_event = {
|
||||
"recipe_id": str(recipe.id),
|
||||
"user_id": unique_user.user_id,
|
||||
"user_id": str(unique_user.user_id),
|
||||
"subject": random_string(),
|
||||
"event_type": "info",
|
||||
"message": random_string(),
|
||||
|
@ -63,7 +63,7 @@ def test_get_all_timeline_events(api_client: TestClient, unique_user: TestUser,
|
|||
events_data = [
|
||||
{
|
||||
"recipe_id": str(recipe.id),
|
||||
"user_id": unique_user.user_id,
|
||||
"user_id": str(unique_user.user_id),
|
||||
"subject": random_string(),
|
||||
"event_type": "info",
|
||||
"message": random_string(),
|
||||
|
@ -98,7 +98,7 @@ def test_get_timeline_event(api_client: TestClient, unique_user: TestUser, recip
|
|||
recipe = recipes[0]
|
||||
new_event_data = {
|
||||
"recipe_id": str(recipe.id),
|
||||
"user_id": unique_user.user_id,
|
||||
"user_id": str(unique_user.user_id),
|
||||
"subject": random_string(),
|
||||
"event_type": "info",
|
||||
"message": random_string(),
|
||||
|
@ -127,7 +127,7 @@ def test_update_timeline_event(api_client: TestClient, unique_user: TestUser, re
|
|||
recipe = recipes[0]
|
||||
new_event_data = {
|
||||
"recipe_id": str(recipe.id),
|
||||
"user_id": unique_user.user_id,
|
||||
"user_id": str(unique_user.user_id),
|
||||
"subject": old_subject,
|
||||
"event_type": "info",
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ def test_delete_timeline_event(api_client: TestClient, unique_user: TestUser, re
|
|||
recipe = recipes[0]
|
||||
new_event_data = {
|
||||
"recipe_id": str(recipe.id),
|
||||
"user_id": unique_user.user_id,
|
||||
"user_id": str(unique_user.user_id),
|
||||
"subject": random_string(),
|
||||
"event_type": "info",
|
||||
"message": random_string(),
|
||||
|
@ -187,7 +187,7 @@ def test_timeline_event_message_alias(api_client: TestClient, unique_user: TestU
|
|||
recipe = recipes[0]
|
||||
new_event_data = {
|
||||
"recipeId": str(recipe.id),
|
||||
"userId": unique_user.user_id,
|
||||
"userId": str(unique_user.user_id),
|
||||
"subject": random_string(),
|
||||
"eventType": "info",
|
||||
"eventMessage": random_string(), # eventMessage is the correct alias for the message
|
||||
|
@ -234,7 +234,7 @@ def test_timeline_event_update_image(
|
|||
recipe = recipes[0]
|
||||
new_event_data = {
|
||||
"recipe_id": str(recipe.id),
|
||||
"user_id": unique_user.user_id,
|
||||
"user_id": str(unique_user.user_id),
|
||||
"subject": random_string(),
|
||||
"message": random_string(),
|
||||
"event_type": "info",
|
||||
|
@ -281,7 +281,7 @@ def test_create_recipe_with_timeline_event(api_client: TestClient, unique_user:
|
|||
def test_invalid_recipe_id(api_client: TestClient, unique_user: TestUser):
|
||||
new_event_data = {
|
||||
"recipe_id": str(uuid4()),
|
||||
"user_id": unique_user.user_id,
|
||||
"user_id": str(unique_user.user_id),
|
||||
"subject": random_string(),
|
||||
"event_type": "info",
|
||||
"message": random_string(),
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from tests.utils import TestUser, api_routes
|
||||
from tests.utils.factories import random_email, random_int, random_string
|
||||
|
||||
|
||||
@pytest.mark.parametrize("use_admin_user", [True, False])
|
||||
def test_get_all_users_admin(
|
||||
request: pytest.FixtureRequest, database: AllRepositories, api_client: TestClient, use_admin_user: bool
|
||||
):
|
||||
def test_get_all_users_admin(request: pytest.FixtureRequest, api_client: TestClient, use_admin_user: bool):
|
||||
user: TestUser
|
||||
if use_admin_user:
|
||||
user = request.getfixturevalue("admin_user")
|
||||
else:
|
||||
user = request.getfixturevalue("unique_user")
|
||||
|
||||
database = user.repos
|
||||
user_ids: set[str] = set()
|
||||
for _ in range(random_int(2, 5)):
|
||||
group = database.groups.create({"name": random_string()})
|
||||
household = database.households.create({"name": random_string(), "group_id": group.id})
|
||||
for _ in range(random_int(2, 5)):
|
||||
new_user = database.users.create(
|
||||
{
|
||||
"username": random_string(),
|
||||
"email": random_email(),
|
||||
"group": group.name,
|
||||
"household": household.name,
|
||||
"full_name": random_string(),
|
||||
"password": random_string(),
|
||||
"admin": False,
|
||||
|
@ -43,56 +43,3 @@ def test_get_all_users_admin(
|
|||
response_user_ids = {user["id"] for user in response.json()["items"]}
|
||||
for user_id in user_ids:
|
||||
assert user_id in response_user_ids
|
||||
|
||||
|
||||
@pytest.mark.parametrize("use_admin_user", [True, False])
|
||||
def test_get_all_group_users(
|
||||
request: pytest.FixtureRequest, database: AllRepositories, api_client: TestClient, use_admin_user: bool
|
||||
):
|
||||
user: TestUser
|
||||
if use_admin_user:
|
||||
user = request.getfixturevalue("admin_user")
|
||||
else:
|
||||
user = request.getfixturevalue("unique_user")
|
||||
|
||||
other_group_user_ids: set[str] = set()
|
||||
for _ in range(random_int(2, 5)):
|
||||
group = database.groups.create({"name": random_string()})
|
||||
for _ in range(random_int(2, 5)):
|
||||
new_user = database.users.create(
|
||||
{
|
||||
"username": random_string(),
|
||||
"email": random_email(),
|
||||
"group": group.name,
|
||||
"full_name": random_string(),
|
||||
"password": random_string(),
|
||||
"admin": False,
|
||||
}
|
||||
)
|
||||
other_group_user_ids.add(str(new_user.id))
|
||||
|
||||
user_group = database.groups.get_by_slug_or_id(user.group_id)
|
||||
assert user_group
|
||||
same_group_user_ids: set[str] = {user.user_id}
|
||||
for _ in range(random_int(2, 5)):
|
||||
new_user = database.users.create(
|
||||
{
|
||||
"username": random_string(),
|
||||
"email": random_email(),
|
||||
"group": user_group.name,
|
||||
"full_name": random_string(),
|
||||
"password": random_string(),
|
||||
"admin": False,
|
||||
}
|
||||
)
|
||||
same_group_user_ids.add(str(new_user.id))
|
||||
|
||||
response = api_client.get(api_routes.users_group_users, params={"perPage": -1}, headers=user.token)
|
||||
assert response.status_code == 200
|
||||
response_user_ids = {user["id"] for user in response.json()["items"]}
|
||||
|
||||
# assert only users from the same group are returned
|
||||
for user_id in other_group_user_ids:
|
||||
assert user_id not in response_user_ids
|
||||
for user_id in same_group_user_ids:
|
||||
assert user_id in response_user_ids
|
||||
|
|
|
@ -4,7 +4,6 @@ import pytest
|
|||
from fastapi.testclient import TestClient
|
||||
|
||||
from mealie.core.config import get_app_settings
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.services.user_services.user_service import UserService
|
||||
from tests.utils import api_routes
|
||||
from tests.utils.factories import random_string
|
||||
|
@ -45,11 +44,12 @@ def test_get_logged_in_user_invalid_token(api_client: TestClient, use_token: boo
|
|||
assert response.status_code == 401
|
||||
|
||||
|
||||
def test_user_lockout_after_bad_attemps(api_client: TestClient, unique_user: TestUser, database: AllRepositories):
|
||||
def test_user_lockout_after_bad_attemps(api_client: TestClient, unique_user: TestUser):
|
||||
"""
|
||||
if the user has more than 5 bad login attempts the user will be locked out for 4 hours
|
||||
This only applies if there is a user in the database with the same username
|
||||
"""
|
||||
database = unique_user.repos
|
||||
settings = get_app_settings()
|
||||
|
||||
for _ in range(settings.SECURITY_MAX_LOGIN_ATTEMPTS):
|
||||
|
|
|
@ -23,7 +23,7 @@ all_cases = [
|
|||
def test_multitenant_cases_get_all(
|
||||
api_client: TestClient,
|
||||
multitenants: MultiTenant,
|
||||
database: AllRepositories,
|
||||
unfiltered_database: AllRepositories,
|
||||
test_case_type: type[ABCMultiTenantTestCase],
|
||||
):
|
||||
"""
|
||||
|
@ -34,7 +34,7 @@ def test_multitenant_cases_get_all(
|
|||
user1 = multitenants.user_one
|
||||
user2 = multitenants.user_two
|
||||
|
||||
test_case = test_case_type(database, api_client)
|
||||
test_case = test_case_type(unfiltered_database, api_client)
|
||||
|
||||
with test_case:
|
||||
expected_ids = test_case.seed_action(user1.group_id)
|
||||
|
@ -60,7 +60,7 @@ def test_multitenant_cases_get_all(
|
|||
def test_multitenant_cases_same_named_resources(
|
||||
api_client: TestClient,
|
||||
multitenants: MultiTenant,
|
||||
database: AllRepositories,
|
||||
unfiltered_database: AllRepositories,
|
||||
test_case_type: type[ABCMultiTenantTestCase],
|
||||
):
|
||||
"""
|
||||
|
@ -71,7 +71,7 @@ def test_multitenant_cases_same_named_resources(
|
|||
user1 = multitenants.user_one
|
||||
user2 = multitenants.user_two
|
||||
|
||||
test_case = test_case_type(database, api_client)
|
||||
test_case = test_case_type(unfiltered_database, api_client)
|
||||
|
||||
with test_case:
|
||||
expected_ids, expected_ids2 = test_case.seed_multi(user1.group_id, user2.group_id)
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
from mealie.repos.repository_factory import AllRepositories
|
||||
from tests.fixtures.fixture_multitenant import MultiTenant
|
||||
|
||||
|
||||
def test_multitenant_recipe_data_storage(
|
||||
multitenants: MultiTenant,
|
||||
database: AllRepositories,
|
||||
):
|
||||
pass
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
from mealie.schema.group.group_shopping_list import ShoppingListItemOut
|
||||
import uuid
|
||||
|
||||
from mealie.schema.household.group_shopping_list import ShoppingListItemOut
|
||||
|
||||
|
||||
def test_shopping_list_ingredient_validation():
|
||||
|
@ -15,7 +17,7 @@ def test_shopping_list_ingredient_validation():
|
|||
"aliases": [],
|
||||
"label": None,
|
||||
"createdAt": "2024-02-26T18:29:46.190754",
|
||||
"updateAt": "2024-02-26T18:29:46.190758",
|
||||
"updatedAt": "2024-02-26T18:29:46.190758",
|
||||
},
|
||||
"note": "",
|
||||
"isFood": True,
|
||||
|
@ -30,8 +32,10 @@ def test_shopping_list_ingredient_validation():
|
|||
"id": "80f4df25-6139-4d30-be0c-4100f50e5396",
|
||||
"label": None,
|
||||
"recipeReferences": [],
|
||||
"groupId": uuid.uuid4(),
|
||||
"householdId": uuid.uuid4(),
|
||||
"createdAt": "2024-02-27T10:18:19.274677",
|
||||
"updateAt": "2024-02-27T11:26:32.643392",
|
||||
"updatedAt": "2024-02-27T11:26:32.643392",
|
||||
}
|
||||
out = ShoppingListItemOut.model_validate(db_obj)
|
||||
assert out.display == "8 bell peppers"
|
||||
|
|
|
@ -11,7 +11,7 @@ from mealie.core.config import get_app_settings
|
|||
from mealie.db.db_setup import session_context
|
||||
from mealie.db.models._model_utils.guid import GUID
|
||||
from mealie.db.models.group import Group
|
||||
from mealie.db.models.group.shopping_list import ShoppingList
|
||||
from mealie.db.models.household.shopping_list import ShoppingList
|
||||
from mealie.db.models.labels import MultiPurposeLabel
|
||||
from mealie.db.models.recipe.ingredient import IngredientFoodModel, IngredientUnitModel
|
||||
from mealie.db.models.recipe.recipe import RecipeModel
|
||||
|
|
|
@ -40,7 +40,7 @@ def test_new_mealplan_event(api_client: TestClient, unique_user: TestUser):
|
|||
new_plan["date"] = datetime.now(timezone.utc).date().isoformat()
|
||||
new_plan["recipeId"] = str(recipe_id)
|
||||
|
||||
response = api_client.post(api_routes.groups_mealplans, json=new_plan, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
# run the task and check to make sure a new event was created from the mealplan
|
||||
|
@ -70,7 +70,7 @@ def test_new_mealplan_event(api_client: TestClient, unique_user: TestUser):
|
|||
# make sure nothing else was updated
|
||||
for data in [original_recipe_data, new_recipe_data]:
|
||||
data.pop("dateUpdated")
|
||||
data.pop("updateAt")
|
||||
data.pop("updatedAt")
|
||||
data.pop("lastMade")
|
||||
|
||||
# instructions ids are generated randomly and aren't consistent between get requests
|
||||
|
@ -107,7 +107,7 @@ def test_new_mealplan_event_duplicates(api_client: TestClient, unique_user: Test
|
|||
new_plan["date"] = datetime.now(timezone.utc).date().isoformat()
|
||||
new_plan["recipeId"] = str(recipe_id)
|
||||
|
||||
response = api_client.post(api_routes.groups_mealplans, json=new_plan, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
# run the task multiple times and make sure we only create one event
|
||||
|
@ -153,7 +153,7 @@ def test_new_mealplan_events_with_multiple_recipes(api_client: TestClient, uniqu
|
|||
new_plan["date"] = datetime.now(timezone.utc).date().isoformat()
|
||||
new_plan["recipeId"] = str(recipe.id)
|
||||
|
||||
response = api_client.post(api_routes.groups_mealplans, json=new_plan, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
mealplan_count_by_recipe_id[recipe.id] += 1 # type: ignore
|
||||
|
||||
|
@ -213,7 +213,7 @@ def test_preserve_future_made_date(api_client: TestClient, unique_user: TestUser
|
|||
new_plan["date"] = datetime.now(timezone.utc).date().isoformat()
|
||||
new_plan["recipeId"] = str(recipe_id)
|
||||
|
||||
response = api_client.post(api_routes.groups_mealplans, json=new_plan, headers=unique_user.token)
|
||||
response = api_client.post(api_routes.households_mealplans, json=new_plan, headers=unique_user.token)
|
||||
assert response.status_code == 201
|
||||
|
||||
# run the task and make sure the recipe's last made date was not updated
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from datetime import datetime, timezone
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.group.group_shopping_list import ShoppingListItemCreate, ShoppingListItemOut, ShoppingListSave
|
||||
from mealie.schema.household.group_shopping_list import ShoppingListItemCreate, ShoppingListItemOut, ShoppingListSave
|
||||
from mealie.services.scheduler.tasks.delete_old_checked_shopping_list_items import (
|
||||
MAX_CHECKED_ITEMS,
|
||||
delete_old_checked_list_items,
|
||||
|
@ -10,12 +9,17 @@ from tests.utils.factories import random_int, random_string
|
|||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
def test_cleanup(database: AllRepositories, unique_user: TestUser):
|
||||
list_repo = database.group_shopping_lists.by_group(unique_user.group_id)
|
||||
def test_cleanup(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
list_repo = database.group_shopping_lists
|
||||
list_item_repo = database.group_shopping_list_item
|
||||
|
||||
shopping_list = list_repo.create(
|
||||
ShoppingListSave(name=random_string(), group_id=unique_user.group_id, user_id=unique_user.user_id)
|
||||
ShoppingListSave(
|
||||
name=random_string(),
|
||||
group_id=unique_user.group_id,
|
||||
user_id=unique_user.user_id,
|
||||
)
|
||||
)
|
||||
unchecked_items = list_item_repo.create_many(
|
||||
[
|
||||
|
@ -40,12 +44,13 @@ def test_cleanup(database: AllRepositories, unique_user: TestUser):
|
|||
for item in unchecked_items + checked_items:
|
||||
assert item in shopping_list.list_items
|
||||
|
||||
checked_items.sort(key=lambda x: x.update_at or datetime.now(timezone.utc), reverse=True)
|
||||
checked_items.sort(key=lambda x: x.updated_at or datetime.now(timezone.utc), reverse=True)
|
||||
expected_kept_items = unchecked_items + checked_items[:MAX_CHECKED_ITEMS]
|
||||
expected_deleted_items = checked_items[MAX_CHECKED_ITEMS:]
|
||||
|
||||
# make sure we only see the expected items
|
||||
delete_old_checked_list_items()
|
||||
database.session.commit()
|
||||
shopping_list = list_repo.get_one(shopping_list.id) # type: ignore
|
||||
assert shopping_list
|
||||
assert len(shopping_list.list_items) == len(expected_kept_items)
|
||||
|
@ -55,12 +60,17 @@ def test_cleanup(database: AllRepositories, unique_user: TestUser):
|
|||
assert item not in shopping_list.list_items
|
||||
|
||||
|
||||
def test_no_cleanup(database: AllRepositories, unique_user: TestUser):
|
||||
list_repo = database.group_shopping_lists.by_group(unique_user.group_id)
|
||||
def test_no_cleanup(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
list_repo = database.group_shopping_lists
|
||||
list_item_repo = database.group_shopping_list_item
|
||||
|
||||
shopping_list = list_repo.create(
|
||||
ShoppingListSave(name=random_string(), group_id=unique_user.group_id, user_id=unique_user.user_id)
|
||||
ShoppingListSave(
|
||||
name=random_string(),
|
||||
group_id=unique_user.group_id,
|
||||
user_id=unique_user.user_id,
|
||||
)
|
||||
)
|
||||
unchecked_items = list_item_repo.create_many(
|
||||
[
|
||||
|
@ -87,6 +97,7 @@ def test_no_cleanup(database: AllRepositories, unique_user: TestUser):
|
|||
|
||||
# make sure we still see all items
|
||||
delete_old_checked_list_items()
|
||||
database.session.commit()
|
||||
shopping_list = list_repo.get_one(shopping_list.id) # type: ignore
|
||||
assert shopping_list
|
||||
assert len(shopping_list.list_items) == len(unchecked_items) + len(checked_items)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from datetime import datetime, timedelta, timezone
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.group.webhook import SaveWebhook, WebhookType
|
||||
from mealie.schema.household.webhook import SaveWebhook, WebhookType
|
||||
from mealie.services.event_bus_service.event_bus_listeners import WebhookEventListener
|
||||
from tests.utils import random_string
|
||||
from tests.utils.factories import random_bool
|
||||
|
@ -12,6 +12,7 @@ from tests.utils.fixture_schemas import TestUser
|
|||
|
||||
def webhook_factory(
|
||||
group_id: str | UUID4,
|
||||
household_id: str | UUID4,
|
||||
enabled: bool = True,
|
||||
name: str = "",
|
||||
url: str = "",
|
||||
|
@ -25,22 +26,27 @@ def webhook_factory(
|
|||
webhook_type=webhook_type,
|
||||
scheduled_time=scheduled_time.time() if scheduled_time else datetime.now(timezone.utc).time(),
|
||||
group_id=group_id,
|
||||
household_id=household_id,
|
||||
)
|
||||
|
||||
|
||||
def test_get_scheduled_webhooks_filter_query(database: AllRepositories, unique_user: TestUser):
|
||||
def test_get_scheduled_webhooks_filter_query(unique_user: TestUser):
|
||||
"""
|
||||
get_scheduled_webhooks_test tests the get_scheduled_webhooks function on the webhook event bus listener.
|
||||
"""
|
||||
|
||||
database = unique_user.repos
|
||||
expected: list[SaveWebhook] = []
|
||||
|
||||
start = datetime.now(timezone.utc)
|
||||
|
||||
for _ in range(5):
|
||||
new_item = webhook_factory(group_id=unique_user.group_id, enabled=random_bool())
|
||||
new_item = webhook_factory(
|
||||
group_id=unique_user.group_id, household_id=unique_user.household_id, enabled=random_bool()
|
||||
)
|
||||
out_of_range_item = webhook_factory(
|
||||
group_id=unique_user.group_id,
|
||||
household_id=unique_user.household_id,
|
||||
enabled=random_bool(),
|
||||
scheduled_time=(start - timedelta(minutes=20)),
|
||||
)
|
||||
|
@ -51,7 +57,7 @@ def test_get_scheduled_webhooks_filter_query(database: AllRepositories, unique_u
|
|||
if new_item.enabled:
|
||||
expected.append(new_item)
|
||||
|
||||
event_bus_listener = WebhookEventListener(unique_user.group_id) # type: ignore
|
||||
event_bus_listener = WebhookEventListener(UUID(unique_user.group_id), UUID(unique_user.household_id))
|
||||
results = event_bus_listener.get_scheduled_webhooks(start, datetime.now(timezone.utc) + timedelta(minutes=5))
|
||||
|
||||
assert len(results) == len(expected)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import tempfile
|
||||
from pathlib import Path
|
||||
from uuid import UUID
|
||||
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from mealie.services.recipe.recipe_bulk_service import RecipeBulkActionsService
|
||||
from mealie.services.scheduler.tasks.purge_group_exports import purge_group_data_exports
|
||||
|
@ -9,7 +9,9 @@ from tests.utils.factories import random_int, random_string
|
|||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
def test_purge_group_exports(database: AllRepositories, unique_user: TestUser):
|
||||
def test_purge_group_exports(unique_user: TestUser):
|
||||
database = unique_user.repos
|
||||
|
||||
# create the export
|
||||
group = database.groups.get_one(unique_user.group_id)
|
||||
assert group
|
||||
|
@ -17,7 +19,14 @@ def test_purge_group_exports(database: AllRepositories, unique_user: TestUser):
|
|||
assert user
|
||||
recipe_exporter = RecipeBulkActionsService(database, user, group)
|
||||
recipes = [
|
||||
database.recipes.create(Recipe(name=random_string(), group_id=group.id)) for _ in range(random_int(2, 5))
|
||||
database.recipes.create(
|
||||
Recipe(
|
||||
name=random_string(),
|
||||
group_id=UUID(unique_user.group_id),
|
||||
user_id=unique_user.user_id,
|
||||
)
|
||||
)
|
||||
for _ in range(random_int(2, 5))
|
||||
]
|
||||
|
||||
with tempfile.NamedTemporaryFile() as tmpfile:
|
||||
|
|
|
@ -5,14 +5,16 @@ from mealie.services.user_services.user_service import UserService
|
|||
from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
def test_get_locked_users(database: AllRepositories, user_tuple: list[TestUser]) -> None:
|
||||
def test_get_locked_users(user_tuple: list[TestUser]) -> None:
|
||||
usr_1, usr_2 = user_tuple
|
||||
database = usr_1.repos
|
||||
|
||||
# Setup
|
||||
user_service = UserService(database)
|
||||
|
||||
user_1 = database.users.get_one(usr_1.user_id)
|
||||
user_2 = database.users.get_one(usr_2.user_id)
|
||||
assert user_1 and user_2
|
||||
|
||||
locked_users = user_service.get_locked_users()
|
||||
assert len(locked_users) == 0
|
||||
|
@ -41,11 +43,13 @@ def test_get_locked_users(database: AllRepositories, user_tuple: list[TestUser])
|
|||
user_service.unlock_user(user_2)
|
||||
|
||||
|
||||
def test_lock_unlocker_user(database: AllRepositories, unique_user: TestUser) -> None:
|
||||
def test_lock_unlocker_user(unique_user: TestUser) -> None:
|
||||
database = unique_user.repos
|
||||
user_service = UserService(database)
|
||||
|
||||
# Test that the user is unlocked
|
||||
user = database.users.get_one(unique_user.user_id)
|
||||
assert user
|
||||
assert not user.locked_at
|
||||
|
||||
# Test that the user is locked
|
||||
|
@ -63,11 +67,13 @@ def test_lock_unlocker_user(database: AllRepositories, unique_user: TestUser) ->
|
|||
assert not user.is_locked
|
||||
|
||||
|
||||
def test_reset_locked_users(database: AllRepositories, unique_user: TestUser) -> None:
|
||||
def test_reset_locked_users(unique_user: TestUser) -> None:
|
||||
database = unique_user.repos
|
||||
user_service = UserService(database)
|
||||
|
||||
# Test that the user is unlocked
|
||||
user = database.users.get_one(unique_user.user_id)
|
||||
assert user
|
||||
assert not user.is_locked
|
||||
assert not user.locked_at
|
||||
|
||||
|
@ -80,6 +86,7 @@ def test_reset_locked_users(database: AllRepositories, unique_user: TestUser) ->
|
|||
# Test that the locked user is not unlocked by reset
|
||||
unlocked = user_service.reset_locked_users()
|
||||
user = database.users.get_one(unique_user.user_id)
|
||||
assert user
|
||||
assert unlocked == 0
|
||||
assert user.is_locked
|
||||
assert user.login_attemps == 5
|
||||
|
@ -89,6 +96,7 @@ def test_reset_locked_users(database: AllRepositories, unique_user: TestUser) ->
|
|||
database.users.update(user.id, user)
|
||||
unlocked = user_service.reset_locked_users()
|
||||
user = database.users.get_one(unique_user.user_id)
|
||||
assert user
|
||||
assert unlocked == 1
|
||||
assert not user.is_locked
|
||||
assert user.login_attemps == 0
|
||||
|
|
|
@ -6,8 +6,10 @@ from fractions import Fraction
|
|||
|
||||
import pytest
|
||||
from pydantic import UUID4
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from mealie.db.db_setup import session_context
|
||||
from mealie.repos.all_repositories import get_repositories
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.openai.recipe_ingredient import OpenAIIngredient, OpenAIIngredients
|
||||
from mealie.schema.recipe.recipe_ingredient import (
|
||||
|
@ -56,15 +58,20 @@ def build_parsed_ing(food: str | None, unit: str | None) -> ParsedIngredient:
|
|||
|
||||
|
||||
@pytest.fixture()
|
||||
def unique_local_group_id(database: AllRepositories) -> UUID4:
|
||||
return str(database.groups.create(GroupBase(name=random_string())).id)
|
||||
def unique_local_group_id(unfiltered_database: AllRepositories) -> UUID4:
|
||||
return str(unfiltered_database.groups.create(GroupBase(name=random_string())).id)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def unique_db(session: Session, unique_local_group_id: str):
|
||||
return get_repositories(session, group_id=unique_local_group_id)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def parsed_ingredient_data(
|
||||
database: AllRepositories, unique_local_group_id: UUID4
|
||||
unique_db: AllRepositories, unique_local_group_id: UUID4
|
||||
) -> tuple[list[IngredientFood], list[IngredientUnit]]:
|
||||
foods = database.ingredient_foods.create_many(
|
||||
foods = unique_db.ingredient_foods.create_many(
|
||||
[
|
||||
SaveIngredientFood(name="potatoes", group_id=unique_local_group_id),
|
||||
SaveIngredientFood(name="onion", group_id=unique_local_group_id),
|
||||
|
@ -85,7 +92,7 @@ def parsed_ingredient_data(
|
|||
)
|
||||
|
||||
foods.extend(
|
||||
database.ingredient_foods.create_many(
|
||||
unique_db.ingredient_foods.create_many(
|
||||
[
|
||||
SaveIngredientFood(name=f"{random_string()} food", group_id=unique_local_group_id)
|
||||
for _ in range(random_int(10, 15))
|
||||
|
@ -93,7 +100,7 @@ def parsed_ingredient_data(
|
|||
)
|
||||
)
|
||||
|
||||
units = database.ingredient_units.create_many(
|
||||
units = unique_db.ingredient_units.create_many(
|
||||
[
|
||||
SaveIngredientUnit(name="Cups", group_id=unique_local_group_id),
|
||||
SaveIngredientUnit(name="Tablespoon", group_id=unique_local_group_id),
|
||||
|
@ -116,7 +123,7 @@ def parsed_ingredient_data(
|
|||
)
|
||||
|
||||
units.extend(
|
||||
database.ingredient_foods.create_many(
|
||||
unique_db.ingredient_foods.create_many(
|
||||
[
|
||||
SaveIngredientUnit(name=f"{random_string()} unit", group_id=unique_local_group_id)
|
||||
for _ in range(random_int(10, 15))
|
||||
|
|
|
@ -6,6 +6,7 @@ from mealie.schema.user.registration import CreateUserRegistration
|
|||
def test_create_user_registration() -> None:
|
||||
CreateUserRegistration(
|
||||
group="Home",
|
||||
household="Family",
|
||||
group_token=None,
|
||||
email="SomeValidEmail@example.com",
|
||||
username="SomeValidUsername",
|
||||
|
@ -18,6 +19,7 @@ def test_create_user_registration() -> None:
|
|||
|
||||
CreateUserRegistration(
|
||||
group=None,
|
||||
household=None,
|
||||
group_token="asdfadsfasdfasdfasdf",
|
||||
email="SomeValidEmail@example.com",
|
||||
username="SomeValidUsername",
|
||||
|
@ -29,11 +31,14 @@ def test_create_user_registration() -> None:
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("group, group_token", [(None, None), ("", None), (None, "")])
|
||||
def test_group_or_token_validator(group, group_token) -> None:
|
||||
@pytest.mark.parametrize("group", [None, ""])
|
||||
@pytest.mark.parametrize("household", [None, ""])
|
||||
@pytest.mark.parametrize("group_token", [None, ""])
|
||||
def test_group_or_token_validator(group, household, group_token) -> None:
|
||||
with pytest.raises(ValueError):
|
||||
CreateUserRegistration(
|
||||
group=group,
|
||||
household=household,
|
||||
group_token=group_token,
|
||||
email="SomeValidEmail@example.com",
|
||||
username="SomeValidUsername",
|
||||
|
@ -62,6 +67,7 @@ def test_password_validator() -> None:
|
|||
with pytest.raises(ValueError):
|
||||
CreateUserRegistration(
|
||||
group=None,
|
||||
household=None,
|
||||
group_token="asdfadsfasdfasdfasdf",
|
||||
email="SomeValidEmail@example.com",
|
||||
username="SomeValidUsername",
|
||||
|
@ -71,6 +77,3 @@ def test_password_validator() -> None:
|
|||
advanced=False,
|
||||
private=True,
|
||||
)
|
||||
|
||||
|
||||
test_create_user_registration()
|
||||
|
|
|
@ -7,8 +7,6 @@ admin_about_check = "/api/admin/about/check"
|
|||
"""`/api/admin/about/check`"""
|
||||
admin_about_statistics = "/api/admin/about/statistics"
|
||||
"""`/api/admin/about/statistics`"""
|
||||
admin_analytics = "/api/admin/analytics"
|
||||
"""`/api/admin/analytics`"""
|
||||
admin_backups = "/api/admin/backups"
|
||||
"""`/api/admin/backups`"""
|
||||
admin_backups_upload = "/api/admin/backups/upload"
|
||||
|
@ -17,6 +15,8 @@ admin_email = "/api/admin/email"
|
|||
"""`/api/admin/email`"""
|
||||
admin_groups = "/api/admin/groups"
|
||||
"""`/api/admin/groups`"""
|
||||
admin_households = "/api/admin/households"
|
||||
"""`/api/admin/households`"""
|
||||
admin_maintenance = "/api/admin/maintenance"
|
||||
"""`/api/admin/maintenance`"""
|
||||
admin_maintenance_clean_images = "/api/admin/maintenance/clean/images"
|
||||
|
@ -53,36 +53,16 @@ foods = "/api/foods"
|
|||
"""`/api/foods`"""
|
||||
foods_merge = "/api/foods/merge"
|
||||
"""`/api/foods/merge`"""
|
||||
groups_categories = "/api/groups/categories"
|
||||
"""`/api/groups/categories`"""
|
||||
groups_cookbooks = "/api/groups/cookbooks"
|
||||
"""`/api/groups/cookbooks`"""
|
||||
groups_events_notifications = "/api/groups/events/notifications"
|
||||
"""`/api/groups/events/notifications`"""
|
||||
groups_invitations = "/api/groups/invitations"
|
||||
"""`/api/groups/invitations`"""
|
||||
groups_invitations_email = "/api/groups/invitations/email"
|
||||
"""`/api/groups/invitations/email`"""
|
||||
groups_households = "/api/groups/households"
|
||||
"""`/api/groups/households`"""
|
||||
groups_labels = "/api/groups/labels"
|
||||
"""`/api/groups/labels`"""
|
||||
groups_mealplans = "/api/groups/mealplans"
|
||||
"""`/api/groups/mealplans`"""
|
||||
groups_mealplans_random = "/api/groups/mealplans/random"
|
||||
"""`/api/groups/mealplans/random`"""
|
||||
groups_mealplans_rules = "/api/groups/mealplans/rules"
|
||||
"""`/api/groups/mealplans/rules`"""
|
||||
groups_mealplans_today = "/api/groups/mealplans/today"
|
||||
"""`/api/groups/mealplans/today`"""
|
||||
groups_members = "/api/groups/members"
|
||||
"""`/api/groups/members`"""
|
||||
groups_migrations = "/api/groups/migrations"
|
||||
"""`/api/groups/migrations`"""
|
||||
groups_permissions = "/api/groups/permissions"
|
||||
"""`/api/groups/permissions`"""
|
||||
groups_preferences = "/api/groups/preferences"
|
||||
"""`/api/groups/preferences`"""
|
||||
groups_recipe_actions = "/api/groups/recipe-actions"
|
||||
"""`/api/groups/recipe-actions`"""
|
||||
groups_reports = "/api/groups/reports"
|
||||
"""`/api/groups/reports`"""
|
||||
groups_seeders_foods = "/api/groups/seeders/foods"
|
||||
|
@ -93,20 +73,46 @@ groups_seeders_units = "/api/groups/seeders/units"
|
|||
"""`/api/groups/seeders/units`"""
|
||||
groups_self = "/api/groups/self"
|
||||
"""`/api/groups/self`"""
|
||||
groups_shopping_items = "/api/groups/shopping/items"
|
||||
"""`/api/groups/shopping/items`"""
|
||||
groups_shopping_items_create_bulk = "/api/groups/shopping/items/create-bulk"
|
||||
"""`/api/groups/shopping/items/create-bulk`"""
|
||||
groups_shopping_lists = "/api/groups/shopping/lists"
|
||||
"""`/api/groups/shopping/lists`"""
|
||||
groups_statistics = "/api/groups/statistics"
|
||||
"""`/api/groups/statistics`"""
|
||||
groups_storage = "/api/groups/storage"
|
||||
"""`/api/groups/storage`"""
|
||||
groups_webhooks = "/api/groups/webhooks"
|
||||
"""`/api/groups/webhooks`"""
|
||||
groups_webhooks_rerun = "/api/groups/webhooks/rerun"
|
||||
"""`/api/groups/webhooks/rerun`"""
|
||||
households_cookbooks = "/api/households/cookbooks"
|
||||
"""`/api/households/cookbooks`"""
|
||||
households_events_notifications = "/api/households/events/notifications"
|
||||
"""`/api/households/events/notifications`"""
|
||||
households_invitations = "/api/households/invitations"
|
||||
"""`/api/households/invitations`"""
|
||||
households_invitations_email = "/api/households/invitations/email"
|
||||
"""`/api/households/invitations/email`"""
|
||||
households_mealplans = "/api/households/mealplans"
|
||||
"""`/api/households/mealplans`"""
|
||||
households_mealplans_random = "/api/households/mealplans/random"
|
||||
"""`/api/households/mealplans/random`"""
|
||||
households_mealplans_rules = "/api/households/mealplans/rules"
|
||||
"""`/api/households/mealplans/rules`"""
|
||||
households_mealplans_today = "/api/households/mealplans/today"
|
||||
"""`/api/households/mealplans/today`"""
|
||||
households_members = "/api/households/members"
|
||||
"""`/api/households/members`"""
|
||||
households_permissions = "/api/households/permissions"
|
||||
"""`/api/households/permissions`"""
|
||||
households_preferences = "/api/households/preferences"
|
||||
"""`/api/households/preferences`"""
|
||||
households_recipe_actions = "/api/households/recipe-actions"
|
||||
"""`/api/households/recipe-actions`"""
|
||||
households_self = "/api/households/self"
|
||||
"""`/api/households/self`"""
|
||||
households_shopping_items = "/api/households/shopping/items"
|
||||
"""`/api/households/shopping/items`"""
|
||||
households_shopping_items_create_bulk = "/api/households/shopping/items/create-bulk"
|
||||
"""`/api/households/shopping/items/create-bulk`"""
|
||||
households_shopping_lists = "/api/households/shopping/lists"
|
||||
"""`/api/households/shopping/lists`"""
|
||||
households_statistics = "/api/households/statistics"
|
||||
"""`/api/households/statistics`"""
|
||||
households_webhooks = "/api/households/webhooks"
|
||||
"""`/api/households/webhooks`"""
|
||||
households_webhooks_rerun = "/api/households/webhooks/rerun"
|
||||
"""`/api/households/webhooks/rerun`"""
|
||||
media_docker_validate_txt = "/api/media/docker/validate.txt"
|
||||
"""`/api/media/docker/validate.txt`"""
|
||||
organizers_categories = "/api/organizers/categories"
|
||||
|
@ -149,10 +155,6 @@ recipes_create_url_bulk = "/api/recipes/create-url/bulk"
|
|||
"""`/api/recipes/create-url/bulk`"""
|
||||
recipes_exports = "/api/recipes/exports"
|
||||
"""`/api/recipes/exports`"""
|
||||
recipes_summary_uncategorized = "/api/recipes/summary/uncategorized"
|
||||
"""`/api/recipes/summary/uncategorized`"""
|
||||
recipes_summary_untagged = "/api/recipes/summary/untagged"
|
||||
"""`/api/recipes/summary/untagged`"""
|
||||
recipes_test_scrape_url = "/api/recipes/test-scrape-url"
|
||||
"""`/api/recipes/test-scrape-url`"""
|
||||
recipes_timeline_events = "/api/recipes/timeline/events"
|
||||
|
@ -169,8 +171,6 @@ users_api_tokens = "/api/users/api-tokens"
|
|||
"""`/api/users/api-tokens`"""
|
||||
users_forgot_password = "/api/users/forgot-password"
|
||||
"""`/api/users/forgot-password`"""
|
||||
users_group_users = "/api/users/group-users"
|
||||
"""`/api/users/group-users`"""
|
||||
users_password = "/api/users/password"
|
||||
"""`/api/users/password`"""
|
||||
users_register = "/api/users/register"
|
||||
|
@ -187,6 +187,8 @@ utils_download = "/api/utils/download"
|
|||
"""`/api/utils/download`"""
|
||||
validators_group = "/api/validators/group"
|
||||
"""`/api/validators/group`"""
|
||||
validators_household = "/api/validators/household"
|
||||
"""`/api/validators/household`"""
|
||||
validators_recipe = "/api/validators/recipe"
|
||||
"""`/api/validators/recipe`"""
|
||||
validators_user_email = "/api/validators/user/email"
|
||||
|
@ -210,6 +212,11 @@ def admin_groups_item_id(item_id):
|
|||
return f"{prefix}/admin/groups/{item_id}"
|
||||
|
||||
|
||||
def admin_households_item_id(item_id):
|
||||
"""`/api/admin/households/{item_id}`"""
|
||||
return f"{prefix}/admin/households/{item_id}"
|
||||
|
||||
|
||||
def admin_users_item_id(item_id):
|
||||
"""`/api/admin/users/{item_id}`"""
|
||||
return f"{prefix}/admin/users/{item_id}"
|
||||
|
@ -220,64 +227,64 @@ def comments_item_id(item_id):
|
|||
return f"{prefix}/comments/{item_id}"
|
||||
|
||||
|
||||
def explore_cookbooks_group_slug(group_slug):
|
||||
"""`/api/explore/cookbooks/{group_slug}`"""
|
||||
return f"{prefix}/explore/cookbooks/{group_slug}"
|
||||
def explore_groups_group_slug_cookbooks(group_slug):
|
||||
"""`/api/explore/groups/{group_slug}/cookbooks`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/cookbooks"
|
||||
|
||||
|
||||
def explore_cookbooks_group_slug_item_id(group_slug, item_id):
|
||||
"""`/api/explore/cookbooks/{group_slug}/{item_id}`"""
|
||||
return f"{prefix}/explore/cookbooks/{group_slug}/{item_id}"
|
||||
def explore_groups_group_slug_cookbooks_item_id(group_slug, item_id):
|
||||
"""`/api/explore/groups/{group_slug}/cookbooks/{item_id}`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/cookbooks/{item_id}"
|
||||
|
||||
|
||||
def explore_foods_group_slug(group_slug):
|
||||
"""`/api/explore/foods/{group_slug}`"""
|
||||
return f"{prefix}/explore/foods/{group_slug}"
|
||||
def explore_groups_group_slug_foods(group_slug):
|
||||
"""`/api/explore/groups/{group_slug}/foods`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/foods"
|
||||
|
||||
|
||||
def explore_foods_group_slug_item_id(group_slug, item_id):
|
||||
"""`/api/explore/foods/{group_slug}/{item_id}`"""
|
||||
return f"{prefix}/explore/foods/{group_slug}/{item_id}"
|
||||
def explore_groups_group_slug_foods_item_id(group_slug, item_id):
|
||||
"""`/api/explore/groups/{group_slug}/foods/{item_id}`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/foods/{item_id}"
|
||||
|
||||
|
||||
def explore_organizers_group_slug_categories(group_slug):
|
||||
"""`/api/explore/organizers/{group_slug}/categories`"""
|
||||
return f"{prefix}/explore/organizers/{group_slug}/categories"
|
||||
def explore_groups_group_slug_organizers_categories(group_slug):
|
||||
"""`/api/explore/groups/{group_slug}/organizers/categories`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/organizers/categories"
|
||||
|
||||
|
||||
def explore_organizers_group_slug_categories_item_id(group_slug, item_id):
|
||||
"""`/api/explore/organizers/{group_slug}/categories/{item_id}`"""
|
||||
return f"{prefix}/explore/organizers/{group_slug}/categories/{item_id}"
|
||||
def explore_groups_group_slug_organizers_categories_item_id(group_slug, item_id):
|
||||
"""`/api/explore/groups/{group_slug}/organizers/categories/{item_id}`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/organizers/categories/{item_id}"
|
||||
|
||||
|
||||
def explore_organizers_group_slug_tags(group_slug):
|
||||
"""`/api/explore/organizers/{group_slug}/tags`"""
|
||||
return f"{prefix}/explore/organizers/{group_slug}/tags"
|
||||
def explore_groups_group_slug_organizers_tags(group_slug):
|
||||
"""`/api/explore/groups/{group_slug}/organizers/tags`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/organizers/tags"
|
||||
|
||||
|
||||
def explore_organizers_group_slug_tags_item_id(group_slug, item_id):
|
||||
"""`/api/explore/organizers/{group_slug}/tags/{item_id}`"""
|
||||
return f"{prefix}/explore/organizers/{group_slug}/tags/{item_id}"
|
||||
def explore_groups_group_slug_organizers_tags_item_id(group_slug, item_id):
|
||||
"""`/api/explore/groups/{group_slug}/organizers/tags/{item_id}`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/organizers/tags/{item_id}"
|
||||
|
||||
|
||||
def explore_organizers_group_slug_tools(group_slug):
|
||||
"""`/api/explore/organizers/{group_slug}/tools`"""
|
||||
return f"{prefix}/explore/organizers/{group_slug}/tools"
|
||||
def explore_groups_group_slug_organizers_tools(group_slug):
|
||||
"""`/api/explore/groups/{group_slug}/organizers/tools`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/organizers/tools"
|
||||
|
||||
|
||||
def explore_organizers_group_slug_tools_item_id(group_slug, item_id):
|
||||
"""`/api/explore/organizers/{group_slug}/tools/{item_id}`"""
|
||||
return f"{prefix}/explore/organizers/{group_slug}/tools/{item_id}"
|
||||
def explore_groups_group_slug_organizers_tools_item_id(group_slug, item_id):
|
||||
"""`/api/explore/groups/{group_slug}/organizers/tools/{item_id}`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/organizers/tools/{item_id}"
|
||||
|
||||
|
||||
def explore_recipes_group_slug(group_slug):
|
||||
"""`/api/explore/recipes/{group_slug}`"""
|
||||
return f"{prefix}/explore/recipes/{group_slug}"
|
||||
def explore_groups_group_slug_recipes(group_slug):
|
||||
"""`/api/explore/groups/{group_slug}/recipes`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/recipes"
|
||||
|
||||
|
||||
def explore_recipes_group_slug_recipe_slug(group_slug, recipe_slug):
|
||||
"""`/api/explore/recipes/{group_slug}/{recipe_slug}`"""
|
||||
return f"{prefix}/explore/recipes/{group_slug}/{recipe_slug}"
|
||||
def explore_groups_group_slug_recipes_recipe_slug(group_slug, recipe_slug):
|
||||
"""`/api/explore/groups/{group_slug}/recipes/{recipe_slug}`"""
|
||||
return f"{prefix}/explore/groups/{group_slug}/recipes/{recipe_slug}"
|
||||
|
||||
|
||||
def foods_item_id(item_id):
|
||||
|
@ -285,79 +292,79 @@ def foods_item_id(item_id):
|
|||
return f"{prefix}/foods/{item_id}"
|
||||
|
||||
|
||||
def groups_cookbooks_item_id(item_id):
|
||||
"""`/api/groups/cookbooks/{item_id}`"""
|
||||
return f"{prefix}/groups/cookbooks/{item_id}"
|
||||
|
||||
|
||||
def groups_events_notifications_item_id(item_id):
|
||||
"""`/api/groups/events/notifications/{item_id}`"""
|
||||
return f"{prefix}/groups/events/notifications/{item_id}"
|
||||
|
||||
|
||||
def groups_events_notifications_item_id_test(item_id):
|
||||
"""`/api/groups/events/notifications/{item_id}/test`"""
|
||||
return f"{prefix}/groups/events/notifications/{item_id}/test"
|
||||
|
||||
|
||||
def groups_labels_item_id(item_id):
|
||||
"""`/api/groups/labels/{item_id}`"""
|
||||
return f"{prefix}/groups/labels/{item_id}"
|
||||
|
||||
|
||||
def groups_mealplans_item_id(item_id):
|
||||
"""`/api/groups/mealplans/{item_id}`"""
|
||||
return f"{prefix}/groups/mealplans/{item_id}"
|
||||
|
||||
|
||||
def groups_mealplans_rules_item_id(item_id):
|
||||
"""`/api/groups/mealplans/rules/{item_id}`"""
|
||||
return f"{prefix}/groups/mealplans/rules/{item_id}"
|
||||
|
||||
|
||||
def groups_recipe_actions_item_id(item_id):
|
||||
"""`/api/groups/recipe-actions/{item_id}`"""
|
||||
return f"{prefix}/groups/recipe-actions/{item_id}"
|
||||
|
||||
|
||||
def groups_reports_item_id(item_id):
|
||||
"""`/api/groups/reports/{item_id}`"""
|
||||
return f"{prefix}/groups/reports/{item_id}"
|
||||
|
||||
|
||||
def groups_shopping_items_item_id(item_id):
|
||||
"""`/api/groups/shopping/items/{item_id}`"""
|
||||
return f"{prefix}/groups/shopping/items/{item_id}"
|
||||
def households_cookbooks_item_id(item_id):
|
||||
"""`/api/households/cookbooks/{item_id}`"""
|
||||
return f"{prefix}/households/cookbooks/{item_id}"
|
||||
|
||||
|
||||
def groups_shopping_lists_item_id(item_id):
|
||||
"""`/api/groups/shopping/lists/{item_id}`"""
|
||||
return f"{prefix}/groups/shopping/lists/{item_id}"
|
||||
def households_events_notifications_item_id(item_id):
|
||||
"""`/api/households/events/notifications/{item_id}`"""
|
||||
return f"{prefix}/households/events/notifications/{item_id}"
|
||||
|
||||
|
||||
def groups_shopping_lists_item_id_label_settings(item_id):
|
||||
"""`/api/groups/shopping/lists/{item_id}/label-settings`"""
|
||||
return f"{prefix}/groups/shopping/lists/{item_id}/label-settings"
|
||||
def households_events_notifications_item_id_test(item_id):
|
||||
"""`/api/households/events/notifications/{item_id}/test`"""
|
||||
return f"{prefix}/households/events/notifications/{item_id}/test"
|
||||
|
||||
|
||||
def groups_shopping_lists_item_id_recipe_recipe_id(item_id, recipe_id):
|
||||
"""`/api/groups/shopping/lists/{item_id}/recipe/{recipe_id}`"""
|
||||
return f"{prefix}/groups/shopping/lists/{item_id}/recipe/{recipe_id}"
|
||||
def households_mealplans_item_id(item_id):
|
||||
"""`/api/households/mealplans/{item_id}`"""
|
||||
return f"{prefix}/households/mealplans/{item_id}"
|
||||
|
||||
|
||||
def groups_shopping_lists_item_id_recipe_recipe_id_delete(item_id, recipe_id):
|
||||
"""`/api/groups/shopping/lists/{item_id}/recipe/{recipe_id}/delete`"""
|
||||
return f"{prefix}/groups/shopping/lists/{item_id}/recipe/{recipe_id}/delete"
|
||||
def households_mealplans_rules_item_id(item_id):
|
||||
"""`/api/households/mealplans/rules/{item_id}`"""
|
||||
return f"{prefix}/households/mealplans/rules/{item_id}"
|
||||
|
||||
|
||||
def groups_webhooks_item_id(item_id):
|
||||
"""`/api/groups/webhooks/{item_id}`"""
|
||||
return f"{prefix}/groups/webhooks/{item_id}"
|
||||
def households_recipe_actions_item_id(item_id):
|
||||
"""`/api/households/recipe-actions/{item_id}`"""
|
||||
return f"{prefix}/households/recipe-actions/{item_id}"
|
||||
|
||||
|
||||
def groups_webhooks_item_id_test(item_id):
|
||||
"""`/api/groups/webhooks/{item_id}/test`"""
|
||||
return f"{prefix}/groups/webhooks/{item_id}/test"
|
||||
def households_shopping_items_item_id(item_id):
|
||||
"""`/api/households/shopping/items/{item_id}`"""
|
||||
return f"{prefix}/households/shopping/items/{item_id}"
|
||||
|
||||
|
||||
def households_shopping_lists_item_id(item_id):
|
||||
"""`/api/households/shopping/lists/{item_id}`"""
|
||||
return f"{prefix}/households/shopping/lists/{item_id}"
|
||||
|
||||
|
||||
def households_shopping_lists_item_id_label_settings(item_id):
|
||||
"""`/api/households/shopping/lists/{item_id}/label-settings`"""
|
||||
return f"{prefix}/households/shopping/lists/{item_id}/label-settings"
|
||||
|
||||
|
||||
def households_shopping_lists_item_id_recipe_recipe_id(item_id, recipe_id):
|
||||
"""`/api/households/shopping/lists/{item_id}/recipe/{recipe_id}`"""
|
||||
return f"{prefix}/households/shopping/lists/{item_id}/recipe/{recipe_id}"
|
||||
|
||||
|
||||
def households_shopping_lists_item_id_recipe_recipe_id_delete(item_id, recipe_id):
|
||||
"""`/api/households/shopping/lists/{item_id}/recipe/{recipe_id}/delete`"""
|
||||
return f"{prefix}/households/shopping/lists/{item_id}/recipe/{recipe_id}/delete"
|
||||
|
||||
|
||||
def households_webhooks_item_id(item_id):
|
||||
"""`/api/households/webhooks/{item_id}`"""
|
||||
return f"{prefix}/households/webhooks/{item_id}"
|
||||
|
||||
|
||||
def households_webhooks_item_id_test(item_id):
|
||||
"""`/api/households/webhooks/{item_id}/test`"""
|
||||
return f"{prefix}/households/webhooks/{item_id}/test"
|
||||
|
||||
|
||||
def media_recipes_recipe_id_assets_file_name(recipe_id, file_name):
|
||||
|
|
|
@ -23,6 +23,7 @@ def random_int(min=-4294967296, max=4294967296) -> int:
|
|||
def user_registration_factory(advanced=None, private=None) -> CreateUserRegistration:
|
||||
return CreateUserRegistration(
|
||||
group=random_string(),
|
||||
household=random_string(),
|
||||
email=random_email(),
|
||||
username=random_string(),
|
||||
full_name=random_string(),
|
||||
|
|
|
@ -3,6 +3,7 @@ from typing import Any
|
|||
from uuid import UUID
|
||||
|
||||
from mealie.db.models.users.users import AuthMethod
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -12,9 +13,15 @@ class TestUser:
|
|||
username: str
|
||||
password: str
|
||||
_group_id: UUID
|
||||
_household_id: UUID
|
||||
token: Any
|
||||
auth_method = AuthMethod.MEALIE
|
||||
repos: AllRepositories
|
||||
|
||||
@property
|
||||
def group_id(self) -> str:
|
||||
return str(self._group_id)
|
||||
|
||||
@property
|
||||
def household_id(self) -> str:
|
||||
return str(self._household_id)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue