develop
Сергей Ванюшкин 2024-02-02 08:04:02 +03:00
parent 7eefa8e5db
commit 58ecd82bb6
10 changed files with 450 additions and 476 deletions

View File

@ -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.menu import router as menu_router
@ -61,7 +63,7 @@ tags_metadata = [
]
def create_app() -> FastAPI:
def create_app(redis=None) -> FastAPI:
"""
Фабрика FastAPI.
"""

View File

@ -1,31 +1,35 @@
from typing import Annotated
from uuid import UUID
from fastapi import Depends
from sqlalchemy import delete, distinct, func, select, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import aliased
from fastfood import models, schemas
from fastfood.dbase import get_async_session
class MenuCrud:
@staticmethod
async def get_menus(session: AsyncSession):
async with session:
query = select(models.Menu)
menus = await session.execute(query)
return menus
def __init__(self, session: AsyncSession = Depends(get_async_session)):
self.db = session
@staticmethod
async def create_menu_item(menu: schemas.MenuBase, session: AsyncSession):
async with session:
async def get_menus(self):
query = select(models.Menu)
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())
session.add(new_menu)
await session.commit()
await session.refresh(new_menu)
self.db.add(new_menu)
await self.db.commit()
await self.db.refresh(new_menu)
return new_menu
@staticmethod
async def get_menu_item(menu_id: UUID, session: AsyncSession):
async def get_menu_item(
menu_id: UUID, session: AsyncSession = Depends(get_async_session)
):
async with session:
m = aliased(models.Menu)
s = aliased(models.SubMenu)
@ -52,7 +56,7 @@ class MenuCrud:
async def update_menu_item(
menu_id: UUID,
menu: schemas.MenuBase,
session: AsyncSession,
session: AsyncSession = Depends(get_async_session),
):
async with session:
query = (
@ -67,7 +71,9 @@ class MenuCrud:
return updated_menu
@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:
query = delete(models.Menu).where(models.Menu.id == menu_id)
await session.execute(query)

View File

@ -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)

View File

@ -1,12 +1,13 @@
from typing import List, Optional
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from fastfood import schemas
from fastfood.cruds import crud
from fastfood.dbase import get_async_session
from fastfood.service.menu import MenuService
router = APIRouter(
prefix="/api/v1/menus",
@ -15,21 +16,22 @@ router = APIRouter(
@router.get("/", response_model=Optional[List[schemas.Menu]])
async def get_menus(session: AsyncSession = Depends(get_async_session)):
result = await crud.get_menus(session=session)
return result.scalars().all()
async def get_menus(
menu: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
result = await menu.read_menus()
return result
@router.post("/", status_code=201, response_model=schemas.Menu)
async def add_menu(
menu: schemas.MenuBase,
session: AsyncSession = Depends(get_async_session),
responce: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
result = await crud.create_menu_item(
menu=menu,
session=session,
)
return result
rspn = await responce.create_menu(menu)
return rspn
@router.get("/{menu_id}", response_model=schemas.MenuRead)

65
fastfood/service/menu.py Normal file
View File

@ -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)

20
poetry.lock generated
View File

@ -670,6 +670,24 @@ files = [
[package.extras]
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]]
name = "sniffio"
version = "1.3.0"
@ -829,4 +847,4 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)",
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "5bbc3cad36f6f40d10cb848918426b640f9e703bc2c6b22b5b8fe381a6251ded"
content-hash = "8da16a83882a9b35a5a05441a33e2296b04a5f664dbb090fec0f384c709fb7ef"

View File

@ -14,6 +14,7 @@ asyncpg = "^0.29.0"
pydantic-settings = "^2.1.0"
email-validator = "^2.1.0.post1"
pytest-asyncio = "^0.23.3"
redis = "^5.0.1"
[tool.poetry.group.dev.dependencies]

View File

@ -53,16 +53,10 @@ def app(event_loop) -> Generator[FastAPI, None, None]:
yield app
@pytest_asyncio.fixture(scope="function")
@pytest_asyncio.fixture()
async def client(app) -> AsyncGenerator[AsyncClient, None]:
async with AsyncClient(
app=app,
base_url="http://localhost:8000/api/v1/menus",
) as 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

View File

@ -7,9 +7,10 @@ from httpx import AsyncClient, Response
class TestBaseCrud:
class Menu:
@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()
@staticmethod
@ -144,264 +145,269 @@ class TestBaseCrud:
)
return response.status_code
@pytest.mark.asyncio
async def test_menu_crud(self, client: AsyncClient) -> None:
@pytest.mark.asyncio
async def test_menu_crud(client) -> None:
"""Тестирование функций меню"""
code, rspn = await self.Menu.read_all(client)
code, rspn = await TestBaseCrud.Menu.read_all(client)
assert code == 200
data = {"title": "Menu", "description": None}
code, rspn = await self.Menu.write(client, data)
code, rspn = await TestBaseCrud.Menu.write(client, data)
assert code == 201
assert rspn["title"] == "Menu"
assert rspn["description"] is None
code, menu = await self.Menu.get(client, {"id": rspn.get("id")})
assert code == 200
assert menu["title"] == rspn["title"]
upd_data = {
"id": rspn.get("id"),
"title": "upd Menu",
"description": "",
}
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:
@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
# Просматриваем все меню
data = {"title": "Menu1", "description": "11"}
code, rspn = await TestBaseCrud.Menu.write(client, data)
code, rspn = await TestBaseCrud.Menu.read_all(client)
assert code == 200
assert rspn == []
# code, menu = await self.Menu.get(client, {"id": rspn.get("id")})
# assert code == 200
# assert menu["title"] == rspn["title"]
#
# upd_data = {
# "id": rspn.get("id"),
# "title": "upd Menu",
# "description": "",
# }
# 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:
# @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 == []

View File

@ -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)