mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 02:03:35 -04:00 
			
		
		
		
	* fix #1144 * fix type checks * refactor test routes package * fix #1208 * unify test routes into module
This commit is contained in:
		| @@ -1,9 +1,9 @@ | |||||||
| preserve_hierarchy: false | preserve_hierarchy: false | ||||||
| files: | files: | ||||||
|   - source: /frontend/src/locales/messages/en-US.json |   - source: /frontend/lang/messages/en-US.json | ||||||
|     translation: /frontend/src/locales/messages/%locale%.json |     translation: /frontend/lang/messages/%locale%.json | ||||||
|   - source: /frontend/src/locales/dateTimeFormats/en-US.json |   - source: /frontend/lang/dateTimeFormats/en-US.json | ||||||
|     translation: /frontend/src/locales/dateTimeFormats/%locale%.json |     translation: /frontend/lang/dateTimeFormats/%locale%.json | ||||||
|  |  | ||||||
|   # Backend General Messages |   # Backend General Messages | ||||||
|   - source: /mealie/lang/messages/en-US.json |   - source: /mealie/lang/messages/en-US.json | ||||||
|   | |||||||
| @@ -149,8 +149,8 @@ class RepositoryGeneric(Generic[T, D]): | |||||||
|         if match_key is None: |         if match_key is None: | ||||||
|             match_key = self.primary_key |             match_key = self.primary_key | ||||||
|  |  | ||||||
|         filter = self._filter_builder(**{match_key: match_value}) |         fltr = self._filter_builder(**{match_key: match_value}) | ||||||
|         return self.session.query(self.sql_model).filter_by(**filter).one() |         return self.session.query(self.sql_model).filter_by(**fltr).one() | ||||||
|  |  | ||||||
|     def get_one(self, value: str | int | UUID4, key: str = None, any_case=False, override_schema=None) -> T | None: |     def get_one(self, value: str | int | UUID4, key: str = None, any_case=False, override_schema=None) -> T | None: | ||||||
|         key = key or self.primary_key |         key = key or self.primary_key | ||||||
| @@ -210,7 +210,7 @@ class RepositoryGeneric(Generic[T, D]): | |||||||
|  |  | ||||||
|         return [eff_schema.from_orm(x) for x in result] |         return [eff_schema.from_orm(x) for x in result] | ||||||
|  |  | ||||||
|     def create(self, document: T | BaseModel) -> T: |     def create(self, document: T | BaseModel | dict) -> T: | ||||||
|         """Creates a new database entry for the given SQL Alchemy Model. |         """Creates a new database entry for the given SQL Alchemy Model. | ||||||
|  |  | ||||||
|         Args: |         Args: | ||||||
| @@ -266,8 +266,10 @@ class RepositoryGeneric(Generic[T, D]): | |||||||
|  |  | ||||||
|         return self.update(match_value, entry_as_dict) |         return self.update(match_value, entry_as_dict) | ||||||
|  |  | ||||||
|     def delete(self, primary_key_value) -> D: |     def delete(self, value, match_key: str | None = None) -> T: | ||||||
|         result = self.session.query(self.sql_model).filter_by(**{self.primary_key: primary_key_value}).one() |         match_key = match_key or self.primary_key | ||||||
|  |  | ||||||
|  |         result = self.session.query(self.sql_model).filter_by(**{match_key: value}).one() | ||||||
|         results_as_model = self.schema.from_orm(result) |         results_as_model = self.schema.from_orm(result) | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
| @@ -313,7 +315,7 @@ class RepositoryGeneric(Generic[T, D]): | |||||||
|                 for x in self.session.query(self.sql_model).filter(attribute_name == attr_match).all()  # noqa: 711 |                 for x in self.session.query(self.sql_model).filter(attribute_name == attr_match).all()  # noqa: 711 | ||||||
|             ] |             ] | ||||||
|  |  | ||||||
|     def create_many(self, documents: list[T]) -> list[T]: |     def create_many(self, documents: list[T | dict]) -> list[T]: | ||||||
|         new_documents = [] |         new_documents = [] | ||||||
|         for document in documents: |         for document in documents: | ||||||
|             document = document if isinstance(document, dict) else document.dict() |             document = document if isinstance(document, dict) else document.dict() | ||||||
|   | |||||||
| @@ -2,6 +2,8 @@ import random | |||||||
| import shutil | import shutil | ||||||
| from typing import Optional | from typing import Optional | ||||||
|  |  | ||||||
|  | from pydantic import UUID4 | ||||||
|  |  | ||||||
| from mealie.assets import users as users_assets | from mealie.assets import users as users_assets | ||||||
| from mealie.schema.user.user import PrivateUser, User | from mealie.schema.user.user import PrivateUser, User | ||||||
|  |  | ||||||
| @@ -30,11 +32,11 @@ class RepositoryUsers(RepositoryGeneric[PrivateUser, User]): | |||||||
|  |  | ||||||
|         return new_user |         return new_user | ||||||
|  |  | ||||||
|     def delete(self, id: str) -> User: |     def delete(self, value: str | UUID4, match_key: str | None = None) -> User: | ||||||
|         entry = super().delete(id) |         entry = super().delete(value, match_key) | ||||||
|         # Delete the user's directory |         # Delete the user's directory | ||||||
|         shutil.rmtree(PrivateUser.get_directory(id)) |         shutil.rmtree(PrivateUser.get_directory(value)) | ||||||
|         return entry |         return entry  # type: ignore | ||||||
|  |  | ||||||
|     def get_by_username(self, username: str, limit=1) -> Optional[User]: |     def get_by_username(self, username: str, limit=1) -> Optional[User]: | ||||||
|         dbuser = self.session.query(User).filter(User.username == username).one_or_none() |         dbuser = self.session.query(User).filter(User.username == username).one_or_none() | ||||||
|   | |||||||
| @@ -128,7 +128,7 @@ class PrivateUser(UserOut): | |||||||
|         orm_mode = True |         orm_mode = True | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def get_directory(user_id: UUID4) -> Path: |     def get_directory(user_id: UUID4 | str) -> Path: | ||||||
|         user_dir = get_app_dirs().USER_DIR / str(user_id) |         user_dir = get_app_dirs().USER_DIR / str(user_id) | ||||||
|         user_dir.mkdir(parents=True, exist_ok=True) |         user_dir.mkdir(parents=True, exist_ok=True) | ||||||
|         return user_dir |         return user_dir | ||||||
|   | |||||||
| @@ -178,7 +178,7 @@ class RecipeService(BaseService): | |||||||
|     def delete_one(self, slug) -> Recipe: |     def delete_one(self, slug) -> Recipe: | ||||||
|         recipe = self._get_recipe(slug) |         recipe = self._get_recipe(slug) | ||||||
|         self.can_update(recipe) |         self.can_update(recipe) | ||||||
|         data = self.repos.recipes.delete(slug) |         data = self.repos.recipes.delete(recipe.id, "id") | ||||||
|         self.delete_assets(data) |         self.delete_assets(data) | ||||||
|         return data |         return data | ||||||
|  |  | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ def generate_create_data() -> dict: | |||||||
| def test_init_superuser(api_client: TestClient, admin_user: TestUser): | def test_init_superuser(api_client: TestClient, admin_user: TestUser): | ||||||
|     settings = get_app_settings() |     settings = get_app_settings() | ||||||
|  |  | ||||||
|     response = api_client.get(routes.RoutesAdminUsers.item(admin_user.user_id), headers=admin_user.token) |     response = api_client.get(routes.admin.AdminUsers.item(admin_user.user_id), headers=admin_user.token) | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|  |  | ||||||
|     admin_data = response.json() |     admin_data = response.json() | ||||||
| @@ -41,13 +41,13 @@ def test_init_superuser(api_client: TestClient, admin_user: TestUser): | |||||||
|  |  | ||||||
| def test_create_user(api_client: TestClient, api_routes: AppRoutes, admin_token): | def test_create_user(api_client: TestClient, api_routes: AppRoutes, admin_token): | ||||||
|     create_data = generate_create_data() |     create_data = generate_create_data() | ||||||
|     response = api_client.post(routes.RoutesAdminUsers.base, json=create_data, headers=admin_token) |     response = api_client.post(routes.admin.AdminUsers.base, json=create_data, headers=admin_token) | ||||||
|     assert response.status_code == 201 |     assert response.status_code == 201 | ||||||
|  |  | ||||||
|     form_data = {"username": create_data["email"], "password": create_data["password"]} |     form_data = {"username": create_data["email"], "password": create_data["password"]} | ||||||
|     header = utils.login(form_data=form_data, api_client=api_client, api_routes=api_routes) |     header = utils.login(form_data=form_data, api_client=api_client, api_routes=api_routes) | ||||||
|  |  | ||||||
|     response = api_client.get(routes.RoutesUsers.self, headers=header) |     response = api_client.get(routes.user.Users.self, headers=header) | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|  |  | ||||||
|     user_data = response.json() |     user_data = response.json() | ||||||
| @@ -60,14 +60,14 @@ def test_create_user(api_client: TestClient, api_routes: AppRoutes, admin_token) | |||||||
|  |  | ||||||
| def test_create_user_as_non_admin(api_client: TestClient, user_token): | def test_create_user_as_non_admin(api_client: TestClient, user_token): | ||||||
|     create_data = generate_create_data() |     create_data = generate_create_data() | ||||||
|     response = api_client.post(routes.RoutesAdminUsers.base, json=create_data, headers=user_token) |     response = api_client.post(routes.admin.AdminUsers.base, json=create_data, headers=user_token) | ||||||
|     assert response.status_code == 403 |     assert response.status_code == 403 | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_update_user(api_client: TestClient, admin_user: TestUser): | def test_update_user(api_client: TestClient, admin_user: TestUser): | ||||||
|     # Create a new user |     # Create a new user | ||||||
|     create_data = generate_create_data() |     create_data = generate_create_data() | ||||||
|     response = api_client.post(routes.RoutesAdminUsers.base, json=create_data, headers=admin_user.token) |     response = api_client.post(routes.admin.AdminUsers.base, json=create_data, headers=admin_user.token) | ||||||
|     assert response.status_code == 201 |     assert response.status_code == 201 | ||||||
|     update_data = response.json() |     update_data = response.json() | ||||||
|  |  | ||||||
| @@ -76,7 +76,7 @@ def test_update_user(api_client: TestClient, admin_user: TestUser): | |||||||
|     update_data["email"] = random_email() |     update_data["email"] = random_email() | ||||||
|  |  | ||||||
|     response = api_client.put( |     response = api_client.put( | ||||||
|         routes.RoutesAdminUsers.item(update_data["id"]), headers=admin_user.token, json=update_data |         routes.admin.AdminUsers.item(update_data["id"]), headers=admin_user.token, json=update_data | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
| @@ -93,21 +93,21 @@ def test_update_other_user_as_not_admin(api_client: TestClient, unique_user: Tes | |||||||
|         "admin": True, |         "admin": True, | ||||||
|     } |     } | ||||||
|     response = api_client.put( |     response = api_client.put( | ||||||
|         routes.RoutesAdminUsers.item(g2_user.user_id), headers=unique_user.token, json=update_data |         routes.admin.AdminUsers.item(g2_user.user_id), headers=unique_user.token, json=update_data | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     assert response.status_code == 403 |     assert response.status_code == 403 | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_self_demote_admin(api_client: TestClient, admin_user: TestUser): | def test_self_demote_admin(api_client: TestClient, admin_user: TestUser): | ||||||
|     response = api_client.get(routes.RoutesUsers.self, headers=admin_user.token) |     response = api_client.get(routes.user.Users.self, headers=admin_user.token) | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|  |  | ||||||
|     user_data = response.json() |     user_data = response.json() | ||||||
|     user_data["admin"] = False |     user_data["admin"] = False | ||||||
|  |  | ||||||
|     response = api_client.put( |     response = api_client.put( | ||||||
|         routes.RoutesAdminUsers.item(admin_user.user_id), headers=admin_user.token, json=user_data |         routes.admin.AdminUsers.item(admin_user.user_id), headers=admin_user.token, json=user_data | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     assert response.status_code == 403 |     assert response.status_code == 403 | ||||||
| @@ -122,12 +122,12 @@ def test_self_promote_admin(api_client: TestClient, unique_user: TestUser): | |||||||
|         "admin": True, |         "admin": True, | ||||||
|     } |     } | ||||||
|     response = api_client.put( |     response = api_client.put( | ||||||
|         routes.RoutesAdminUsers.item(unique_user.user_id), headers=unique_user.token, json=update_data |         routes.admin.AdminUsers.item(unique_user.user_id), headers=unique_user.token, json=update_data | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     assert response.status_code == 403 |     assert response.status_code == 403 | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_delete_user(api_client: TestClient, admin_token, unique_user: TestUser): | def test_delete_user(api_client: TestClient, admin_token, unique_user: TestUser): | ||||||
|     response = api_client.delete(routes.RoutesAdminUsers.item(unique_user.user_id), headers=admin_token) |     response = api_client.delete(routes.admin.AdminUsers.item(unique_user.user_id), headers=admin_token) | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|   | |||||||
| @@ -14,9 +14,9 @@ test_ids = [ | |||||||
| ] | ] | ||||||
|  |  | ||||||
| organizer_routes = [ | organizer_routes = [ | ||||||
|     (routes.RoutesCategory), |     (routes.organizers.Categories), | ||||||
|     (routes.RoutesTags), |     (routes.organizers.Tags), | ||||||
|     (routes.RoutesTools), |     (routes.organizers.Tools), | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -43,9 +43,9 @@ def test_organizers_create_read(api_client: TestClient, unique_user: TestUser, r | |||||||
|  |  | ||||||
|  |  | ||||||
| update_data = [ | update_data = [ | ||||||
|     (routes.RoutesCategory, {"name": random_string(10)}), |     (routes.organizers.Categories, {"name": random_string(10)}), | ||||||
|     (routes.RoutesTags, {"name": random_string(10)}), |     (routes.organizers.Tags, {"name": random_string(10)}), | ||||||
|     (routes.RoutesTools, {"name": random_string(10), "onHand": random_bool()}), |     (routes.organizers.Tools, {"name": random_string(10), "onHand": random_bool()}), | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -101,9 +101,9 @@ def test_organizer_delete( | |||||||
|  |  | ||||||
|  |  | ||||||
| association_data = [ | association_data = [ | ||||||
|     (routes.RoutesCategory, recipe_keys.recipe_category), |     (routes.organizers.Categories, recipe_keys.recipe_category), | ||||||
|     (routes.RoutesTags, "tags"), |     (routes.organizers.Tags, "tags"), | ||||||
|     (routes.RoutesTools, "tools"), |     (routes.organizers.Tools, "tools"), | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -123,28 +123,28 @@ def test_organizer_association( | |||||||
|  |  | ||||||
|     # Setup Recipe |     # Setup Recipe | ||||||
|     recipe_data = {"name": random_string(10)} |     recipe_data = {"name": random_string(10)} | ||||||
|     response = api_client.post(routes.RoutesRecipe.base, json=recipe_data, headers=unique_user.token) |     response = api_client.post(routes.recipes.Recipe.base, json=recipe_data, headers=unique_user.token) | ||||||
|     slug = response.json() |     slug = response.json() | ||||||
|     assert response.status_code == 201 |     assert response.status_code == 201 | ||||||
|  |  | ||||||
|     # Get Recipe Data |     # Get Recipe Data | ||||||
|     response = api_client.get(routes.RoutesRecipe.item(slug), headers=unique_user.token) |     response = api_client.get(routes.recipes.Recipe.item(slug), headers=unique_user.token) | ||||||
|     as_json = response.json() |     as_json = response.json() | ||||||
|     as_json[recipe_key] = [ |     as_json[recipe_key] = [ | ||||||
|         {"id": item["id"], "group_id": unique_user.group_id, "name": item["name"], "slug": item["slug"]} |         {"id": item["id"], "group_id": unique_user.group_id, "name": item["name"], "slug": item["slug"]} | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     # Update Recipe |     # Update Recipe | ||||||
|     response = api_client.put(routes.RoutesRecipe.item(slug), json=as_json, headers=unique_user.token) |     response = api_client.put(routes.recipes.Recipe.item(slug), json=as_json, headers=unique_user.token) | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|  |  | ||||||
|     # Get Recipe Data |     # Get Recipe Data | ||||||
|     response = api_client.get(routes.RoutesRecipe.item(slug), headers=unique_user.token) |     response = api_client.get(routes.recipes.Recipe.item(slug), headers=unique_user.token) | ||||||
|     as_json = response.json() |     as_json = response.json() | ||||||
|     assert as_json[recipe_key][0]["slug"] == item["slug"] |     assert as_json[recipe_key][0]["slug"] == item["slug"] | ||||||
|  |  | ||||||
|     # Cleanup |     # Cleanup | ||||||
|     response = api_client.delete(routes.RoutesRecipe.item(slug), headers=unique_user.token) |     response = api_client.delete(routes.recipes.Recipe.item(slug), headers=unique_user.token) | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|  |  | ||||||
|     response = api_client.delete(route.item(item["id"]), headers=unique_user.token) |     response = api_client.delete(route.item(item["id"]), headers=unique_user.token) | ||||||
| @@ -155,7 +155,7 @@ def test_organizer_association( | |||||||
| def test_organizer_get_by_slug( | def test_organizer_get_by_slug( | ||||||
|     api_client: TestClient, |     api_client: TestClient, | ||||||
|     unique_user: TestUser, |     unique_user: TestUser, | ||||||
|     route: routes.RoutesOrganizerBase, |     route: routes.organizers.RoutesOrganizerBase, | ||||||
|     recipe_key: str, |     recipe_key: str, | ||||||
| ): | ): | ||||||
|     # Create Organizer |     # Create Organizer | ||||||
| @@ -170,20 +170,20 @@ def test_organizer_get_by_slug( | |||||||
|     for _ in range(10): |     for _ in range(10): | ||||||
|         # Setup Recipe |         # Setup Recipe | ||||||
|         recipe_data = {"name": random_string(10)} |         recipe_data = {"name": random_string(10)} | ||||||
|         response = api_client.post(routes.RoutesRecipe.base, json=recipe_data, headers=unique_user.token) |         response = api_client.post(routes.recipes.Recipe.base, json=recipe_data, headers=unique_user.token) | ||||||
|         assert response.status_code == 201 |         assert response.status_code == 201 | ||||||
|         slug = response.json() |         slug = response.json() | ||||||
|         recipe_slugs.append(slug) |         recipe_slugs.append(slug) | ||||||
|  |  | ||||||
|     # Associate 10 Recipes to Organizer |     # Associate 10 Recipes to Organizer | ||||||
|     for slug in recipe_slugs: |     for slug in recipe_slugs: | ||||||
|         response = api_client.get(routes.RoutesRecipe.item(slug), headers=unique_user.token) |         response = api_client.get(routes.recipes.Recipe.item(slug), headers=unique_user.token) | ||||||
|         as_json = response.json() |         as_json = response.json() | ||||||
|         as_json[recipe_key] = [ |         as_json[recipe_key] = [ | ||||||
|             {"id": item["id"], "group_id": unique_user.group_id, "name": item["name"], "slug": item["slug"]} |             {"id": item["id"], "group_id": unique_user.group_id, "name": item["name"], "slug": item["slug"]} | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
|         response = api_client.put(routes.RoutesRecipe.item(slug), json=as_json, headers=unique_user.token) |         response = api_client.put(routes.recipes.Recipe.item(slug), json=as_json, headers=unique_user.token) | ||||||
|         assert response.status_code == 200 |         assert response.status_code == 200 | ||||||
|  |  | ||||||
|     # Get Organizer by Slug |     # Get Organizer by Slug | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| from fastapi.testclient import TestClient | from fastapi.testclient import TestClient | ||||||
|  |  | ||||||
| from mealie.repos.repository_factory import AllRepositories | from mealie.repos.repository_factory import AllRepositories | ||||||
|  | from tests.utils import routes | ||||||
| from tests.utils.fixture_schemas import TestUser | from tests.utils.fixture_schemas import TestUser | ||||||
| from tests.utils.routes import RoutesSeeders |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_seed_invalid_locale(api_client: TestClient, unique_user: TestUser): | def test_seed_invalid_locale(api_client: TestClient, unique_user: TestUser): | ||||||
|     for route in [RoutesSeeders.foods, RoutesSeeders.labels, RoutesSeeders.units]: |     for route in [routes.seeders.Seeders.foods, routes.seeders.Seeders.labels, routes.seeders.Seeders.units]: | ||||||
|         resp = api_client.post(route, json={"locale": "invalid"}, headers=unique_user.token) |         resp = api_client.post(route, json={"locale": "invalid"}, headers=unique_user.token) | ||||||
|         assert resp.status_code == 422 |         assert resp.status_code == 422 | ||||||
|  |  | ||||||
| @@ -18,7 +18,7 @@ def test_seed_foods(api_client: TestClient, unique_user: TestUser, database: All | |||||||
|     foods = database.ingredient_foods.by_group(unique_user.group_id).get_all() |     foods = database.ingredient_foods.by_group(unique_user.group_id).get_all() | ||||||
|     assert len(foods) == 0 |     assert len(foods) == 0 | ||||||
|  |  | ||||||
|     resp = api_client.post(RoutesSeeders.foods, json={"locale": "en-US"}, headers=unique_user.token) |     resp = api_client.post(routes.seeders.Seeders.foods, json={"locale": "en-US"}, headers=unique_user.token) | ||||||
|     assert resp.status_code == 200 |     assert resp.status_code == 200 | ||||||
|  |  | ||||||
|     # Check that the foods was created |     # Check that the foods was created | ||||||
| @@ -33,7 +33,7 @@ def test_seed_units(api_client: TestClient, unique_user: TestUser, database: All | |||||||
|     units = database.ingredient_units.by_group(unique_user.group_id).get_all() |     units = database.ingredient_units.by_group(unique_user.group_id).get_all() | ||||||
|     assert len(units) == 0 |     assert len(units) == 0 | ||||||
|  |  | ||||||
|     resp = api_client.post(RoutesSeeders.units, json={"locale": "en-US"}, headers=unique_user.token) |     resp = api_client.post(routes.seeders.Seeders.units, json={"locale": "en-US"}, headers=unique_user.token) | ||||||
|     assert resp.status_code == 200 |     assert resp.status_code == 200 | ||||||
|  |  | ||||||
|     # Check that the foods was created |     # Check that the foods was created | ||||||
| @@ -48,7 +48,7 @@ def test_seed_labels(api_client: TestClient, unique_user: TestUser, database: Al | |||||||
|     labels = database.group_multi_purpose_labels.by_group(unique_user.group_id).get_all() |     labels = database.group_multi_purpose_labels.by_group(unique_user.group_id).get_all() | ||||||
|     assert len(labels) == 0 |     assert len(labels) == 0 | ||||||
|  |  | ||||||
|     resp = api_client.post(RoutesSeeders.labels, json={"locale": "en-US"}, headers=unique_user.token) |     resp = api_client.post(routes.seeders.Seeders.labels, json={"locale": "en-US"}, headers=unique_user.token) | ||||||
|     assert resp.status_code == 200 |     assert resp.status_code == 200 | ||||||
|  |  | ||||||
|     # Check that the foods was created |     # Check that the foods was created | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ from mealie.schema.recipe.recipe import RecipeCategory | |||||||
| from mealie.services.recipe.recipe_data_service import RecipeDataService | from mealie.services.recipe.recipe_data_service import RecipeDataService | ||||||
| from mealie.services.scraper.scraper_strategies import RecipeScraperOpenGraph | from mealie.services.scraper.scraper_strategies import RecipeScraperOpenGraph | ||||||
| from tests import data, utils | from tests import data, utils | ||||||
|  | from tests.utils import routes | ||||||
| from tests.utils.app_routes import AppRoutes | from tests.utils.app_routes import AppRoutes | ||||||
| from tests.utils.factories import random_string | from tests.utils.factories import random_string | ||||||
| from tests.utils.fixture_schemas import TestUser | from tests.utils.fixture_schemas import TestUser | ||||||
| @@ -157,12 +158,11 @@ def test_create_by_url_with_tags( | |||||||
| @pytest.mark.parametrize("recipe_data", recipe_test_data) | @pytest.mark.parametrize("recipe_data", recipe_test_data) | ||||||
| def test_read_update( | def test_read_update( | ||||||
|     api_client: TestClient, |     api_client: TestClient, | ||||||
|     api_routes: AppRoutes, |  | ||||||
|     recipe_data: RecipeSiteTestCase, |     recipe_data: RecipeSiteTestCase, | ||||||
|     unique_user: TestUser, |     unique_user: TestUser, | ||||||
|     recipe_categories: list[RecipeCategory], |     recipe_categories: list[RecipeCategory], | ||||||
| ): | ): | ||||||
|     recipe_url = api_routes.recipes_recipe_slug(recipe_data.expected_slug) |     recipe_url = routes.recipes.Recipe.item(recipe_data.expected_slug) | ||||||
|     response = api_client.get(recipe_url, headers=unique_user.token) |     response = api_client.get(recipe_url, headers=unique_user.token) | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|  |  | ||||||
| @@ -196,8 +196,8 @@ def test_read_update( | |||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.mark.parametrize("recipe_data", recipe_test_data) | @pytest.mark.parametrize("recipe_data", recipe_test_data) | ||||||
| def test_rename(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeSiteTestCase, unique_user: TestUser): | def test_rename(api_client: TestClient, recipe_data: RecipeSiteTestCase, unique_user: TestUser): | ||||||
|     recipe_url = api_routes.recipes_recipe_slug(recipe_data.expected_slug) |     recipe_url = routes.recipes.Recipe.item(recipe_data.expected_slug) | ||||||
|     response = api_client.get(recipe_url, headers=unique_user.token) |     response = api_client.get(recipe_url, headers=unique_user.token) | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|  |  | ||||||
| @@ -215,44 +215,66 @@ def test_rename(api_client: TestClient, api_routes: AppRoutes, recipe_data: Reci | |||||||
|  |  | ||||||
|  |  | ||||||
| @pytest.mark.parametrize("recipe_data", recipe_test_data) | @pytest.mark.parametrize("recipe_data", recipe_test_data) | ||||||
| def test_delete(api_client: TestClient, api_routes: AppRoutes, recipe_data: RecipeSiteTestCase, unique_user: TestUser): | def test_delete(api_client: TestClient, recipe_data: RecipeSiteTestCase, unique_user: TestUser): | ||||||
|     recipe_url = api_routes.recipes_recipe_slug(recipe_data.expected_slug) |     response = api_client.delete(routes.recipes.Recipe.item(recipe_data.expected_slug), headers=unique_user.token) | ||||||
|     response = api_client.delete(recipe_url, headers=unique_user.token) |  | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_recipe_crud_404(api_client: TestClient, api_routes: AppRoutes, unique_user: TestUser): | def test_recipe_crud_404(api_client: TestClient, api_routes: AppRoutes, unique_user: TestUser): | ||||||
|     response = api_client.put(api_routes.recipes_recipe_slug("test"), json={"test": "stest"}, headers=unique_user.token) |     response = api_client.put(routes.recipes.Recipe.item("test"), json={"test": "stest"}, headers=unique_user.token) | ||||||
|     assert response.status_code == 404 |     assert response.status_code == 404 | ||||||
|  |  | ||||||
|     response = api_client.get(api_routes.recipes_recipe_slug("test"), headers=unique_user.token) |     response = api_client.get(routes.recipes.Recipe.item("test"), headers=unique_user.token) | ||||||
|     assert response.status_code == 404 |     assert response.status_code == 404 | ||||||
|  |  | ||||||
|     response = api_client.delete(api_routes.recipes_recipe_slug("test"), headers=unique_user.token) |     response = api_client.delete(routes.recipes.Recipe.item("test"), headers=unique_user.token) | ||||||
|     assert response.status_code == 404 |     assert response.status_code == 404 | ||||||
|  |  | ||||||
|     response = api_client.patch(api_routes.recipes_create_url, json={"test": "stest"}, headers=unique_user.token) |     response = api_client.patch(api_routes.recipes_create_url, json={"test": "stest"}, headers=unique_user.token) | ||||||
|     assert response.status_code == 404 |     assert response.status_code == 404 | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_create_recipe_same_name(api_client: TestClient, api_routes: AppRoutes, unique_user: TestUser): | def test_create_recipe_same_name(api_client: TestClient, unique_user: TestUser): | ||||||
|     slug = random_string(10) |     slug = random_string(10) | ||||||
|  |  | ||||||
|     response = api_client.post("/api/recipes", json={"name": slug}, headers=unique_user.token) |     response = api_client.post(routes.recipes.Recipe.base, json={"name": slug}, headers=unique_user.token) | ||||||
|     assert response.status_code == 201 |     assert response.status_code == 201 | ||||||
|     assert json.loads(response.text) == slug |     assert json.loads(response.text) == slug | ||||||
|  |  | ||||||
|     response = api_client.post("/api/recipes", json={"name": slug}, headers=unique_user.token) |     response = api_client.post(routes.recipes.Recipe.base, json={"name": slug}, headers=unique_user.token) | ||||||
|     assert response.status_code == 201 |     assert response.status_code == 201 | ||||||
|     assert json.loads(response.text) == f"{slug}-1" |     assert json.loads(response.text) == f"{slug}-1" | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_create_recipe_too_many_time(api_client: TestClient, api_routes: AppRoutes, unique_user: TestUser): | def test_create_recipe_too_many_time(api_client: TestClient, unique_user: TestUser): | ||||||
|     slug = random_string(10) |     slug = random_string(10) | ||||||
|  |  | ||||||
|     for _ in range(10): |     for _ in range(10): | ||||||
|         response = api_client.post("/api/recipes", json={"name": slug}, headers=unique_user.token) |         response = api_client.post(routes.recipes.Recipe.base, json={"name": slug}, headers=unique_user.token) | ||||||
|         assert response.status_code == 201 |         assert response.status_code == 201 | ||||||
|  |  | ||||||
|     response = api_client.post("/api/recipes", json={"name": slug}, headers=unique_user.token) |     response = api_client.post(routes.recipes.Recipe.base, json={"name": slug}, headers=unique_user.token) | ||||||
|     assert response.status_code == 400 |     assert response.status_code == 400 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_delete_recipe_same_name(api_client: TestClient, unique_user: utils.TestUser, g2_user: utils.TestUser): | ||||||
|  |     slug = random_string(10) | ||||||
|  |  | ||||||
|  |     # Create recipe for both users | ||||||
|  |     for user in (unique_user, g2_user): | ||||||
|  |         response = api_client.post(routes.recipes.Recipe.base, json={"name": slug}, headers=user.token) | ||||||
|  |         assert response.status_code == 201 | ||||||
|  |         assert json.loads(response.text) == slug | ||||||
|  |  | ||||||
|  |     # Delete recipe for user 1 | ||||||
|  |     response = api_client.delete(routes.recipes.Recipe.item(slug), headers=unique_user.token) | ||||||
|  |     assert response.status_code == 200 | ||||||
|  |  | ||||||
|  |     # Ensure recipe for user 2 still exists | ||||||
|  |     response = api_client.get(routes.recipes.Recipe.item(slug), headers=g2_user.token) | ||||||
|  |     assert response.status_code == 200 | ||||||
|  |  | ||||||
|  |     # Make sure recipe for user 1 doesn't exist | ||||||
|  |     response = api_client.get(routes.recipes.Recipe.item(slug), headers=unique_user.token) | ||||||
|  |     response = api_client.get(routes.recipes.Recipe.item(slug), headers=unique_user.token) | ||||||
|  |     assert response.status_code == 404 | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ def test_associate_ingredient_with_step(api_client: TestClient, unique_user: Tes | |||||||
|         steps[idx] = [str(ingredient.reference_id) for ingredient in ingredients] |         steps[idx] = [str(ingredient.reference_id) for ingredient in ingredients] | ||||||
|  |  | ||||||
|     response = api_client.put( |     response = api_client.put( | ||||||
|         routes.RoutesRecipe.item(recipe.slug), |         routes.recipes.Recipe.item(recipe.slug), | ||||||
|         json=jsonify(recipe.dict()), |         json=jsonify(recipe.dict()), | ||||||
|         headers=unique_user.token, |         headers=unique_user.token, | ||||||
|     ) |     ) | ||||||
| @@ -35,14 +35,14 @@ def test_associate_ingredient_with_step(api_client: TestClient, unique_user: Tes | |||||||
|  |  | ||||||
|     # Get Recipe and check that the ingredient is associated with the step |     # Get Recipe and check that the ingredient is associated with the step | ||||||
|  |  | ||||||
|     response = api_client.get(routes.RoutesRecipe.item(recipe.slug), headers=unique_user.token) |     response = api_client.get(routes.recipes.Recipe.item(recipe.slug), headers=unique_user.token) | ||||||
|  |  | ||||||
|     assert response.status_code == 200 |     assert response.status_code == 200 | ||||||
|  |  | ||||||
|     recipe = json.loads(response.text) |     data: dict = json.loads(response.text) | ||||||
|  |  | ||||||
|     for idx, step in enumerate(recipe.get("recipeInstructions")): |     for idx, stp in enumerate(data.get("recipeInstructions")): | ||||||
|         all_refs = [ref["referenceId"] for ref in step.get("ingredientReferences")] |         all_refs = [ref["referenceId"] for ref in stp.get("ingredientReferences")] | ||||||
|  |  | ||||||
|         assert len(all_refs) == 2 |         assert len(all_refs) == 2 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,8 +10,8 @@ from tests.utils import routes | |||||||
| class CategoryTestCase(ABCMultiTenantTestCase): | class CategoryTestCase(ABCMultiTenantTestCase): | ||||||
|     items: list[RecipeCategory] |     items: list[RecipeCategory] | ||||||
|  |  | ||||||
|     def seed_action(self, group_id: str) -> set[int]: |     def seed_action(self, group_id: str) -> set[str]: | ||||||
|         category_ids: set[int] = set() |         category_ids: set[str] = set() | ||||||
|         for _ in range(10): |         for _ in range(10): | ||||||
|             category = self.database.categories.create( |             category = self.database.categories.create( | ||||||
|                 CategorySave( |                 CategorySave( | ||||||
| @@ -26,8 +26,8 @@ class CategoryTestCase(ABCMultiTenantTestCase): | |||||||
|         return category_ids |         return category_ids | ||||||
|  |  | ||||||
|     def seed_multi(self, group1_id: str, group2_id: str) -> tuple[set[str], set[str]]: |     def seed_multi(self, group1_id: str, group2_id: str) -> tuple[set[str], set[str]]: | ||||||
|         g1_item_ids = set() |         g1_item_ids: set[str] = set() | ||||||
|         g2_item_ids = set() |         g2_item_ids: set[str] = set() | ||||||
|  |  | ||||||
|         for group_id, item_ids in [(group1_id, g1_item_ids), (group2_id, g2_item_ids)]: |         for group_id, item_ids in [(group1_id, g1_item_ids), (group2_id, g2_item_ids)]: | ||||||
|             for _ in range(10): |             for _ in range(10): | ||||||
| @@ -44,7 +44,7 @@ class CategoryTestCase(ABCMultiTenantTestCase): | |||||||
|         return g1_item_ids, g2_item_ids |         return g1_item_ids, g2_item_ids | ||||||
|  |  | ||||||
|     def get_all(self, token: str) -> Response: |     def get_all(self, token: str) -> Response: | ||||||
|         return self.client.get(routes.RoutesCategory.base, headers=token) |         return self.client.get(routes.organizers.Categories.base, headers=token) | ||||||
|  |  | ||||||
|     def cleanup(self) -> None: |     def cleanup(self) -> None: | ||||||
|         for item in self.items: |         for item in self.items: | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ class FoodsTestCase(ABCMultiTenantTestCase): | |||||||
|         return g1_item_ids, g2_item_ids |         return g1_item_ids, g2_item_ids | ||||||
|  |  | ||||||
|     def get_all(self, token: str) -> Response: |     def get_all(self, token: str) -> Response: | ||||||
|         return self.client.get(routes.RoutesFoods.base, headers=token) |         return self.client.get(routes.recipes.Foods.base, headers=token) | ||||||
|  |  | ||||||
|     def cleanup(self) -> None: |     def cleanup(self) -> None: | ||||||
|         for item in self.items: |         for item in self.items: | ||||||
|   | |||||||
| @@ -10,8 +10,8 @@ from tests.utils import routes | |||||||
| class TagsTestCase(ABCMultiTenantTestCase): | class TagsTestCase(ABCMultiTenantTestCase): | ||||||
|     items: list[RecipeTag] |     items: list[RecipeTag] | ||||||
|  |  | ||||||
|     def seed_action(self, group_id: str) -> set[int]: |     def seed_action(self, group_id: str) -> set[str]: | ||||||
|         tag_ids: set[int] = set() |         tag_ids: set[str] = set() | ||||||
|         for _ in range(10): |         for _ in range(10): | ||||||
|             tag = self.database.tags.create( |             tag = self.database.tags.create( | ||||||
|                 TagSave( |                 TagSave( | ||||||
| @@ -26,8 +26,8 @@ class TagsTestCase(ABCMultiTenantTestCase): | |||||||
|         return tag_ids |         return tag_ids | ||||||
|  |  | ||||||
|     def seed_multi(self, group1_id: str, group2_id: str) -> tuple[set[str], set[str]]: |     def seed_multi(self, group1_id: str, group2_id: str) -> tuple[set[str], set[str]]: | ||||||
|         g1_item_ids = set() |         g1_item_ids: set[str] = set() | ||||||
|         g2_item_ids = set() |         g2_item_ids: set[str] = set() | ||||||
|  |  | ||||||
|         for group_id, item_ids in [(group1_id, g1_item_ids), (group2_id, g2_item_ids)]: |         for group_id, item_ids in [(group1_id, g1_item_ids), (group2_id, g2_item_ids)]: | ||||||
|             for _ in range(10): |             for _ in range(10): | ||||||
| @@ -44,7 +44,7 @@ class TagsTestCase(ABCMultiTenantTestCase): | |||||||
|         return g1_item_ids, g2_item_ids |         return g1_item_ids, g2_item_ids | ||||||
|  |  | ||||||
|     def get_all(self, token: str) -> Response: |     def get_all(self, token: str) -> Response: | ||||||
|         return self.client.get(routes.RoutesTags.base, headers=token) |         return self.client.get(routes.organizers.Tags.base, headers=token) | ||||||
|  |  | ||||||
|     def cleanup(self) -> None: |     def cleanup(self) -> None: | ||||||
|         for item in self.items: |         for item in self.items: | ||||||
|   | |||||||
| @@ -44,7 +44,7 @@ class ToolsTestCase(ABCMultiTenantTestCase): | |||||||
|         return g1_item_ids, g2_item_ids |         return g1_item_ids, g2_item_ids | ||||||
|  |  | ||||||
|     def get_all(self, token: str) -> Response: |     def get_all(self, token: str) -> Response: | ||||||
|         return self.client.get(routes.RoutesTools.base, headers=token) |         return self.client.get(routes.organizers.Tools.base, headers=token) | ||||||
|  |  | ||||||
|     def cleanup(self) -> None: |     def cleanup(self) -> None: | ||||||
|         for item in self.items: |         for item in self.items: | ||||||
|   | |||||||
| @@ -9,8 +9,8 @@ from tests.utils import routes | |||||||
| class UnitsTestCase(ABCMultiTenantTestCase): | class UnitsTestCase(ABCMultiTenantTestCase): | ||||||
|     items: list[IngredientUnit] |     items: list[IngredientUnit] | ||||||
|  |  | ||||||
|     def seed_action(self, group_id: str) -> set[int]: |     def seed_action(self, group_id: str) -> set[str]: | ||||||
|         unit_ids: set[int] = set() |         unit_ids: set[str] = set() | ||||||
|         for _ in range(10): |         for _ in range(10): | ||||||
|             unit = self.database.ingredient_units.create( |             unit = self.database.ingredient_units.create( | ||||||
|                 SaveIngredientUnit( |                 SaveIngredientUnit( | ||||||
| @@ -25,8 +25,8 @@ class UnitsTestCase(ABCMultiTenantTestCase): | |||||||
|         return unit_ids |         return unit_ids | ||||||
|  |  | ||||||
|     def seed_multi(self, group1_id: str, group2_id: str) -> tuple[set[str], set[str]]: |     def seed_multi(self, group1_id: str, group2_id: str) -> tuple[set[str], set[str]]: | ||||||
|         g1_item_ids = set() |         g1_item_ids: set[str] = set() | ||||||
|         g2_item_ids = set() |         g2_item_ids: set[str] = set() | ||||||
|  |  | ||||||
|         for group_id, item_ids in [(group1_id, g1_item_ids), (group2_id, g2_item_ids)]: |         for group_id, item_ids in [(group1_id, g1_item_ids), (group2_id, g2_item_ids)]: | ||||||
|             for _ in range(10): |             for _ in range(10): | ||||||
| @@ -43,7 +43,7 @@ class UnitsTestCase(ABCMultiTenantTestCase): | |||||||
|         return g1_item_ids, g2_item_ids |         return g1_item_ids, g2_item_ids | ||||||
|  |  | ||||||
|     def get_all(self, token: str) -> Response: |     def get_all(self, token: str) -> Response: | ||||||
|         return self.client.get(routes.RoutesUnits.base, headers=token) |         return self.client.get(routes.recipes.Units.base, headers=token) | ||||||
|  |  | ||||||
|     def cleanup(self) -> None: |     def cleanup(self) -> None: | ||||||
|         for item in self.items: |         for item in self.items: | ||||||
|   | |||||||
| @@ -1,60 +0,0 @@ | |||||||
| from pydantic import UUID4 |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesBase: |  | ||||||
|     prefix = "/api" |  | ||||||
|     base = f"{prefix}/" |  | ||||||
|  |  | ||||||
|     def __init__(self) -> None: |  | ||||||
|         raise Exception("This class is not meant to be instantiated.") |  | ||||||
|  |  | ||||||
|     @classmethod |  | ||||||
|     def item(cls, item_id: int | str | UUID4) -> str: |  | ||||||
|         return f"{cls.base}/{item_id}" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesFoods(RoutesBase): |  | ||||||
|     base = "/api/foods" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesUnits(RoutesBase): |  | ||||||
|     base = "/api/units" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesOrganizerBase(RoutesBase): |  | ||||||
|     @classmethod |  | ||||||
|     def slug(cls, slug: str) -> str: |  | ||||||
|         return f"{cls.base}/slug/{slug}" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesTools(RoutesOrganizerBase): |  | ||||||
|     base = "/api/organizers/tools" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesTags(RoutesOrganizerBase): |  | ||||||
|     base = "/api/organizers/tags" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesCategory(RoutesOrganizerBase): |  | ||||||
|     base = "/api/organizers/categories" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesRecipe(RoutesBase): |  | ||||||
|     base = "/api/recipes" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesAdminUsers(RoutesBase): |  | ||||||
|     base = "/api/admin/users" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesUsers(RoutesBase): |  | ||||||
|     base = "/api/users" |  | ||||||
|     self = f"{base}/self" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RoutesSeeders(RoutesBase): |  | ||||||
|     base = "/api/groups/seeders" |  | ||||||
|  |  | ||||||
|     foods = f"{base}/foods" |  | ||||||
|     units = f"{base}/units" |  | ||||||
|     labels = f"{base}/labels" |  | ||||||
							
								
								
									
										6
									
								
								tests/utils/routes/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tests/utils/routes/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | from . import routes_admin as admin | ||||||
|  | from . import routes_organizers as organizers | ||||||
|  | from . import routes_recipes as recipes | ||||||
|  | from . import routes_seeders as seeders | ||||||
|  | from . import routes_user as user | ||||||
|  | from ._base import RoutesBase | ||||||
							
								
								
									
										17
									
								
								tests/utils/routes/_base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tests/utils/routes/_base.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | from pydantic import UUID4 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def v1(route: str) -> str: | ||||||
|  |     return f"/api{route}" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RoutesBase: | ||||||
|  |     prefix = "/api" | ||||||
|  |     base = f"{prefix}/" | ||||||
|  |  | ||||||
|  |     def __init__(self) -> None: | ||||||
|  |         raise NotImplementedError("This class is not meant to be instantiated.") | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def item(cls, item_id: int | str | UUID4) -> str: | ||||||
|  |         return f"{cls.base}/{item_id}" | ||||||
							
								
								
									
										5
									
								
								tests/utils/routes/routes_admin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/utils/routes/routes_admin.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | from ._base import RoutesBase, v1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AdminUsers(RoutesBase): | ||||||
|  |     base = v1("/admin/users") | ||||||
							
								
								
									
										19
									
								
								tests/utils/routes/routes_organizers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/utils/routes/routes_organizers.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | from ._base import RoutesBase, v1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RoutesOrganizerBase(RoutesBase): | ||||||
|  |     @classmethod | ||||||
|  |     def slug(cls, slug: str) -> str: | ||||||
|  |         return f"{cls.base}/slug/{slug}" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Tools(RoutesOrganizerBase): | ||||||
|  |     base = v1("/organizers/tools") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Tags(RoutesOrganizerBase): | ||||||
|  |     base = v1("/organizers/tags") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Categories(RoutesOrganizerBase): | ||||||
|  |     base = v1("/organizers/categories") | ||||||
							
								
								
									
										13
									
								
								tests/utils/routes/routes_recipes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/utils/routes/routes_recipes.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | from ._base import RoutesBase, v1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Foods(RoutesBase): | ||||||
|  |     base = v1("/foods") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Units(RoutesBase): | ||||||
|  |     base = v1("/units") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Recipe(RoutesBase): | ||||||
|  |     base = v1("/recipes") | ||||||
							
								
								
									
										9
									
								
								tests/utils/routes/routes_seeders.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/utils/routes/routes_seeders.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | from ._base import RoutesBase, v1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Seeders(RoutesBase): | ||||||
|  |     base = v1("/groups/seeders") | ||||||
|  |  | ||||||
|  |     foods = f"{base}/foods" | ||||||
|  |     units = f"{base}/units" | ||||||
|  |     labels = f"{base}/labels" | ||||||
							
								
								
									
										6
									
								
								tests/utils/routes/routes_user.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tests/utils/routes/routes_user.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | from ._base import RoutesBase, v1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Users(RoutesBase): | ||||||
|  |     base = v1("/users") | ||||||
|  |     self = f"{base}/self" | ||||||
		Reference in New Issue
	
	Block a user