From ed11efa704f7d9c2d4295806292a8bd8407d6fe8 Mon Sep 17 00:00:00 2001 From: pi3c Date: Mon, 22 Jan 2024 01:28:32 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BD=D0=B5=D0=B1=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D1=88=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example.env | 5 + fastfood/app.py | 89 +- fastfood/crud.py | 185 - fastfood/cruds/__init__.py | 18 + fastfood/cruds/dish.py | 58 + fastfood/cruds/menu.py | 67 + fastfood/cruds/submenu.py | 68 + fastfood/routers/__init__.py | 0 fastfood/routers/dish.py | 76 + fastfood/routers/menu.py | 64 + fastfood/routers/submenu.py | 73 + fastfood/routes.py | 183 - fastfood/schemas.py | 4 +- fastfood/utils.py | 2 +- manage.py | 20 +- poetry.lock | 37 +- .../menu app.postman_collection.json | 3890 +++++++++++++++++ .../menu app.postman_environment.json | 93 + pyproject.toml | 1 + 19 files changed, 4543 insertions(+), 390 deletions(-) create mode 100644 example.env delete mode 100644 fastfood/crud.py create mode 100644 fastfood/cruds/__init__.py create mode 100644 fastfood/cruds/dish.py create mode 100644 fastfood/cruds/menu.py create mode 100644 fastfood/cruds/submenu.py create mode 100644 fastfood/routers/__init__.py create mode 100644 fastfood/routers/dish.py create mode 100644 fastfood/routers/menu.py create mode 100644 fastfood/routers/submenu.py delete mode 100644 fastfood/routes.py create mode 100644 postman_scripts/menu app.postman_collection.json create mode 100644 postman_scripts/menu app.postman_environment.json diff --git a/example.env b/example.env new file mode 100644 index 0000000..81ce7a8 --- /dev/null +++ b/example.env @@ -0,0 +1,5 @@ +DB_HOST=localhost +DB_PORT=5432 +DB_USER=postgres +DB_PASS=postgres +DB_NAME=postgres diff --git a/fastfood/app.py b/fastfood/app.py index 9991a58..55081a7 100644 --- a/fastfood/app.py +++ b/fastfood/app.py @@ -1,20 +1,91 @@ from fastapi import FastAPI -from fastfood.routes import router +from fastfood.routers.menu import router as menu_router +from fastfood.routers.submenu import router as submenu_router +from fastfood.routers.dish import router as dish_router -async def generate_test_data(): - """ - Создание БД и наполнение ее данными - """ - pass +description = """ +# 🔥🔥🔥Fastfood-API поможет тебе подкрепиться 🔥🔥🔥 + +### У нас есть Menu. Ты можеш выбрать блюда из кухни, которая тебе нравится + +## Menu + +Ты можешь **add menu**. + +Ты можешь **read menu**. + +Ты можешь **patch menu**. + +Ты можешь **delete menu**. + +### У нас есть в SubMenu, где ты сможешь найти +десерты/напитки/супчики/прочие вкусности + +# SubMenu + +Ты можешь **add submenu into menu**. + +Ты можешь **read submenu**. + +Ты можешь **patch submenu**. + +Ты можешь **delete menu**. + +### У нас есть в Dish, где ты сможешь найти блюдо по вкусу + +# Dish + +Ты можешь **add dish into submenu**. + +Ты можешь **read dish**. + +Ты можешь **patch dish**. + +Ты можешь **delete dish**. + +## Приятного аппетита +""" + + +tags_metadata = [ + { + "name": "menu", + "description": "Операции с меню.", + }, + { + "name": "submenu", + "description": "Подменю и работа с ним", + }, + { + "name": "dish", + "description": "Блюда и работа с ними" + }, +] def create_app(): """ - Создание экземпляра приложения FastAPI и врзврат его + Фабрика FastAPI. """ - app = FastAPI() - app.include_router(router) + app = FastAPI( + title="Fastfood-API", + description=description, + version="0.0.1", + contact={ + "name": "Sergey Vanyushkin", + "url": "http://pi3c.ru", + "email": "pi3c@yandex.ru", + }, + license_info={ + "name": "MIT license", + "url": "https://mit-license.org/", + }, + openapi_tags=tags_metadata, + ) + app.include_router(menu_router) + app.include_router(submenu_router) + app.include_router(dish_router) return app diff --git a/fastfood/crud.py b/fastfood/crud.py deleted file mode 100644 index 282e2c9..0000000 --- a/fastfood/crud.py +++ /dev/null @@ -1,185 +0,0 @@ -from re import sub -from uuid import UUID -from sqlalchemy import delete, func, select, update -from sqlalchemy.ext.asyncio import AsyncSession - -from fastfood import models, schemas -from fastfood.dbase import async_engine - - -async def create_db_and_tables(): - async with async_engine.begin() as conn: - await conn.run_sync(models.Base.metadata.drop_all) - await conn.run_sync(models.Base.metadata.create_all) - - -class Crud: - @staticmethod - async def get_menus(session: AsyncSession): - async with session: - query = select(models.Menu) - result = await session.execute(query) - return result.scalars().all() - - @staticmethod - async def create_menu_item(menu: schemas.MenuBase, session: AsyncSession): - async with 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: - query = select(models.Menu).where(models.Menu.id == menu_id) - menu = await session.execute(query) - menu = menu.scalars().one_or_none() - if menu is None: - return None - submenu_query = select(func.count(models.SubMenu.id).label("counter")).filter(models.SubMenu.parent_menu == menu_id) - counter = await session.execute(submenu_query) - - dish_query = ( - select(func.count(models.Dish.id)) - .join(models.SubMenu) - .filter(models.Dish.parent_submenu == models.SubMenu.id) - .filter(models.SubMenu.parent_menu == menu_id) - ) - dishes = await session.execute(dish_query) - menu.submenus_count = counter.scalars().one_or_none() - menu.dishes_count = dishes.scalars().one_or_none() - return menu - - @staticmethod - async def update_menu_item(menu_id: UUID, - menu: schemas.MenuBase, - session: AsyncSession, - ): - async with session: - query = update(models.Menu).where(models.Menu.id == menu_id).values(**menu.model_dump()) - await session.execute(query) - await session.commit() - qr = select(models.Menu).where(models.Menu.id == menu_id) - updated_menu = await session.execute(qr) - return updated_menu.scalars().one() - - @staticmethod - async def delete_menu_item(menu_id: UUID, session: AsyncSession): - async with session: - query = delete(models.Menu).where(models.Menu.id == menu_id) - await session.execute(query) - await session.commit() - - @staticmethod - async def get_submenus(menu_id: UUID, session: AsyncSession): - async with session: - query = select(models.SubMenu).where(models.SubMenu.parent_menu == menu_id) - submenus = await session.execute(query) - return submenus.scalars().all() - - @staticmethod - async def create_submenu_item( - menu_id: UUID, submenu: schemas.MenuBase, session: AsyncSession, - ): - async with session: - new_submenu = models.SubMenu(**submenu.model_dump()) - new_submenu.parent_menu = menu_id - session.add(new_submenu) - await session.flush() - await session.commit() - return new_submenu - - @staticmethod - async def get_submenu_item( - menu_id: UUID, submenu_id: UUID, session: AsyncSession, - ): - async with session: - query = select(models.SubMenu).where(models.SubMenu.id == submenu_id) - submenu = await session.execute(query) - submenu = submenu.scalars().one_or_none() - if submenu is None: - return None - - dish_query = ( - select(func.count(models.Dish.id)) - .join(models.SubMenu) - .filter(models.Dish.parent_submenu == models.SubMenu.id) - ) - dishes = await session.execute(dish_query) - submenu.dishes_count = dishes.scalars().one_or_none() - - return submenu - - @staticmethod - async def update_submenu_item( - submenu_id: UUID, - submenu: schemas.MenuBase, - session: AsyncSession, - ): - async with session: - query = update(models.SubMenu).where(models.SubMenu.id == submenu_id).values(**submenu.model_dump()) - await session.execute(query) - await session.commit() - qr = select(models.SubMenu).where(models.SubMenu.id == submenu_id) - updated_submenu = await session.execute(qr) - return updated_submenu.scalars().one() - - @staticmethod - async def delete_submenu_item(submenu_id: UUID, session: AsyncSession): - async with session: - query = delete(models.SubMenu).where(models.SubMenu.id == submenu_id) - await session.execute(query) - await session.commit() - - @staticmethod - async def get_dishes(submenu_id: UUID, session: AsyncSession): - async with session: - query = select(models.Dish).where(models.Dish.parent_submenu == submenu_id) - dishes = await session.execute(query) - return dishes.scalars().all() - - @staticmethod - async def create_dish_item( - submenu_id: UUID, dish: schemas.DishBase, session: AsyncSession, - ): - async with session: - new_dish = models.Dish(**dish.model_dump()) - new_dish.parent_submenu = submenu_id - session.add(new_dish) - await session.flush() - await session.commit() - return new_dish - - @staticmethod - async def get_dish_item( - dish_id: UUID, session: AsyncSession, - ): - async with session: - query = select(models.Dish).where(models.Dish.id == dish_id) - submenu = await session.execute(query) - return submenu.scalars().one_or_none() - - @staticmethod - async def update_dish_item( - dish_id: UUID, - dish: schemas.DishBase, - session: AsyncSession, - ): - async with session: - query = update(models.Dish).where(models.Dish.id == dish_id).values(**dish.model_dump()) - await session.execute(query) - await session.commit() - qr = select(models.Dish).where(models.Dish.id == dish_id) - updated_submenu = await session.execute(qr) - return updated_submenu.scalars().one() - - @staticmethod - async def delete_dish_item(dish_id: UUID, session: AsyncSession): - async with session: - query = delete(models.Dish).where(models.Dish.id == dish_id) - await session.execute(query) - await session.commit() - - diff --git a/fastfood/cruds/__init__.py b/fastfood/cruds/__init__.py new file mode 100644 index 0000000..1af1f3e --- /dev/null +++ b/fastfood/cruds/__init__.py @@ -0,0 +1,18 @@ +from fastfood import models +from fastfood.dbase import async_engine +from .menu import MenuCrud +from .submenu import SubMenuCrud +from .dish import DishCrud + + +async def create_db_and_tables(): + async with async_engine.begin() as conn: + await conn.run_sync(models.Base.metadata.drop_all) + await conn.run_sync(models.Base.metadata.create_all) + + +class Crud(MenuCrud, SubMenuCrud, DishCrud): + pass + + +crud = Crud() diff --git a/fastfood/cruds/dish.py b/fastfood/cruds/dish.py new file mode 100644 index 0000000..38cf973 --- /dev/null +++ b/fastfood/cruds/dish.py @@ -0,0 +1,58 @@ +from uuid import UUID +from sqlalchemy import delete, select, update +from sqlalchemy.ext.asyncio import AsyncSession + +from fastfood import models, schemas + + +class DishCrud: + @staticmethod + async def get_dishes(submenu_id: UUID, session: AsyncSession): + async with session: + query = select(models.Dish).where(models.Dish.parent_submenu == submenu_id) + dishes = await session.execute(query) + return dishes.scalars().all() + + @staticmethod + async def create_dish_item( + submenu_id: UUID, dish: schemas.DishBase, session: AsyncSession, + ): + async with session: + new_dish = models.Dish(**dish.model_dump()) + new_dish.parent_submenu = submenu_id + session.add(new_dish) + await session.flush() + await session.commit() + return new_dish + + @staticmethod + async def get_dish_item( + dish_id: UUID, session: AsyncSession, + ): + async with session: + query = select(models.Dish).where(models.Dish.id == dish_id) + submenu = await session.execute(query) + return submenu.scalars().one_or_none() + + @staticmethod + async def update_dish_item( + dish_id: UUID, + dish: schemas.DishBase, + session: AsyncSession, + ): + async with session: + query = update(models.Dish).where(models.Dish.id == dish_id).values(**dish.model_dump()) + await session.execute(query) + await session.commit() + qr = select(models.Dish).where(models.Dish.id == dish_id) + updated_submenu = await session.execute(qr) + return updated_submenu.scalars().one() + + @staticmethod + async def delete_dish_item(dish_id: UUID, session: AsyncSession): + async with session: + query = delete(models.Dish).where(models.Dish.id == dish_id) + await session.execute(query) + await session.commit() + + diff --git a/fastfood/cruds/menu.py b/fastfood/cruds/menu.py new file mode 100644 index 0000000..3770c2a --- /dev/null +++ b/fastfood/cruds/menu.py @@ -0,0 +1,67 @@ +from uuid import UUID +from sqlalchemy import delete, func, select, update +from sqlalchemy.ext.asyncio import AsyncSession + +from fastfood import models, schemas + + +class MenuCrud: + @staticmethod + async def get_menus(session: AsyncSession): + async with session: + query = select(models.Menu) + result = await session.execute(query) + return result.scalars().all() + + @staticmethod + async def create_menu_item(menu: schemas.MenuBase, session: AsyncSession): + async with 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: + query = select(models.Menu).where(models.Menu.id == menu_id) + menu = await session.execute(query) + menu = menu.scalars().one_or_none() + if menu is None: + return None + submenu_query = select(func.count(models.SubMenu.id).label("counter")).filter(models.SubMenu.parent_menu == menu_id) + counter = await session.execute(submenu_query) + + dish_query = ( + select(func.count(models.Dish.id)) + .join(models.SubMenu) + .filter(models.Dish.parent_submenu == models.SubMenu.id) + .filter(models.SubMenu.parent_menu == menu_id) + ) + dishes = await session.execute(dish_query) + menu.submenus_count = counter.scalars().one_or_none() + menu.dishes_count = dishes.scalars().one_or_none() + return menu + + @staticmethod + async def update_menu_item(menu_id: UUID, + menu: schemas.MenuBase, + session: AsyncSession, + ): + async with session: + query = update(models.Menu).where(models.Menu.id == menu_id).values(**menu.model_dump()) + await session.execute(query) + await session.commit() + qr = select(models.Menu).where(models.Menu.id == menu_id) + updated_menu = await session.execute(qr) + return updated_menu.scalars().one() + + @staticmethod + async def delete_menu_item(menu_id: UUID, session: AsyncSession): + async with session: + query = delete(models.Menu).where(models.Menu.id == menu_id) + await session.execute(query) + await session.commit() + + diff --git a/fastfood/cruds/submenu.py b/fastfood/cruds/submenu.py new file mode 100644 index 0000000..9bdd3cd --- /dev/null +++ b/fastfood/cruds/submenu.py @@ -0,0 +1,68 @@ +from uuid import UUID +from sqlalchemy import delete, func, select, update +from sqlalchemy.ext.asyncio import AsyncSession + +from fastfood import models, schemas + + +class SubMenuCrud: + @staticmethod + async def get_submenus(menu_id: UUID, session: AsyncSession): + async with session: + query = select(models.SubMenu).where(models.SubMenu.parent_menu == menu_id) + submenus = await session.execute(query) + return submenus.scalars().all() + + @staticmethod + async def create_submenu_item( + menu_id: UUID, submenu: schemas.MenuBase, session: AsyncSession, + ): + async with session: + new_submenu = models.SubMenu(**submenu.model_dump()) + new_submenu.parent_menu = menu_id + session.add(new_submenu) + await session.flush() + await session.commit() + return new_submenu + + @staticmethod + async def get_submenu_item( + menu_id: UUID, submenu_id: UUID, session: AsyncSession, + ): + async with session: + query = select(models.SubMenu).where(models.SubMenu.id == submenu_id) + submenu = await session.execute(query) + submenu = submenu.scalars().one_or_none() + if submenu is None: + return None + + dish_query = ( + select(func.count(models.Dish.id)) + .join(models.SubMenu) + .filter(models.Dish.parent_submenu == models.SubMenu.id) + ) + dishes = await session.execute(dish_query) + submenu.dishes_count = dishes.scalars().one_or_none() + + return submenu + + @staticmethod + async def update_submenu_item( + submenu_id: UUID, + submenu: schemas.MenuBase, + session: AsyncSession, + ): + async with session: + query = update(models.SubMenu).where(models.SubMenu.id == submenu_id).values(**submenu.model_dump()) + await session.execute(query) + await session.commit() + qr = select(models.SubMenu).where(models.SubMenu.id == submenu_id) + updated_submenu = await session.execute(qr) + return updated_submenu.scalars().one() + + @staticmethod + async def delete_submenu_item(submenu_id: UUID, session: AsyncSession): + async with session: + query = delete(models.SubMenu).where(models.SubMenu.id == submenu_id) + await session.execute(query) + await session.commit() diff --git a/fastfood/routers/__init__.py b/fastfood/routers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fastfood/routers/dish.py b/fastfood/routers/dish.py new file mode 100644 index 0000000..c034c9c --- /dev/null +++ b/fastfood/routers/dish.py @@ -0,0 +1,76 @@ +from typing import List, Optional +from fastapi import APIRouter, Depends, HTTPException +from uuid import UUID +from sqlalchemy.ext.asyncio import AsyncSession + +from fastfood import schemas +from fastfood.utils import price_converter +from fastfood.cruds import crud +from fastfood.dbase import get_async_session + + +router = APIRouter( + prefix="/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes", + tags=["dish"], +) + + +@router.get("/") +async def get_dishes( + menu_id: UUID, + submenu_id: UUID, + session: AsyncSession = Depends(get_async_session) +): + result = await crud.get_dishes(submenu_id=submenu_id, session=session) + return result + + +@router.post("/", status_code=201) +async def create_dish( + menu_id: UUID, + submenu_id: UUID, + dish: schemas.DishBase, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.create_dish_item( + submenu_id=submenu_id, + dish=dish, + session=session, + ) + return price_converter(result) + + +@router.get("/{dish_id}") +async def get_dish( + menu_id: UUID, + submenu_id: UUID, + dish_id: UUID, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.get_dish_item( + dish_id=dish_id, session=session, + ) + if not result: + raise HTTPException(status_code=404, detail="dish not found") + return price_converter(result) + + +@router.patch( + "/{dish_id}" +) +async def update_dish( + menu_id: UUID, + submenu_id: UUID, + dish_id: UUID, + dish: schemas.DishBase, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.update_dish_item( + dish_id=dish_id, dish=dish, session=session, + ) + return price_converter(result) + + +@router.delete("/{dish_id}") +async def delete_dish(menu_id: UUID, submenu_id: UUID, dish_id: UUID, session: AsyncSession = Depends(get_async_session)): + await crud.delete_dish_item(dish_id=dish_id, session=session) diff --git a/fastfood/routers/menu.py b/fastfood/routers/menu.py new file mode 100644 index 0000000..8ccfec9 --- /dev/null +++ b/fastfood/routers/menu.py @@ -0,0 +1,64 @@ +from typing import List, Optional +from fastapi import APIRouter, Depends, HTTPException +from uuid import UUID +from sqlalchemy.ext.asyncio import AsyncSession + +from fastfood import schemas +from fastfood.cruds import crud +from fastfood.dbase import get_async_session + + +router = APIRouter( + prefix="/api/v1/menus", + tags=["menu"], +) + + +@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 + + +@router.post("/", status_code=201, response_model=schemas.Menu) +async def add_menu( + menu: schemas.MenuBase, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.create_menu_item( + menu=menu, + session=session, + ) + return result + + +@router.get("/{menu_id}", response_model=schemas.MenuRead) +async def get_menu( + menu_id: UUID, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.get_menu_item(menu_id=menu_id, session=session) + if not result: + raise HTTPException(status_code=404, detail="menu not found") + return result + + +@router.patch("/{menu_id}", response_model=schemas.MenuBase) +async def update_menu( + menu_id: UUID, + menu: schemas.MenuBase, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.update_menu_item( + menu_id=menu_id, menu=menu, session=session, + ) + return result + + +@router.delete("/{menu_id}") +async def delete_menu( + menu_id: UUID, session: AsyncSession = Depends(get_async_session), +): + await crud.delete_menu_item(menu_id=menu_id, session=session) + + diff --git a/fastfood/routers/submenu.py b/fastfood/routers/submenu.py new file mode 100644 index 0000000..1afe313 --- /dev/null +++ b/fastfood/routers/submenu.py @@ -0,0 +1,73 @@ +from fastapi import APIRouter, Depends, HTTPException +from uuid import UUID +from sqlalchemy.ext.asyncio import AsyncSession + +from fastfood import schemas +from fastfood.cruds import crud +from fastfood.dbase import get_async_session + + +router = APIRouter( + prefix="/api/v1/menus/{menu_id}/submenus", + tags=["submenu"], +) + + +@router.get("/") +async def get_submenus( + menu_id: UUID, + session: AsyncSession = Depends(get_async_session) +): + result = await crud.get_submenus(menu_id=menu_id, session=session) + return result + + +@router.post("/", status_code=201) +async def create_submenu_item( + menu_id: UUID, + submenu: schemas.MenuBase, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.create_submenu_item( + menu_id=menu_id, + submenu=submenu, + session=session, + ) + return result + + +@router.get("/{submenu_id}", response_model=schemas.SubMenuRead) +async def get_submenu( + menu_id: UUID, + submenu_id: UUID, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.get_submenu_item( + menu_id=menu_id, submenu_id=submenu_id, session=session, + ) + if not result: + raise HTTPException(status_code=404, detail="submenu not found") + return result + + +@router.patch( + "/{submenu_id}", + response_model=schemas.MenuBase, +) +async def update_submenu( + menu_id: UUID, + submenu_id: UUID, + submenu: schemas.MenuBase, + session: AsyncSession = Depends(get_async_session), +): + result = await crud.update_submenu_item( + submenu_id=submenu_id, submenu=submenu, session=session, + ) + return result + + +@router.delete("/{submenu_id}") +async def delete_submenu(menu_id: UUID, submenu_id: UUID, session: AsyncSession = Depends(get_async_session)): + await crud.delete_submenu_item(submenu_id=submenu_id, session=session) + + diff --git a/fastfood/routes.py b/fastfood/routes.py deleted file mode 100644 index 736d889..0000000 --- a/fastfood/routes.py +++ /dev/null @@ -1,183 +0,0 @@ -from typing import List, Optional -from fastapi import APIRouter, Depends, HTTPException -from uuid import UUID -from sqlalchemy.ext.asyncio import AsyncSession - -from fastfood import schemas -from fastfood.crud import Crud as crud -from fastfood.dbase import get_async_session - - -router = APIRouter() - - -def price_converter(dish: dict) -> dict: - dish.price = str(dish.price) - return dish - - -@router.get("/api/v1/menus", 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 - - -@router.post("/api/v1/menus", status_code=201, response_model=schemas.Menu) -async def add_menu( - menu: schemas.MenuBase, - session: AsyncSession = Depends(get_async_session), -): - result = await crud.create_menu_item( - menu=menu, - session=session, - ) - return result - - -@router.get("/api/v1/menus/{menu_id}", response_model=schemas.MenuRead) -async def get_menu( - menu_id: UUID, - session: AsyncSession = Depends(get_async_session), -): - result = await crud.get_menu_item(menu_id=menu_id, session=session) - if not result: - raise HTTPException(status_code=404, detail="menu not found") - return result - - -@router.patch("/api/v1/menus/{menu_id}", response_model=schemas.MenuBase) -async def update_menu( - menu_id: UUID, - menu: schemas.MenuBase, - session: AsyncSession = Depends(get_async_session), -): - result = await crud.update_menu_item( - menu_id=menu_id, menu=menu, session=session, - ) - return result - - -@router.delete("/api/v1/menus/{menu_id}") -async def delete_menu( - menu_id: UUID, session: AsyncSession = Depends(get_async_session), -): - await crud.delete_menu_item(menu_id=menu_id, session=session) - - -@router.get("/api/v1/menus/{menu_id}/submenus") -async def get_submenus( - menu_id: UUID, - session: AsyncSession = Depends(get_async_session) -): - result = await crud.get_submenus(menu_id=menu_id, session=session) - return result - - -@router.post("/api/v1/menus/{menu_id}/submenus", status_code=201) -async def create_submenu_item( - menu_id: UUID, - submenu: schemas.MenuBase, - session: AsyncSession = Depends(get_async_session), -): - result = await crud.create_submenu_item( - menu_id=menu_id, - submenu=submenu, - session=session, - ) - return result - - -@router.get("/api/v1/menus/{menu_id}/submenus/{submenu_id}", response_model=schemas.SubMenuRead) -async def get_submenu( - menu_id: UUID, - submenu_id: UUID, - session: AsyncSession = Depends(get_async_session), -): - result = await crud.get_submenu_item( - menu_id=menu_id, submenu_id=submenu_id, session=session, - ) - if not result: - raise HTTPException(status_code=404, detail="submenu not found") - return result - - -@router.patch( - "/api/v1/menus/{menu_id}/submenus/{submenu_id}", - response_model=schemas.MenuBase, -) -async def update_submenu( - menu_id: UUID, - submenu_id: UUID, - submenu: schemas.MenuBase, - session: AsyncSession = Depends(get_async_session), -): - result = await crud.update_submenu_item( - submenu_id=submenu_id, submenu=submenu, session=session, - ) - return result - - -@router.delete("/api/v1/menus/{menu_id}/submenus/{submenu_id}") -async def delete_submenu(menu_id: UUID, submenu_id: UUID, session: AsyncSession = Depends(get_async_session)): - await crud.delete_submenu_item(submenu_id=submenu_id, session=session) - - -@router.get("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes") -async def get_dishes( - menu_id: UUID, - submenu_id: UUID, - session: AsyncSession = Depends(get_async_session) -): - result = await crud.get_dishes(submenu_id=submenu_id, session=session) - return result - - -@router.post("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes", status_code=201) -async def create_dish( - menu_id: UUID, - submenu_id: UUID, - dish: schemas.DishBase, - session: AsyncSession = Depends(get_async_session), -): - result = await crud.create_dish_item( - submenu_id=submenu_id, - dish=dish, - session=session, - ) - return price_converter(result) - - -@router.get("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}") -async def get_dish( - menu_id: UUID, - submenu_id: UUID, - dish_id: UUID, - session: AsyncSession = Depends(get_async_session), -): - result = await crud.get_dish_item( - dish_id=dish_id, session=session, - ) - if not result: - raise HTTPException(status_code=404, detail="dish not found") - return price_converter(result) - - -@router.patch( - "/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}" -) -async def update_dish( - menu_id: UUID, - submenu_id: UUID, - dish_id: UUID, - dish: schemas.DishBase, - session: AsyncSession = Depends(get_async_session), -): - result = await crud.update_dish_item( - dish_id=dish_id, dish=dish, session=session, - ) - return price_converter(result) - - -@router.delete("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}") -async def delete_dish(menu_id: UUID, submenu_id: UUID, dish_id: UUID, session: AsyncSession = Depends(get_async_session)): - await crud.delete_dish_item(dish_id=dish_id, session=session) diff --git a/fastfood/schemas.py b/fastfood/schemas.py index a6398af..8fab6a1 100644 --- a/fastfood/schemas.py +++ b/fastfood/schemas.py @@ -1,5 +1,4 @@ -from decimal import Decimal -from typing import List, Optional +from typing import Optional from uuid import UUID from pydantic import BaseModel @@ -21,6 +20,7 @@ class MenuRead(Menu): submenus_count: int dishes_count: int + class SubMenuRead(Menu): dishes_count: int diff --git a/fastfood/utils.py b/fastfood/utils.py index cd49c8a..8cb26a0 100644 --- a/fastfood/utils.py +++ b/fastfood/utils.py @@ -1,4 +1,4 @@ -def convert_price(dish: dict): +def price_converter(dish: dict) -> dict: dish.price = str(dish.price) return dish diff --git a/manage.py b/manage.py index a33377b..fabcab9 100644 --- a/manage.py +++ b/manage.py @@ -3,12 +3,12 @@ import sys import uvicorn -from fastfood.crud import create_db_and_tables +from fastfood.cruds import create_db_and_tables def run_app(): """ - Запуск + Запуск FastAPI """ uvicorn.run( app="fastfood.app:create_app", @@ -17,13 +17,15 @@ def run_app(): ) -if __name__ == "__main__": - if "filldb" in sys.argv: - """Наполнение БД демонстрационными данными""" - pass +async def recreate(): + """Удаление и создание таблиц в базе данных для тестирования""" + await create_db_and_tables() + +if __name__ == "__main__": if "--run-server" in sys.argv: - async def create(): - await create_db_and_tables() - asyncio.run(create()) + run_app() + + if "--run-test-server" in sys.argv: + asyncio.run(recreate()) run_app() diff --git a/poetry.lock b/poetry.lock index 30a4731..5c46756 100644 --- a/poetry.lock +++ b/poetry.lock @@ -126,6 +126,41 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "dnspython" +version = "2.5.0" +description = "DNS toolkit" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dnspython-2.5.0-py3-none-any.whl", hash = "sha256:6facdf76b73c742ccf2d07add296f178e629da60be23ce4b0a9c927b1e02c3a6"}, + {file = "dnspython-2.5.0.tar.gz", hash = "sha256:a0034815a59ba9ae888946be7ccca8f7c157b286f8455b379c692efb51022a15"}, +] + +[package.extras] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=5.0.3)", "mypy (>=1.0.1)", "pylint (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0.0)", "sphinx (>=7.0.0)", "twine (>=4.0.0)", "wheel (>=0.41.0)"] +dnssec = ["cryptography (>=41)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=0.17.3)", "httpx (>=0.25.1)"] +doq = ["aioquic (>=0.9.20)"] +idna = ["idna (>=2.1)"] +trio = ["trio (>=0.14)"] +wmi = ["wmi (>=1.5.1)"] + +[[package]] +name = "email-validator" +version = "2.1.0.post1" +description = "A robust email address syntax and deliverability validation library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "email_validator-2.1.0.post1-py3-none-any.whl", hash = "sha256:c973053efbeddfef924dc0bd93f6e77a1ea7ee0fce935aea7103c7a3d6d2d637"}, + {file = "email_validator-2.1.0.post1.tar.gz", hash = "sha256:a4b0bd1cf55f073b924258d19321b1f3aa74b4b5a71a42c305575dba920e1a44"}, +] + +[package.dependencies] +dnspython = ">=2.0.0" +idna = ">=2.0.0" + [[package]] name = "exceptiongroup" version = "1.2.0" @@ -716,4 +751,4 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "f2b347c9b370a1cf7c178196c0a8298d34de656dc914e03b2cdec5a67384fd03" +content-hash = "84fe024aa665ddad3077ca7e73054d1a5cb019a9a3e78af917922433ff4b3d8c" diff --git a/postman_scripts/menu app.postman_collection.json b/postman_scripts/menu app.postman_collection.json new file mode 100644 index 0000000..f60b345 --- /dev/null +++ b/postman_scripts/menu app.postman_collection.json @@ -0,0 +1,3890 @@ +{ + "info": { + "_postman_id": "a3191130-ff05-45b0-81c9-574532f3996f", + "name": "menu app", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "24396936" + }, + "item": [ + { + "name": "Тестовый сценарий", + "item": [ + { + "name": "CRUD для Меню", + "item": [ + { + "name": "Просматривает список меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + }, + { + "name": "Создает меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_menu_id', responseJSON.id);\r", + "postman.setEnvironmentVariable('target_menu_title', responseJSON.title);\r", + "postman.setEnvironmentVariable('target_menu_description', responseJSON.description);\r", + "\r", + "// check that 'target_menu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'target_menu_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_menu_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_description')).to.eql(responseJSON.description);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My menu 1\",\r\n \"description\": \"My menu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is not empty list\r", + "pm.test(\"Response is not empty list\", function() {\r", + " pm.expect(responseJSON).not.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_menu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'target_menu_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_menu_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_description')).to.eql(responseJSON.description);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Обновляет меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Status code is 200\", () => {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_menu_title' from environment & response are not equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_title')).not.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_menu_description' from environment & response are not equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_description')).not.eql(responseJSON.description);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_menu_title', responseJSON.title);\r", + "postman.setEnvironmentVariable('target_menu_description', responseJSON.description);\r", + "\r", + "// check that 'target_menu_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_menu_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_description')).to.eql(responseJSON.description);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My updated menu 1\",\r\n \"description\": \"My updated menu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_menu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'target_menu_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_menu_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_description')).to.eql(responseJSON.description);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Удаляет меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 404 NOT FOUND\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(404);\r", + "});\r", + "\r", + "// check that default message & response are equal\r", + "pm.test(\"Response detail message is correct\", () => {\r", + " pm.expect(\"menu not found\").to.eql(responseJSON.detail);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "// check that response headers 'content-type' is 'application/json'", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});" + ] + } + } + ] + }, + { + "name": "CRUD для Подменю", + "item": [ + { + "name": "Создает меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_menu_id', responseJSON.id);\r", + "\r", + "// check that 'target_menu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My submenu 1\",\r\n \"description\": \"My submenu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus" + ] + } + }, + "response": [] + }, + { + "name": "Создает подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_submenu_id', responseJSON.id);\r", + "postman.setEnvironmentVariable('target_submenu_title', responseJSON.title);\r", + "postman.setEnvironmentVariable('target_submenu_description', responseJSON.description);\r", + "\r", + "// check that 'target_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'target_submenu_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_submenu_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_description')).to.eql(responseJSON.description);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My submenu 1\",\r\n \"description\": \"My submenu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is not empty list\r", + "pm.test(\"Response is not empty list\", function() {\r", + " pm.expect(responseJSON).not.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'target_submenu_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_submenu_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_description')).to.eql(responseJSON.description);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Обновляет подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Status code is 200\", () => {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_submenu_title' from environment & response are not equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_title')).not.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_submenu_description' from environment & response are not equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_description')).not.eql(responseJSON.description);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_submenu_title', responseJSON.title);\r", + "postman.setEnvironmentVariable('target_submenu_description', responseJSON.description);\r", + "\r", + "// check that 'target_submenu_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_submenu_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_description')).to.eql(responseJSON.description);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My updated submenu 1\",\r\n \"description\": \"My updated submenu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'target_submenu_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_submenu_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_description')).to.eql(responseJSON.description);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Удаляет подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 404 NOT FOUND\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(404);\r", + "});\r", + "\r", + "// check that default message & response are equal\r", + "pm.test(\"Response detail message is correct\", () => {\r", + " pm.expect(\"submenu not found\").to.eql(responseJSON.detail);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Удаляет меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "// check that response headers 'content-type' is 'application/json'", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});" + ] + } + } + ] + }, + { + "name": "CRUD для Блюда", + "item": [ + { + "name": "Создает меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_menu_id', responseJSON.id);\r", + "\r", + "// check that 'target_menu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My menu 1\",\r\n \"description\": \"My menu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + }, + { + "name": "Создает подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_submenu_id', responseJSON.id);\r", + "\r", + "// check that 'target_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My submenu 1\",\r\n \"description\": \"My submenu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список блюд", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes" + ] + } + }, + "response": [] + }, + { + "name": "Создает блюдо", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_dish_id', responseJSON.id);\r", + "postman.setEnvironmentVariable('target_dish_title', responseJSON.title);\r", + "postman.setEnvironmentVariable('target_dish_description', responseJSON.description);\r", + "postman.setEnvironmentVariable('target_dish_price', responseJSON.price);\r", + "\r", + "// check that 'target_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'target_submenu_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_submenu_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_description')).to.eql(responseJSON.description);\r", + "});\r", + "\r", + "// check that 'target_dish_price' from environment & response are equal\r", + "pm.test(\"Response contains 'description' price\", () => {\r", + " pm.expect(pm.environment.get('target_dish_price')).to.eql(responseJSON.price);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My dish 1\",\r\n \"description\": \"My dish description 1\",\r\n \"price\": \"12.50\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список блюд", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is not empty list\r", + "pm.test(\"Response is not empty list\", function() {\r", + " pm.expect(responseJSON).not.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное блюдо", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_dish_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'target_dish_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_dish_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_description')).to.eql(responseJSON.description);\r", + "});\r", + "\r", + "// check that 'target_dish_price' from environment & response are equal\r", + "pm.test(\"Response contains 'price' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_price')).to.eql(responseJSON.price);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes/{{target_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes", + "{{target_dish_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Обновляет блюдо", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Status code is 200\", () => {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_dish_title' from environment & response are not equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_title')).not.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_dish_description' from environment & response are not equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_description')).not.eql(responseJSON.description);\r", + "});\r", + "\r", + "// check that 'target_dish_price' from environment & response are not equal\r", + "pm.test(\"Response contains 'price' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_price')).not.eql(responseJSON.price);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_dish_title', responseJSON.title);\r", + "postman.setEnvironmentVariable('target_dish_description', responseJSON.description);\r", + "postman.setEnvironmentVariable('target_dish_price', responseJSON.price);\r", + "\r", + "// check that 'target_dish_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_dish_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_description')).to.eql(responseJSON.description);\r", + "});\r", + "\r", + "// check that 'target_dish_price' from environment & response are equal\r", + "pm.test(\"Response contains 'price' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_price')).to.eql(responseJSON.price);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My updated dish 1\",\r\n \"description\": \"My updated dish description 1\",\r\n \"price\": \"14.50\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes/{{target_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes", + "{{target_dish_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное блюдо", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_dish_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'target_dish_title' from environment & response are equal\r", + "pm.test(\"Response contains 'title' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_title')).to.eql(responseJSON.title);\r", + "});\r", + "\r", + "// check that 'target_dish_description' from environment & response are equal\r", + "pm.test(\"Response contains 'description' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_description')).to.eql(responseJSON.description);\r", + "});\r", + "\r", + "// check that 'target_dish_price' from environment & response are equal\r", + "pm.test(\"Response contains 'price' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_price')).to.eql(responseJSON.price);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes/{{target_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes", + "{{target_dish_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Удаляет блюдо", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes/{{target_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes", + "{{target_dish_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список блюд", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное блюдо", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 404 NOT FOUND\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(404);\r", + "});\r", + "\r", + "// check that default message & response are equal\r", + "pm.test(\"Response detail message is correct\", () => {\r", + " pm.expect(\"dish not found\").to.eql(responseJSON.detail);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes/{{target_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes", + "{{target_dish_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Удаляет подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus" + ] + } + }, + "response": [] + }, + { + "name": "Удаляет меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "// check that response headers 'content-type' is 'application/json'", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});" + ] + } + } + ] + }, + { + "name": "Проверка кол-ва блюд и подменю в меню", + "item": [ + { + "name": "Создает меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_menu_id', responseJSON.id);\r", + "\r", + "// check that 'target_menu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My menu 1\",\r\n \"description\": \"My menu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + }, + { + "name": "Создает подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_submenu_id', responseJSON.id);\r", + "\r", + "// check that 'target_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My submenu 1\",\r\n \"description\": \"My submenu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus" + ] + } + }, + "response": [] + }, + { + "name": "Создает блюдо 1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_dish_id', responseJSON.id);\r", + "\r", + "// check that 'target_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My dish 2\",\r\n \"description\": \"My dish description 2\",\r\n \"price\": \"13.50\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes" + ] + } + }, + "response": [] + }, + { + "name": "Создает блюдо 2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "// Save env vars\r", + "postman.setEnvironmentVariable('target_dish_id', responseJSON.id);\r", + "\r", + "// check that 'target_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_dish_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My dish 1\",\r\n \"description\": \"My dish description 1\",\r\n \"price\": \"12.50\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_menu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'submenus_count' from environment & response are equal\r", + "pm.test(\"Response contains 'submenus_count' property\", () => {\r", + " pm.expect(1).to.eql(responseJSON.submenus_count);\r", + "});\r", + "\r", + "// check that 'dishes_count' from environment & response are equal\r", + "pm.test(\"Response contains 'dishes_count' property\", () => {\r", + " pm.expect(2).to.eql(responseJSON.dishes_count);\r", + "});\r", + "\r", + "console.log(responseJSON)\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that 'target_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_submenu_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'dishes_count' from environment & response are equal\r", + "pm.test(\"Response contains 'dishes_count' property\", () => {\r", + " pm.expect(responseJSON.dishes_count).to.eql(2);\r", + "});\r", + "console.log(responseJSON);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Удаляет подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список блюд", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}/submenus/{{target_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}", + "submenus", + "{{target_submenu_id}}", + "dishes" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает определенное меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "console.log(responseJSON);\r", + "\r", + "// check that 'target_menu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('target_menu_id')).to.eql(responseJSON.id);\r", + "});\r", + "\r", + "// check that 'submenus_count' from environment & response are equal\r", + "pm.test(\"Response contains 'submenus_count' property\", () => {\r", + " pm.expect(responseJSON.submenus_count).to.eql(0);\r", + "});\r", + "\r", + "// check that 'dishes_count' from environment & response are equal\r", + "pm.test(\"Response contains 'dishes_count' property\", () => {\r", + " pm.expect(responseJSON.dishes_count).to.eql(0);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Удаляет меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{target_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{target_menu_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Просматривает список меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "// check that response is empty list\r", + "pm.test(\"Response is empty list\", function() {\r", + " pm.expect(responseJSON).to.eql([]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "api", + "item": [ + { + "name": "menu", + "item": [ + { + "name": "Просмотр списка меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [ + { + "name": "Выдача списка меню", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "[\r\n {\r\n \"id\": \"a2eb416c-2245-4526-bb4b-6343d5c5016f\",\r\n \"title\": \"My menu 1\",\r\n \"description\": \"My menu description 1\",\r\n \"submenus_count\": 0,\r\n \"dishes_count\": 0\r\n }\r\n]" + } + ] + }, + { + "name": "Просмотр определенного меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}" + ] + } + }, + "response": [ + { + "name": "Меню найдено", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"id\": \"a2eb416c-2245-4526-bb4b-6343d5c5016f\",\r\n \"title\": \"My menu 1\",\r\n \"description\": \"My menu description 1\",\r\n \"submenus_count\": 0,\r\n \"dishes_count\": 0\r\n}" + }, + { + "name": "Меню не найдено", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"detail\": \"menu not found\"\r\n}" + } + ] + }, + { + "name": "Создать меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable('api_test_menu_id', responseJSON.id);\r", + "\r", + "// check that 'api_test_menu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('api_test_menu_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My menu 1\",\r\n \"description\": \"My menu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "response": [ + { + "name": "Меню создано", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My menu 1\",\r\n \"description\": \"My menu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus" + ] + } + }, + "code": 201, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"id\": \"9a5bce5f-4462-4d12-a66c-d59584b19ee8\",\r\n \"title\": \"My menu 1\",\r\n \"description\": \"My menu description 1\",\r\n \"submenus_count\": 0,\r\n \"dishes_count\": 0\r\n}" + } + ] + }, + { + "name": "Обновить меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My updated menu 1\",\r\n \"description\": \"My updated menu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}" + ] + } + }, + "response": [ + { + "name": "Меню обновлено", + "originalRequest": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My updated menu 1\",\r\n \"description\": \"My updated menu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"id\": \"a2eb416c-2245-4526-bb4b-6343d5c5016f\",\r\n \"title\": \"My updated menu 1\",\r\n \"description\": \"My updated menu description 1\",\r\n \"submenus_count\": 0,\r\n \"dishes_count\": 0\r\n}" + }, + { + "name": "Меню не найдено", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"detail\": \"menu not found\"\r\n}" + } + ] + }, + { + "name": "Удалить меню", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}" + ] + } + }, + "response": [ + { + "name": "Меню удалено", + "originalRequest": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"status\": true,\r\n \"message\": \"The menu has been deleted\"\r\n}" + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "// check that response headers 'content-type' is 'application/json'", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});" + ] + } + } + ] + }, + { + "name": "submenu", + "item": [ + { + "name": "Просмотр списка подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus" + ] + } + }, + "response": [ + { + "name": "Выдача списка подменю", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "[\r\n {\r\n \"id\": \"bc19488a-cc0e-4eaa-8d21-4d486a45392f\",\r\n \"title\": \"My submenu 1\",\r\n \"description\": \"My submenu description 1\",\r\n \"dishes_count\": 0\r\n }\r\n]" + } + ] + }, + { + "name": "Просмотр определенного подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}" + ] + } + }, + "response": [ + { + "name": "Подменю найдено", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"id\": \"bc19488a-cc0e-4eaa-8d21-4d486a45392f\",\r\n \"title\": \"My submenu 1\",\r\n \"description\": \"My submenu description 1\",\r\n \"dishes_count\": 0\r\n}" + }, + { + "name": "Подменю не найдено", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"detail\": \"submenu not found\"\r\n}" + } + ] + }, + { + "name": "Создать подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable('api_test_submenu_id', responseJSON.id);\r", + "\r", + "// check that 'api_test_submenu_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('api_test_submenu_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My submenu 1\",\r\n \"description\": \"My submenu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus" + ] + } + }, + "response": [ + { + "name": "Подменю создано", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My submenu 1\",\r\n \"description\": \"My submenu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus" + ] + } + }, + "status": "Created", + "code": 201, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"id\": \"bc19488a-cc0e-4eaa-8d21-4d486a45392f\",\r\n \"title\": \"My submenu 1\",\r\n \"description\": \"My submenu description 1\",\r\n \"dishes_count\": 0\r\n}" + } + ] + }, + { + "name": "Обновить подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My updated submenu 1\",\r\n \"description\": \"My updated submenu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}" + ] + } + }, + "response": [ + { + "name": "Подменю обновлено", + "originalRequest": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My updated submenu 1\",\r\n \"description\": \"My updated submenu description 1\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"id\": \"bc19488a-cc0e-4eaa-8d21-4d486a45392f\",\r\n \"title\": \"My updated submenu 1\",\r\n \"description\": \"My updated submenu description 1\",\r\n \"dishes_count\": 0\r\n}" + }, + { + "name": "Подменю не найдено", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"detail\": \"submenu not found\"\r\n}" + } + ] + }, + { + "name": "Удалить подменю", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}" + ] + } + }, + "response": [ + { + "name": "Подменю удалено", + "originalRequest": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"status\": true,\r\n \"message\": \"The submenu has been deleted\"\r\n}" + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "// check that response headers 'content-type' is 'application/json'", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});" + ] + } + } + ] + }, + { + "name": "dish", + "item": [ + { + "name": "Просмотр списка блюд", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes" + ] + } + }, + "response": [ + { + "name": "Выдача списка блюд", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "[\r\n {\r\n \"id\": \"602033b3-0462-4de1-a2f8-d8494795e0c0\",\r\n \"title\": \"My dish 1\",\r\n \"description\": \"My dish description 1\",\r\n \"price\": \"12.50\"\r\n }\r\n]" + } + ] + }, + { + "name": "Просмотр определенного блюда", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes/{{api_test_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes", + "{{api_test_dish_id}}" + ] + } + }, + "response": [ + { + "name": "Блюдо найдено", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes/{{api_test_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes", + "{{api_test_dish_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"id\": \"602033b3-0462-4de1-a2f8-d8494795e0c0\",\r\n \"title\": \"My dish 1\",\r\n \"description\": \"My dish description 1\",\r\n \"price\": \"12.50\"\r\n}" + }, + { + "name": "Блюдо не найдено", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes/{{api_test_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes", + "{{api_test_dish_id}}" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"detail\": \"dish not found\"\r\n}" + } + ] + }, + { + "name": "Создать блюдо", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 201 CREATED\r", + "pm.test(\"Status code is 201\", () => {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "postman.setEnvironmentVariable('api_test_dish_id', responseJSON.id);\r", + "\r", + "// check that 'api_test_dish_id' from environment & response are equal\r", + "pm.test(\"Response contains 'id' property\", () => {\r", + " pm.expect(pm.environment.get('api_test_dish_id')).to.eql(responseJSON.id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My dish 1\",\r\n \"description\": \"My dish description 1\",\r\n \"price\": \"12.50\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes" + ] + } + }, + "response": [ + { + "name": "Блюдо создано", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My dish 1\",\r\n \"description\": \"My dish description 1\",\r\n \"price\": \"12.50\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes" + ] + } + }, + "status": "Created", + "code": 201, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"id\": \"602033b3-0462-4de1-a2f8-d8494795e0c0\",\r\n \"title\": \"My dish 1\",\r\n \"description\": \"My dish description 1\",\r\n \"price\": \"12.50\"\r\n}" + } + ] + }, + { + "name": "Обновить блюдо", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My updated dish 1\",\r\n \"description\": \"My updated dish description 1\",\r\n \"price\": \"14.50\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes/{{api_test_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes", + "{{api_test_dish_id}}" + ] + } + }, + "response": [ + { + "name": "Блюдо обновлено", + "originalRequest": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"My updated dish 1\",\r\n \"description\": \"My updated dish description 1\",\r\n \"price\": \"14.50\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes/{{api_test_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes", + "{{api_test_dish_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"id\": \"602033b3-0462-4de1-a2f8-d8494795e0c0\",\r\n \"title\": \"My updated dish 1\",\r\n \"description\": \"My updated dish description 1\",\r\n \"price\": \"14.50\"\r\n}" + }, + { + "name": "Блюдо не найдено", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes/{{api_test_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes", + "{{api_test_dish_id}}" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"detail\": \"dish not found\"\r\n}" + } + ] + }, + { + "name": "Удалить блюдо", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJSON = pm.response.json();\r", + "\r", + "// check that response status HTTP 200 OK\r", + "pm.test(\"Success answer\", function() {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes/{{api_test_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes", + "{{api_test_dish_id}}" + ] + } + }, + "response": [ + { + "name": "Блюдо удалено", + "originalRequest": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{LOCAL_URL}}/api/v1/menus/{{api_test_menu_id}}/submenus/{{api_test_submenu_id}}/dishes/{{api_test_dish_id}}", + "host": [ + "{{LOCAL_URL}}" + ], + "path": [ + "api", + "v1", + "menus", + "{{api_test_menu_id}}", + "submenus", + "{{api_test_submenu_id}}", + "dishes", + "{{api_test_dish_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": null, + "header": null, + "cookie": [], + "body": "{\r\n \"status\": true,\r\n \"message\": \"The dish has been deleted\"\r\n}" + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "// check that response headers 'content-type' is 'application/json'", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});" + ] + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/postman_scripts/menu app.postman_environment.json b/postman_scripts/menu app.postman_environment.json new file mode 100644 index 0000000..f85cfa5 --- /dev/null +++ b/postman_scripts/menu app.postman_environment.json @@ -0,0 +1,93 @@ +{ + "id": "7e7cd612-7f40-491b-8bd6-ba2322a3d0d7", + "name": "menu app", + "values": [ + { + "key": "LOCAL_URL", + "value": "127.0.0.1:8000", + "type": "default", + "enabled": true + }, + { + "key": "api_test_menu_id", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "api_test_submenu_id", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "api_test_dish_id", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_menu_id", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_menu_title", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_menu_description", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_submenu_id", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_submenu_title", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_submenu_description", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_dish_id", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_dish_title", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_dish_description", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "target_dish_price", + "value": "", + "type": "default", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2023-01-12T16:22:10.333Z", + "_postman_exported_using": "Postman/10.6.7" +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 5bccd76..72666d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ uvicorn = "^0.26.0" asyncpg = "^0.29.0" pydantic-settings = "^2.1.0" psycopg2-binary = "^2.9.9" +email-validator = "^2.1.0.post1" [tool.poetry.group.dev.dependencies]