sinc
parent
7eefa8e5db
commit
58ecd82bb6
|
@ -1,4 +1,6 @@
|
||||||
from fastapi import FastAPI
|
import aioredis
|
||||||
|
from fastapi import FastAPI, Request
|
||||||
|
from starlette.responses import JSONResponse
|
||||||
|
|
||||||
from fastfood.routers.dish import router as dish_router
|
from fastfood.routers.dish import router as dish_router
|
||||||
from fastfood.routers.menu import router as menu_router
|
from fastfood.routers.menu import router as menu_router
|
||||||
|
@ -61,7 +63,7 @@ tags_metadata = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def create_app() -> FastAPI:
|
def create_app(redis=None) -> FastAPI:
|
||||||
"""
|
"""
|
||||||
Фабрика FastAPI.
|
Фабрика FastAPI.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,31 +1,35 @@
|
||||||
|
from typing import Annotated
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
|
from fastapi import Depends
|
||||||
from sqlalchemy import delete, distinct, func, select, update
|
from sqlalchemy import delete, distinct, func, select, update
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import aliased
|
from sqlalchemy.orm import aliased
|
||||||
|
|
||||||
from fastfood import models, schemas
|
from fastfood import models, schemas
|
||||||
|
from fastfood.dbase import get_async_session
|
||||||
|
|
||||||
|
|
||||||
class MenuCrud:
|
class MenuCrud:
|
||||||
@staticmethod
|
def __init__(self, session: AsyncSession = Depends(get_async_session)):
|
||||||
async def get_menus(session: AsyncSession):
|
self.db = session
|
||||||
async with session:
|
|
||||||
query = select(models.Menu)
|
async def get_menus(self):
|
||||||
menus = await session.execute(query)
|
query = select(models.Menu)
|
||||||
return menus
|
menus = await self.db.execute(query)
|
||||||
|
return menus.scalars().all()
|
||||||
|
|
||||||
|
async def create_menu_item(self, menu: schemas.MenuBase):
|
||||||
|
new_menu = models.Menu(**menu.model_dump())
|
||||||
|
self.db.add(new_menu)
|
||||||
|
await self.db.commit()
|
||||||
|
await self.db.refresh(new_menu)
|
||||||
|
return new_menu
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def create_menu_item(menu: schemas.MenuBase, session: AsyncSession):
|
async def get_menu_item(
|
||||||
async with session:
|
menu_id: UUID, session: AsyncSession = Depends(get_async_session)
|
||||||
new_menu = models.Menu(**menu.model_dump())
|
):
|
||||||
session.add(new_menu)
|
|
||||||
await session.commit()
|
|
||||||
await session.refresh(new_menu)
|
|
||||||
return new_menu
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
async def get_menu_item(menu_id: UUID, session: AsyncSession):
|
|
||||||
async with session:
|
async with session:
|
||||||
m = aliased(models.Menu)
|
m = aliased(models.Menu)
|
||||||
s = aliased(models.SubMenu)
|
s = aliased(models.SubMenu)
|
||||||
|
@ -52,7 +56,7 @@ class MenuCrud:
|
||||||
async def update_menu_item(
|
async def update_menu_item(
|
||||||
menu_id: UUID,
|
menu_id: UUID,
|
||||||
menu: schemas.MenuBase,
|
menu: schemas.MenuBase,
|
||||||
session: AsyncSession,
|
session: AsyncSession = Depends(get_async_session),
|
||||||
):
|
):
|
||||||
async with session:
|
async with session:
|
||||||
query = (
|
query = (
|
||||||
|
@ -67,7 +71,9 @@ class MenuCrud:
|
||||||
return updated_menu
|
return updated_menu
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def delete_menu_item(menu_id: UUID, session: AsyncSession):
|
async def delete_menu_item(
|
||||||
|
menu_id: UUID, session: AsyncSession = Depends(get_async_session)
|
||||||
|
):
|
||||||
async with session:
|
async with session:
|
||||||
query = delete(models.Menu).where(models.Menu.id == menu_id)
|
query = delete(models.Menu).where(models.Menu.id == menu_id)
|
||||||
await session.execute(query)
|
await session.execute(query)
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
import pickle
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import redis.asyncio as redis
|
||||||
|
from fastapi import BackgroundTasks, Depends
|
||||||
|
|
||||||
|
|
||||||
|
def get_async_redis_pool():
|
||||||
|
redis_url = "redis://localhost"
|
||||||
|
return redis.from_url(redis_url, decode_responses=False)
|
||||||
|
|
||||||
|
|
||||||
|
async def get_async_redis_client(
|
||||||
|
redis_pool: redis.Redis = Depends(get_async_redis_pool),
|
||||||
|
):
|
||||||
|
return redis_pool
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncRedisCache:
|
||||||
|
def __init__(self, redis_pool: redis.Redis = Depends(get_async_redis_pool)) -> None:
|
||||||
|
self.redis_pool = redis_pool
|
||||||
|
self.ttl = 1800
|
||||||
|
|
||||||
|
async def get(self, key: str) -> Any | None:
|
||||||
|
data = await self.redis_pool.get(key)
|
||||||
|
if data is not None:
|
||||||
|
return pickle.loads(data)
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def set(
|
||||||
|
self, key: str, value: Any, background_tasks: BackgroundTasks
|
||||||
|
) -> None:
|
||||||
|
data = pickle.dumps(value)
|
||||||
|
background_tasks.add_task(self._set_cache, key, data)
|
||||||
|
|
||||||
|
async def _set_cache(self, key: str, data: Any) -> None:
|
||||||
|
await self.redis_pool.setex(key, self.ttl, data)
|
||||||
|
|
||||||
|
async def delete(self, key: str, background_tasks: BackgroundTasks) -> None:
|
||||||
|
background_tasks.add_task(self._delete_cache, key)
|
||||||
|
|
||||||
|
async def _delete_cache(self, key: str) -> None:
|
||||||
|
await self.redis_pool.delete(key)
|
||||||
|
|
||||||
|
async def clear_cache(
|
||||||
|
self, pattern: str, background_tasks: BackgroundTasks
|
||||||
|
) -> None:
|
||||||
|
keys = [key async for key in self.redis_pool.scan_iter(pattern)]
|
||||||
|
if keys:
|
||||||
|
background_tasks.add_task(self._clear_keys, keys)
|
||||||
|
|
||||||
|
async def _clear_keys(self, keys: list[str]) -> None:
|
||||||
|
await self.redis_pool.delete(*keys)
|
||||||
|
|
||||||
|
async def clear_after_change(
|
||||||
|
self, menu_id: int | str, background_tasks: BackgroundTasks
|
||||||
|
) -> None:
|
||||||
|
await self.clear_cache(f"{str(menu_id)}*", background_tasks)
|
||||||
|
await self.clear_cache("all*", background_tasks)
|
|
@ -1,12 +1,13 @@
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from fastfood import schemas
|
from fastfood import schemas
|
||||||
from fastfood.cruds import crud
|
from fastfood.cruds import crud
|
||||||
from fastfood.dbase import get_async_session
|
from fastfood.dbase import get_async_session
|
||||||
|
from fastfood.service.menu import MenuService
|
||||||
|
|
||||||
router = APIRouter(
|
router = APIRouter(
|
||||||
prefix="/api/v1/menus",
|
prefix="/api/v1/menus",
|
||||||
|
@ -15,21 +16,22 @@ router = APIRouter(
|
||||||
|
|
||||||
|
|
||||||
@router.get("/", response_model=Optional[List[schemas.Menu]])
|
@router.get("/", response_model=Optional[List[schemas.Menu]])
|
||||||
async def get_menus(session: AsyncSession = Depends(get_async_session)):
|
async def get_menus(
|
||||||
result = await crud.get_menus(session=session)
|
menu: MenuService = Depends(),
|
||||||
return result.scalars().all()
|
background_tasks: BackgroundTasks = BackgroundTasks(),
|
||||||
|
):
|
||||||
|
result = await menu.read_menus()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@router.post("/", status_code=201, response_model=schemas.Menu)
|
@router.post("/", status_code=201, response_model=schemas.Menu)
|
||||||
async def add_menu(
|
async def add_menu(
|
||||||
menu: schemas.MenuBase,
|
menu: schemas.MenuBase,
|
||||||
session: AsyncSession = Depends(get_async_session),
|
responce: MenuService = Depends(),
|
||||||
|
background_tasks: BackgroundTasks = BackgroundTasks(),
|
||||||
):
|
):
|
||||||
result = await crud.create_menu_item(
|
rspn = await responce.create_menu(menu)
|
||||||
menu=menu,
|
return rspn
|
||||||
session=session,
|
|
||||||
)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{menu_id}", response_model=schemas.MenuRead)
|
@router.get("/{menu_id}", response_model=schemas.MenuRead)
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
import redis.asyncio as redis # type: ignore
|
||||||
|
from fastapi import BackgroundTasks, Depends
|
||||||
|
|
||||||
|
from fastfood.cruds.menu import MenuCrud
|
||||||
|
from fastfood.cruds.redis_cache import AsyncRedisCache, get_async_redis_client
|
||||||
|
from fastfood.schemas import MenuRead
|
||||||
|
|
||||||
|
|
||||||
|
class MenuService:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
menu_crud: MenuCrud = Depends(),
|
||||||
|
redis_client: redis.Redis = Depends(get_async_redis_client),
|
||||||
|
background_tasks: BackgroundTasks = None,
|
||||||
|
):
|
||||||
|
self.menu_crud = menu_crud
|
||||||
|
self.cache_client = AsyncRedisCache(redis_client)
|
||||||
|
self.background_tasks = background_tasks
|
||||||
|
|
||||||
|
async def read_menus(self):
|
||||||
|
cached = await self.cache_client.get("all")
|
||||||
|
|
||||||
|
if cached:
|
||||||
|
return cached
|
||||||
|
|
||||||
|
data = await self.menu_crud.get_menus()
|
||||||
|
print("not cached", data)
|
||||||
|
await self.cache_client.set("all", data, self.background_tasks)
|
||||||
|
return data
|
||||||
|
|
||||||
|
async def create_menu(self, menu_data):
|
||||||
|
data = await self.menu_crud.create_menu_item(menu_data)
|
||||||
|
await self.cache_client.set(str(data.id), data, self.background_tasks)
|
||||||
|
await self.cache_client.clear_after_change(str(data.id), self.background_tasks)
|
||||||
|
return data
|
||||||
|
|
||||||
|
# async def read_menu(self, menu_id: int | str):
|
||||||
|
# cached = await self.cache_client.get(f'{menu_id}')
|
||||||
|
# if cached is not None:
|
||||||
|
# return cached
|
||||||
|
#
|
||||||
|
# data = await self.menu_crud.read_menu(menu_id)
|
||||||
|
# await self.cache_client.set(f'{menu_id}', data, self.background_tasks)
|
||||||
|
# return data
|
||||||
|
#
|
||||||
|
# async def update_menu(self, menu_id: int | str, menu_data):
|
||||||
|
# data = await self.menu_crud.update_menu(menu_id, menu_data)
|
||||||
|
# await self.cache_client.set(f'{menu_id}', data, self.background_tasks)
|
||||||
|
# await self.cache_client.clear_after_change(menu_id, self.background_tasks)
|
||||||
|
# return data
|
||||||
|
#
|
||||||
|
# async def del_menu(self, menu_id: int | str):
|
||||||
|
# data = await self.menu_crud.del_menu(menu_id)
|
||||||
|
# await self.cache_client.delete(f'{menu_id}', self.background_tasks)
|
||||||
|
# await self.cache_client.clear_after_change(menu_id, self.background_tasks)
|
||||||
|
# return data
|
||||||
|
#
|
||||||
|
# async def orm_read_menu(self, menu_id: int | str):
|
||||||
|
# return await self.menu_crud.orm_read_menu(menu_id)
|
||||||
|
#
|
||||||
|
# async def read_full_menus(self):
|
||||||
|
# menu_data = await self.menu_crud.get_full_menus()
|
||||||
|
# return FullMenuListResponse(menus=menu_data)
|
|
@ -670,6 +670,24 @@ files = [
|
||||||
[package.extras]
|
[package.extras]
|
||||||
cli = ["click (>=5.0)"]
|
cli = ["click (>=5.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redis"
|
||||||
|
version = "5.0.1"
|
||||||
|
description = "Python client for Redis database and key-value store"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "redis-5.0.1-py3-none-any.whl", hash = "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f"},
|
||||||
|
{file = "redis-5.0.1.tar.gz", hash = "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
hiredis = ["hiredis (>=1.0.0)"]
|
||||||
|
ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sniffio"
|
name = "sniffio"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -829,4 +847,4 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)",
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.10"
|
python-versions = "^3.10"
|
||||||
content-hash = "5bbc3cad36f6f40d10cb848918426b640f9e703bc2c6b22b5b8fe381a6251ded"
|
content-hash = "8da16a83882a9b35a5a05441a33e2296b04a5f664dbb090fec0f384c709fb7ef"
|
||||||
|
|
|
@ -14,6 +14,7 @@ asyncpg = "^0.29.0"
|
||||||
pydantic-settings = "^2.1.0"
|
pydantic-settings = "^2.1.0"
|
||||||
email-validator = "^2.1.0.post1"
|
email-validator = "^2.1.0.post1"
|
||||||
pytest-asyncio = "^0.23.3"
|
pytest-asyncio = "^0.23.3"
|
||||||
|
redis = "^5.0.1"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
|
|
|
@ -53,16 +53,10 @@ def app(event_loop) -> Generator[FastAPI, None, None]:
|
||||||
yield app
|
yield app
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="function")
|
@pytest_asyncio.fixture()
|
||||||
async def client(app) -> AsyncGenerator[AsyncClient, None]:
|
async def client(app) -> AsyncGenerator[AsyncClient, None]:
|
||||||
async with AsyncClient(
|
async with AsyncClient(
|
||||||
app=app,
|
app=app,
|
||||||
base_url="http://localhost:8000/api/v1/menus",
|
base_url="http://localhost:8000/api/v1/menus",
|
||||||
) as async_client:
|
) as async_client:
|
||||||
yield async_client
|
yield async_client
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="function")
|
|
||||||
async def asession(event_loop) -> AsyncGenerator[AsyncSession, None]:
|
|
||||||
async with async_session_maker() as session:
|
|
||||||
yield session
|
|
||||||
|
|
|
@ -7,9 +7,10 @@ from httpx import AsyncClient, Response
|
||||||
class TestBaseCrud:
|
class TestBaseCrud:
|
||||||
class Menu:
|
class Menu:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def read_all(ac: AsyncClient) -> Tuple[int, dict]:
|
async def read_all(cli: AsyncClient) -> Tuple[int, dict]:
|
||||||
"""чтение всех меню"""
|
"""чтение всех меню"""
|
||||||
response: Response = await ac.get("/")
|
|
||||||
|
response: Response = await cli.get("/")
|
||||||
return response.status_code, response.json()
|
return response.status_code, response.json()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -144,264 +145,269 @@ class TestBaseCrud:
|
||||||
)
|
)
|
||||||
return response.status_code
|
return response.status_code
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_menu_crud(self, client: AsyncClient) -> None:
|
|
||||||
"""Тестирование функций меню"""
|
|
||||||
code, rspn = await self.Menu.read_all(client)
|
|
||||||
assert code == 200
|
|
||||||
|
|
||||||
data = {"title": "Menu", "description": None}
|
@pytest.mark.asyncio
|
||||||
code, rspn = await self.Menu.write(client, data)
|
async def test_menu_crud(client) -> None:
|
||||||
assert code == 201
|
"""Тестирование функций меню"""
|
||||||
assert rspn["title"] == "Menu"
|
code, rspn = await TestBaseCrud.Menu.read_all(client)
|
||||||
assert rspn["description"] is None
|
assert code == 200
|
||||||
|
|
||||||
code, menu = await self.Menu.get(client, {"id": rspn.get("id")})
|
data = {"title": "Menu", "description": None}
|
||||||
assert code == 200
|
code, rspn = await TestBaseCrud.Menu.write(client, data)
|
||||||
assert menu["title"] == rspn["title"]
|
assert code == 201
|
||||||
|
assert rspn["title"] == "Menu"
|
||||||
upd_data = {
|
assert rspn["description"] is None
|
||||||
"id": rspn.get("id"),
|
data = {"title": "Menu1", "description": "11"}
|
||||||
"title": "upd Menu",
|
code, rspn = await TestBaseCrud.Menu.write(client, data)
|
||||||
"description": "",
|
code, rspn = await TestBaseCrud.Menu.read_all(client)
|
||||||
}
|
|
||||||
code, upd_rspn = await self.Menu.update(client, upd_data)
|
|
||||||
assert code == 200
|
|
||||||
assert upd_rspn["title"] == "upd Menu"
|
|
||||||
|
|
||||||
code = await self.Menu.delete(client, rspn)
|
|
||||||
assert code == 200
|
|
||||||
|
|
||||||
code, menu = await self.Menu.get(client, {"id": rspn.get("id")})
|
|
||||||
assert code == 404
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_submenus(self, client) -> None:
|
|
||||||
# Создаем меню и проверяем ответ
|
|
||||||
menu = {"title": "Menu", "description": "main menu"}
|
|
||||||
code, rspn = await self.Menu.write(client, menu)
|
|
||||||
assert code == 201
|
|
||||||
menu.update(rspn)
|
|
||||||
|
|
||||||
# Проверяем наличие подменю
|
|
||||||
code, rspn = await self.Submenu.read_all(client, menu)
|
|
||||||
assert code == 200
|
|
||||||
assert rspn == []
|
|
||||||
|
|
||||||
# Создаем и проверяем подменю
|
|
||||||
submenu = {
|
|
||||||
"title": "Submenu",
|
|
||||||
"description": "submenu",
|
|
||||||
"parent_menu": menu["id"],
|
|
||||||
}
|
|
||||||
code, rspn = await self.Submenu.write(client, menu, submenu)
|
|
||||||
assert code == 201
|
|
||||||
submenu.update(rspn)
|
|
||||||
|
|
||||||
# Проверяем меню на наличие подменю
|
|
||||||
code, rspn = await self.Menu.get(client, menu)
|
|
||||||
assert code == 200
|
|
||||||
assert rspn["submenus_count"] == 1
|
|
||||||
|
|
||||||
# Обновляем подменю и проверяем
|
|
||||||
submenu["title"] = "updated_submenu"
|
|
||||||
code, rspn = await self.Submenu.update(client, menu, submenu)
|
|
||||||
assert code == 200
|
|
||||||
assert submenu["title"] == rspn["title"]
|
|
||||||
submenu.update(rspn)
|
|
||||||
|
|
||||||
# Удаляем подменю
|
|
||||||
code = await self.Submenu.delete(client, menu, submenu)
|
|
||||||
assert code == 200
|
|
||||||
|
|
||||||
# Проверяем меню
|
|
||||||
code, rspn = await self.Menu.get(client, menu)
|
|
||||||
assert code == 200
|
|
||||||
assert rspn["submenus_count"] == 0
|
|
||||||
|
|
||||||
# Проверяем удаленное подменю
|
|
||||||
code, rspn = await self.Submenu.get(client, menu, submenu)
|
|
||||||
assert code == 404
|
|
||||||
|
|
||||||
# удаляем сопутствующее
|
|
||||||
await self.Menu.delete(client, menu)
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_dishes(self, client: AsyncClient) -> None:
|
|
||||||
# Создаем меню и проверяем ответ
|
|
||||||
menu = {
|
|
||||||
"title": "Menu",
|
|
||||||
"description": "main menu",
|
|
||||||
}
|
|
||||||
code, rspn = await self.Menu.write(client, menu)
|
|
||||||
assert code == 201
|
|
||||||
menu.update(rspn)
|
|
||||||
|
|
||||||
# Создаем и проверяем подменю
|
|
||||||
submenu = {
|
|
||||||
"title": "Submenu",
|
|
||||||
"description": "submenu",
|
|
||||||
"parent_menu": menu["id"],
|
|
||||||
}
|
|
||||||
code, rspn = await self.Submenu.write(client, menu, submenu)
|
|
||||||
assert code == 201
|
|
||||||
submenu.update(rspn)
|
|
||||||
|
|
||||||
# Проверяем все блюда в подменю
|
|
||||||
code, rspn = await self.Dish.read_all(client, menu, submenu)
|
|
||||||
assert code == 200
|
|
||||||
assert rspn == []
|
|
||||||
|
|
||||||
# Добавляем блюдо
|
|
||||||
dish = {
|
|
||||||
"title": "dish",
|
|
||||||
"description": "some dish",
|
|
||||||
"price": "12.5",
|
|
||||||
"parent_submenu": submenu["id"],
|
|
||||||
}
|
|
||||||
code, rspn = await self.Dish.write(client, menu, submenu, dish)
|
|
||||||
assert code == 201
|
|
||||||
dish.update(rspn)
|
|
||||||
|
|
||||||
# Получаем блюдо
|
|
||||||
code, rspn = await self.Dish.get(client, menu, submenu, dish)
|
|
||||||
assert code == 200
|
|
||||||
assert rspn["title"] == dish["title"]
|
|
||||||
|
|
||||||
# Проверяем меню на количество блюд
|
|
||||||
code, rspn = await self.Menu.get(client, menu)
|
|
||||||
assert code == 200
|
|
||||||
assert rspn["dishes_count"] == 1
|
|
||||||
|
|
||||||
# Проверяем подменю на наличие блюд
|
|
||||||
code, rspn = await self.Submenu.get(client, menu, submenu)
|
|
||||||
assert code == 200
|
|
||||||
assert rspn["dishes_count"] == 1
|
|
||||||
|
|
||||||
# Обновляем блюдо и проверяем
|
|
||||||
dish["title"] = "updated_dish"
|
|
||||||
code, rspn = await self.Dish.update(client, menu, submenu, dish)
|
|
||||||
assert code == 200
|
|
||||||
assert dish["title"] == rspn["title"]
|
|
||||||
dish.update(rspn)
|
|
||||||
|
|
||||||
# Удаляем подменю
|
|
||||||
code = await self.Dish.delete(client, menu, submenu, dish)
|
|
||||||
assert code == 200
|
|
||||||
|
|
||||||
# Проверяем меню
|
|
||||||
code, rspn = await self.Menu.get(client, menu)
|
|
||||||
assert code == 200
|
|
||||||
assert rspn["dishes_count"] == 0
|
|
||||||
|
|
||||||
# Проверяем подменю на наличие блюд
|
|
||||||
code, rspn = await self.Submenu.get(client, menu, submenu)
|
|
||||||
assert code == 200
|
|
||||||
assert rspn["dishes_count"] == 0
|
|
||||||
|
|
||||||
# Проверяем удаленное блюдо
|
|
||||||
code, rspn = await self.Dish.get(client, menu, submenu, dish)
|
|
||||||
assert code == 404
|
|
||||||
|
|
||||||
# удаляем сопутствующее
|
|
||||||
await self.Submenu.delete(client, menu, submenu)
|
|
||||||
await self.Menu.delete(client, menu)
|
|
||||||
|
|
||||||
|
|
||||||
class TestСontinuity:
|
# code, menu = await self.Menu.get(client, {"id": rspn.get("id")})
|
||||||
@pytest.mark.asyncio
|
# assert code == 200
|
||||||
async def test_postman_continuity(self, client):
|
# assert menu["title"] == rspn["title"]
|
||||||
# Создаем меню
|
#
|
||||||
menu = {
|
# upd_data = {
|
||||||
"title": "Menu",
|
# "id": rspn.get("id"),
|
||||||
"description": "main menu",
|
# "title": "upd Menu",
|
||||||
}
|
# "description": "",
|
||||||
code, rspn = await TestBaseCrud.Menu.write(client, menu)
|
# }
|
||||||
assert code == 201
|
# code, upd_rspn = await self.Menu.update(client, upd_data)
|
||||||
assert "id" in rspn.keys()
|
# assert code == 200
|
||||||
menu.update(rspn)
|
# assert upd_rspn["title"] == "upd Menu"
|
||||||
|
#
|
||||||
# Создаем подменю
|
# code = await self.Menu.delete(client, rspn)
|
||||||
submenu = {
|
# assert code == 200
|
||||||
"title": "Submenu",
|
#
|
||||||
"description": "submenu",
|
# code, menu = await self.Menu.get(client, {"id": rspn.get("id")})
|
||||||
"parent_menu": menu["id"],
|
# assert code == 404
|
||||||
}
|
#
|
||||||
code, rspn = await TestBaseCrud.Submenu.write(client, menu, submenu)
|
# @pytest.mark.asyncio
|
||||||
assert code == 201
|
# async def test_submenus(self, client) -> None:
|
||||||
assert "id" in rspn.keys()
|
# # Создаем меню и проверяем ответ
|
||||||
submenu.update(rspn)
|
# menu = {"title": "Menu", "description": "main menu"}
|
||||||
|
# code, rspn = await self.Menu.write(client, menu)
|
||||||
# Добавляем блюдо1
|
# assert code == 201
|
||||||
dish = {
|
# menu.update(rspn)
|
||||||
"title": "dish1",
|
#
|
||||||
"description": "some dish1",
|
# # Проверяем наличие подменю
|
||||||
"price": "13.50",
|
# code, rspn = await self.Submenu.read_all(client, menu)
|
||||||
"parent_submenu": submenu["id"],
|
# assert code == 200
|
||||||
}
|
# assert rspn == []
|
||||||
code, rspn = await TestBaseCrud.Dish.write(client, menu, submenu, dish)
|
#
|
||||||
assert code == 201
|
# # Создаем и проверяем подменю
|
||||||
assert "id" in rspn.keys()
|
# submenu = {
|
||||||
dish.update(rspn)
|
# "title": "Submenu",
|
||||||
|
# "description": "submenu",
|
||||||
# Добавляем блюдо2
|
# "parent_menu": menu["id"],
|
||||||
dish = {
|
# }
|
||||||
"title": "dish2",
|
# code, rspn = await self.Submenu.write(client, menu, submenu)
|
||||||
"description": "some dish2",
|
# assert code == 201
|
||||||
"price": "12.50",
|
# submenu.update(rspn)
|
||||||
"parent_submenu": submenu["id"],
|
#
|
||||||
}
|
# # Проверяем меню на наличие подменю
|
||||||
code, rspn = await TestBaseCrud.Dish.write(client, menu, submenu, dish)
|
# code, rspn = await self.Menu.get(client, menu)
|
||||||
assert code == 201
|
# assert code == 200
|
||||||
assert "id" in rspn.keys()
|
# assert rspn["submenus_count"] == 1
|
||||||
dish.update(rspn)
|
#
|
||||||
|
# # Обновляем подменю и проверяем
|
||||||
# Просматриваем конкретное меню
|
# submenu["title"] = "updated_submenu"
|
||||||
code, rspn = await TestBaseCrud.Menu.get(client, menu)
|
# code, rspn = await self.Submenu.update(client, menu, submenu)
|
||||||
assert code == 200
|
# assert code == 200
|
||||||
assert "id" in rspn.keys()
|
# assert submenu["title"] == rspn["title"]
|
||||||
assert menu["id"] == rspn["id"]
|
# submenu.update(rspn)
|
||||||
assert "submenus_count" in rspn.keys()
|
#
|
||||||
assert rspn["submenus_count"] == 1
|
# # Удаляем подменю
|
||||||
assert "dishes_count" in rspn.keys()
|
# code = await self.Submenu.delete(client, menu, submenu)
|
||||||
assert rspn["dishes_count"] == 2
|
# assert code == 200
|
||||||
|
#
|
||||||
# Просматриваем конкретное подменю
|
# # Проверяем меню
|
||||||
code, rspn = await TestBaseCrud.Submenu.get(client, menu, submenu)
|
# code, rspn = await self.Menu.get(client, menu)
|
||||||
assert code == 200
|
# assert code == 200
|
||||||
assert "id" in rspn.keys()
|
# assert rspn["submenus_count"] == 0
|
||||||
assert "dishes_count" in rspn.keys()
|
#
|
||||||
assert rspn["dishes_count"] == 2
|
# # Проверяем удаленное подменю
|
||||||
|
# code, rspn = await self.Submenu.get(client, menu, submenu)
|
||||||
# Удаляем подменю
|
# assert code == 404
|
||||||
code = await TestBaseCrud.Submenu.delete(client, menu, submenu)
|
#
|
||||||
assert code == 200
|
# # удаляем сопутствующее
|
||||||
|
# await self.Menu.delete(client, menu)
|
||||||
# Просматриваем список подменю
|
#
|
||||||
code, rspn = await TestBaseCrud.Submenu.read_all(client, menu)
|
# @pytest.mark.asyncio
|
||||||
assert code == 200
|
# async def test_dishes(self, client: AsyncClient) -> None:
|
||||||
assert rspn == []
|
# # Создаем меню и проверяем ответ
|
||||||
|
# menu = {
|
||||||
# Просматриваем список блюд
|
# "title": "Menu",
|
||||||
code, rspn = await TestBaseCrud.Dish.read_all(client, menu, submenu)
|
# "description": "main menu",
|
||||||
assert code == 200
|
# }
|
||||||
assert rspn == []
|
# code, rspn = await self.Menu.write(client, menu)
|
||||||
|
# assert code == 201
|
||||||
# Просматриваем конкретное меню
|
# menu.update(rspn)
|
||||||
code, rspn = await TestBaseCrud.Menu.get(client, menu)
|
#
|
||||||
assert code == 200
|
# # Создаем и проверяем подменю
|
||||||
assert "id" in rspn.keys()
|
# submenu = {
|
||||||
assert menu["id"] == rspn["id"]
|
# "title": "Submenu",
|
||||||
assert "submenus_count" in rspn.keys()
|
# "description": "submenu",
|
||||||
assert rspn["submenus_count"] == 0
|
# "parent_menu": menu["id"],
|
||||||
assert "dishes_count" in rspn.keys()
|
# }
|
||||||
assert rspn["dishes_count"] == 0
|
# code, rspn = await self.Submenu.write(client, menu, submenu)
|
||||||
|
# assert code == 201
|
||||||
# Удаляем меню
|
# submenu.update(rspn)
|
||||||
code = await TestBaseCrud.Menu.delete(client, menu)
|
#
|
||||||
assert code == 200
|
# # Проверяем все блюда в подменю
|
||||||
|
# code, rspn = await self.Dish.read_all(client, menu, submenu)
|
||||||
# Просматриваем все меню
|
# assert code == 200
|
||||||
code, rspn = await TestBaseCrud.Menu.read_all(client)
|
# assert rspn == []
|
||||||
assert code == 200
|
#
|
||||||
assert rspn == []
|
# # Добавляем блюдо
|
||||||
|
# dish = {
|
||||||
|
# "title": "dish",
|
||||||
|
# "description": "some dish",
|
||||||
|
# "price": "12.5",
|
||||||
|
# "parent_submenu": submenu["id"],
|
||||||
|
# }
|
||||||
|
# code, rspn = await self.Dish.write(client, menu, submenu, dish)
|
||||||
|
# assert code == 201
|
||||||
|
# dish.update(rspn)
|
||||||
|
#
|
||||||
|
# # Получаем блюдо
|
||||||
|
# code, rspn = await self.Dish.get(client, menu, submenu, dish)
|
||||||
|
# assert code == 200
|
||||||
|
# assert rspn["title"] == dish["title"]
|
||||||
|
#
|
||||||
|
# # Проверяем меню на количество блюд
|
||||||
|
# code, rspn = await self.Menu.get(client, menu)
|
||||||
|
# assert code == 200
|
||||||
|
# assert rspn["dishes_count"] == 1
|
||||||
|
#
|
||||||
|
# # Проверяем подменю на наличие блюд
|
||||||
|
# code, rspn = await self.Submenu.get(client, menu, submenu)
|
||||||
|
# assert code == 200
|
||||||
|
# assert rspn["dishes_count"] == 1
|
||||||
|
#
|
||||||
|
# # Обновляем блюдо и проверяем
|
||||||
|
# dish["title"] = "updated_dish"
|
||||||
|
# code, rspn = await self.Dish.update(client, menu, submenu, dish)
|
||||||
|
# assert code == 200
|
||||||
|
# assert dish["title"] == rspn["title"]
|
||||||
|
# dish.update(rspn)
|
||||||
|
#
|
||||||
|
# # Удаляем подменю
|
||||||
|
# code = await self.Dish.delete(client, menu, submenu, dish)
|
||||||
|
# assert code == 200
|
||||||
|
#
|
||||||
|
# # Проверяем меню
|
||||||
|
# code, rspn = await self.Menu.get(client, menu)
|
||||||
|
# assert code == 200
|
||||||
|
# assert rspn["dishes_count"] == 0
|
||||||
|
#
|
||||||
|
# # Проверяем подменю на наличие блюд
|
||||||
|
# code, rspn = await self.Submenu.get(client, menu, submenu)
|
||||||
|
# assert code == 200
|
||||||
|
# assert rspn["dishes_count"] == 0
|
||||||
|
#
|
||||||
|
# # Проверяем удаленное блюдо
|
||||||
|
# code, rspn = await self.Dish.get(client, menu, submenu, dish)
|
||||||
|
# assert code == 404
|
||||||
|
#
|
||||||
|
# # удаляем сопутствующее
|
||||||
|
# await self.Submenu.delete(client, menu, submenu)
|
||||||
|
# await self.Menu.delete(client, menu)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class TestСontinuity:
|
||||||
|
# @pytest.mark.asyncio
|
||||||
|
# async def test_postman_continuity(self, client):
|
||||||
|
# # Создаем меню
|
||||||
|
# menu = {
|
||||||
|
# "title": "Menu",
|
||||||
|
# "description": "main menu",
|
||||||
|
# }
|
||||||
|
# code, rspn = await TestBaseCrud.Menu.write(client, menu)
|
||||||
|
# assert code == 201
|
||||||
|
# assert "id" in rspn.keys()
|
||||||
|
# menu.update(rspn)
|
||||||
|
#
|
||||||
|
# # Создаем подменю
|
||||||
|
# submenu = {
|
||||||
|
# "title": "Submenu",
|
||||||
|
# "description": "submenu",
|
||||||
|
# "parent_menu": menu["id"],
|
||||||
|
# }
|
||||||
|
# code, rspn = await TestBaseCrud.Submenu.write(client, menu, submenu)
|
||||||
|
# assert code == 201
|
||||||
|
# assert "id" in rspn.keys()
|
||||||
|
# submenu.update(rspn)
|
||||||
|
#
|
||||||
|
# # Добавляем блюдо1
|
||||||
|
# dish = {
|
||||||
|
# "title": "dish1",
|
||||||
|
# "description": "some dish1",
|
||||||
|
# "price": "13.50",
|
||||||
|
# "parent_submenu": submenu["id"],
|
||||||
|
# }
|
||||||
|
# code, rspn = await TestBaseCrud.Dish.write(client, menu, submenu, dish)
|
||||||
|
# assert code == 201
|
||||||
|
# assert "id" in rspn.keys()
|
||||||
|
# dish.update(rspn)
|
||||||
|
#
|
||||||
|
# # Добавляем блюдо2
|
||||||
|
# dish = {
|
||||||
|
# "title": "dish2",
|
||||||
|
# "description": "some dish2",
|
||||||
|
# "price": "12.50",
|
||||||
|
# "parent_submenu": submenu["id"],
|
||||||
|
# }
|
||||||
|
# code, rspn = await TestBaseCrud.Dish.write(client, menu, submenu, dish)
|
||||||
|
# assert code == 201
|
||||||
|
# assert "id" in rspn.keys()
|
||||||
|
# dish.update(rspn)
|
||||||
|
#
|
||||||
|
# # Просматриваем конкретное меню
|
||||||
|
# code, rspn = await TestBaseCrud.Menu.get(client, menu)
|
||||||
|
# assert code == 200
|
||||||
|
# assert "id" in rspn.keys()
|
||||||
|
# assert menu["id"] == rspn["id"]
|
||||||
|
# assert "submenus_count" in rspn.keys()
|
||||||
|
# assert rspn["submenus_count"] == 1
|
||||||
|
# assert "dishes_count" in rspn.keys()
|
||||||
|
# assert rspn["dishes_count"] == 2
|
||||||
|
#
|
||||||
|
# # Просматриваем конкретное подменю
|
||||||
|
# code, rspn = await TestBaseCrud.Submenu.get(client, menu, submenu)
|
||||||
|
# assert code == 200
|
||||||
|
# assert "id" in rspn.keys()
|
||||||
|
# assert "dishes_count" in rspn.keys()
|
||||||
|
# assert rspn["dishes_count"] == 2
|
||||||
|
#
|
||||||
|
# # Удаляем подменю
|
||||||
|
# code = await TestBaseCrud.Submenu.delete(client, menu, submenu)
|
||||||
|
# assert code == 200
|
||||||
|
#
|
||||||
|
# # Просматриваем список подменю
|
||||||
|
# code, rspn = await TestBaseCrud.Submenu.read_all(client, menu)
|
||||||
|
# assert code == 200
|
||||||
|
# assert rspn == []
|
||||||
|
#
|
||||||
|
# # Просматриваем список блюд
|
||||||
|
# code, rspn = await TestBaseCrud.Dish.read_all(client, menu, submenu)
|
||||||
|
# assert code == 200
|
||||||
|
# assert rspn == []
|
||||||
|
#
|
||||||
|
# # Просматриваем конкретное меню
|
||||||
|
# code, rspn = await TestBaseCrud.Menu.get(client, menu)
|
||||||
|
# assert code == 200
|
||||||
|
# assert "id" in rspn.keys()
|
||||||
|
# assert menu["id"] == rspn["id"]
|
||||||
|
# assert "submenus_count" in rspn.keys()
|
||||||
|
# assert rspn["submenus_count"] == 0
|
||||||
|
# assert "dishes_count" in rspn.keys()
|
||||||
|
# assert rspn["dishes_count"] == 0
|
||||||
|
#
|
||||||
|
# # Удаляем меню
|
||||||
|
# code = await TestBaseCrud.Menu.delete(client, menu)
|
||||||
|
# assert code == 200
|
||||||
|
#
|
||||||
|
# # Просматриваем все меню
|
||||||
|
# code, rspn = await TestBaseCrud.Menu.read_all(client)
|
||||||
|
# assert code == 200
|
||||||
|
# assert rspn == []
|
||||||
|
|
|
@ -1,179 +0,0 @@
|
||||||
from uuid import UUID
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
|
||||||
|
|
||||||
from fastfood.cruds.dish import DishCrud
|
|
||||||
from fastfood.cruds.menu import MenuCrud
|
|
||||||
from fastfood.cruds.submenu import SubMenuCrud
|
|
||||||
from fastfood.models import Dish, Menu, SubMenu
|
|
||||||
from fastfood.schemas import DishBase as dishschema
|
|
||||||
from fastfood.schemas import Menu as menuschema
|
|
||||||
from fastfood.schemas import MenuBase as menubaseschema
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_menu(asession: AsyncSession) -> None:
|
|
||||||
async with asession:
|
|
||||||
# Создаем меню
|
|
||||||
menu: Menu = Menu(title="SomeMenu", description="SomeDescription")
|
|
||||||
menu: Menu = await MenuCrud.create_menu_item(
|
|
||||||
menubaseschema.model_validate(menu),
|
|
||||||
asession,
|
|
||||||
)
|
|
||||||
menu_id: UUID = menu.id
|
|
||||||
|
|
||||||
# Получаем его же
|
|
||||||
req_menu: Menu | None = await MenuCrud.get_menu_item(menu_id, asession)
|
|
||||||
assert menu == req_menu
|
|
||||||
|
|
||||||
# Получаем все меню и проверяем
|
|
||||||
req_menus = await MenuCrud.get_menus(asession)
|
|
||||||
assert menu == req_menus.scalars().all()[0]
|
|
||||||
|
|
||||||
# Обновляем
|
|
||||||
menu.title = "updatedMenu"
|
|
||||||
await MenuCrud.update_menu_item(
|
|
||||||
menu.id, menuschema.model_validate(menu), asession
|
|
||||||
)
|
|
||||||
# И сверяем
|
|
||||||
req_menu = await MenuCrud.get_menu_item(menu_id, asession)
|
|
||||||
assert menu == req_menu
|
|
||||||
|
|
||||||
# Удаляем и проверяем
|
|
||||||
await MenuCrud.delete_menu_item(menu_id, asession)
|
|
||||||
req_menus = await MenuCrud.get_menus(asession)
|
|
||||||
assert req_menus.all() == []
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_submenu(asession: AsyncSession) -> None:
|
|
||||||
async with asession:
|
|
||||||
# Создаем меню напрямую
|
|
||||||
menu: Menu = Menu(title="SomeMenu", description="SomeDescription")
|
|
||||||
asession.add(menu)
|
|
||||||
await asession.commit()
|
|
||||||
await asession.refresh(menu)
|
|
||||||
menu_id: UUID = menu.id
|
|
||||||
|
|
||||||
# Создаем подменю
|
|
||||||
submenu: SubMenu = SubMenu(
|
|
||||||
title="submenu",
|
|
||||||
description="",
|
|
||||||
parent_menu=menu_id,
|
|
||||||
)
|
|
||||||
submenu = await SubMenuCrud.create_submenu_item(
|
|
||||||
menu_id,
|
|
||||||
menubaseschema.model_validate(submenu),
|
|
||||||
asession,
|
|
||||||
)
|
|
||||||
submenu_id = submenu.id
|
|
||||||
|
|
||||||
# Проверяем подменю
|
|
||||||
req_submenu = await SubMenuCrud.get_submenu_item(
|
|
||||||
menu_id,
|
|
||||||
submenu.id,
|
|
||||||
asession,
|
|
||||||
)
|
|
||||||
assert submenu == req_submenu
|
|
||||||
assert submenu.dishes_count == 0
|
|
||||||
|
|
||||||
# Обновляем меню
|
|
||||||
submenu.title = "UpdatedSubmenu"
|
|
||||||
req_submenu = await SubMenuCrud.update_submenu_item(
|
|
||||||
submenu_id,
|
|
||||||
menubaseschema.model_validate(submenu),
|
|
||||||
asession,
|
|
||||||
)
|
|
||||||
assert submenu == req_submenu.scalar_one_or_none()
|
|
||||||
|
|
||||||
menu = await MenuCrud.get_menu_item(menu_id, asession)
|
|
||||||
assert 1 == menu.submenus_count
|
|
||||||
|
|
||||||
# Удаляем полменю
|
|
||||||
await SubMenuCrud.delete_submenu_item(submenu_id, asession)
|
|
||||||
|
|
||||||
menu = await MenuCrud.get_menu_item(menu_id, asession)
|
|
||||||
assert 0 == menu.submenus_count
|
|
||||||
|
|
||||||
await MenuCrud.delete_menu_item(menu_id, asession)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_dish(asession: AsyncSession):
|
|
||||||
"""Not Implemented yet"""
|
|
||||||
async with asession:
|
|
||||||
# Создаем меню напрямую
|
|
||||||
menu = Menu(title="SomeMenu", description="SomeDescription")
|
|
||||||
asession.add(menu)
|
|
||||||
await asession.commit()
|
|
||||||
await asession.refresh(menu)
|
|
||||||
menu_id: UUID = menu.id
|
|
||||||
|
|
||||||
# Создаем подменю
|
|
||||||
submenu: SubMenu = SubMenu(
|
|
||||||
title="submenu",
|
|
||||||
description="",
|
|
||||||
parent_menu=menu_id,
|
|
||||||
)
|
|
||||||
asession.add(submenu)
|
|
||||||
await asession.commit()
|
|
||||||
await asession.refresh(submenu)
|
|
||||||
submenu_id = submenu.id
|
|
||||||
|
|
||||||
# Создаем блюдо
|
|
||||||
dish: Dish = Dish(
|
|
||||||
title="dish1",
|
|
||||||
description="dish number 1",
|
|
||||||
price="12.5",
|
|
||||||
parent_submenu=submenu_id,
|
|
||||||
)
|
|
||||||
dish = await DishCrud.create_dish_item(
|
|
||||||
submenu_id,
|
|
||||||
dishschema.model_validate(dish),
|
|
||||||
asession,
|
|
||||||
)
|
|
||||||
dish_id = dish.id
|
|
||||||
|
|
||||||
# Проверяем блюдо
|
|
||||||
req_dish = await DishCrud.get_dish_item(
|
|
||||||
dish_id,
|
|
||||||
asession,
|
|
||||||
)
|
|
||||||
assert dish == req_dish
|
|
||||||
|
|
||||||
menu = await MenuCrud.get_menu_item(menu_id, asession)
|
|
||||||
submenu = await SubMenuCrud.get_submenu_item(
|
|
||||||
menu_id,
|
|
||||||
submenu.id,
|
|
||||||
asession,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert menu.submenus_count == 1
|
|
||||||
assert menu.dishes_count == 1
|
|
||||||
assert submenu.dishes_count == 1
|
|
||||||
|
|
||||||
# Обновляем блюдо
|
|
||||||
dish.price = 177
|
|
||||||
req_dish = await DishCrud.update_dish_item(
|
|
||||||
dish_id,
|
|
||||||
dishschema.model_validate(dish),
|
|
||||||
asession,
|
|
||||||
)
|
|
||||||
assert dish == req_dish
|
|
||||||
|
|
||||||
# Удаляем длюдо
|
|
||||||
await DishCrud.delete_dish_item(dish_id, asession)
|
|
||||||
|
|
||||||
menu = await MenuCrud.get_menu_item(menu_id, asession)
|
|
||||||
submenu = await SubMenuCrud.get_submenu_item(
|
|
||||||
menu_id,
|
|
||||||
submenu.id,
|
|
||||||
asession,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert menu.dishes_count == 0
|
|
||||||
assert submenu.dishes_count == 0
|
|
||||||
|
|
||||||
await SubMenuCrud.delete_submenu_item(submenu_id, asession)
|
|
||||||
await MenuCrud.delete_menu_item(menu_id, asession)
|
|
Loading…
Reference in New Issue