diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..f8cfb7ea1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.idea/ +__pycache__/ +*.py[cod] + +.pytest_cache/ +.coverage +htmlcov/ +allure-results/ diff --git a/2_task/conftest.py b/2_task/conftest.py new file mode 100644 index 000000000..37670561c --- /dev/null +++ b/2_task/conftest.py @@ -0,0 +1,23 @@ +import pytest +from utils.helpers import register_user, login_user, get_ingredients + + +@pytest.fixture +def registered_user(): + user_data, response = register_user() + return user_data + +@pytest.fixture +def auth_token(): + user_data, _ = register_user() + response = login_user( + user_data["email"], + user_data["password"] + ) + return response.json()["accessToken"] + + +@pytest.fixture +def ingredient_ids(): + ingredients = get_ingredients() + return [ingredients[0]["_id"], ingredients[1]["_id"]] \ No newline at end of file diff --git a/2_task/data/__init__.py b/2_task/data/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/2_task/data/user_data.py b/2_task/data/user_data.py new file mode 100644 index 000000000..eb86b8e88 --- /dev/null +++ b/2_task/data/user_data.py @@ -0,0 +1,9 @@ +from utils.helpers import random_email, random_password, random_name + + +def get_valid_user(): + return { + "email": random_email(), + "password": random_password(), + "name": random_name() + } diff --git a/2_task/requirements.txt b/2_task/requirements.txt new file mode 100644 index 000000000..1cb991a0c --- /dev/null +++ b/2_task/requirements.txt @@ -0,0 +1,3 @@ +pytest +requests +allure-pytest \ No newline at end of file diff --git a/2_task/tests/test_orders.py b/2_task/tests/test_orders.py new file mode 100644 index 000000000..a6874080c --- /dev/null +++ b/2_task/tests/test_orders.py @@ -0,0 +1,59 @@ +import allure + +from utils.helpers import create_order + + +@allure.suite("Заказы") +class TestOrders: + + @allure.title("Создание заказа с авторизацией") + def test_create_order_with_auth(self, auth_token, ingredient_ids): + headers = { + "Authorization": auth_token + } + payload = { + "ingredients": ingredient_ids + } + + response = create_order(payload=payload, headers=headers) + body = response.json() + + assert response.status_code == 200 + assert "order" in body + assert body["order"]["number"] > 0 + assert body["order"]["ingredients"] + + @allure.title("Создание заказа без авторизации") + def test_create_order_without_auth(self, ingredient_ids): + payload = { + "ingredients": ingredient_ids + } + + response = create_order(payload=payload) + body = response.json() + + assert response.status_code == 200 + assert "order" in body + assert body["order"]["number"] > 0 + + @allure.title("Создание заказа без ингредиентов") + def test_create_order_without_ingredients(self): + payload = {} + + response = create_order(payload=payload) + body = response.json() + + assert response.status_code == 400 + assert body["message"] == "Ingredient ids must be provided" + + @allure.title("Создание заказа с некорректным id ингредиента") + def test_create_order_with_invalid_ingredient_id(self): + payload = { + "ingredients": ["invalid_hash"] + } + + response = create_order(payload=payload) + body = response.json() + + assert response.status_code == 400 + assert body["message"] == "One or more ids provided are incorrect" diff --git a/2_task/tests/test_user_create.py b/2_task/tests/test_user_create.py new file mode 100644 index 000000000..b27c600a2 --- /dev/null +++ b/2_task/tests/test_user_create.py @@ -0,0 +1,47 @@ +import allure +import pytest + +from utils.helpers import register_user +from data.user_data import get_valid_user + + +@allure.feature("Создание пользователя") +class TestUserCreate: + + @allure.title("Создание уникального пользователя") + def test_create_unique_user(self): + payload = get_valid_user() + + user_data, response = register_user(payload) + + body = response.json() + + assert response.status_code == 200 + assert "accessToken" in body + assert "refreshToken" in body + assert "user" in body + assert body["user"]["email"] == payload["email"] + + @allure.title("Создание уже существующего пользователя") + def test_create_existing_user(self): + payload = get_valid_user() + + register_user(payload) + _, response = register_user(payload) + + body = response.json() + + assert response.status_code == 403 + assert body["message"] == "User already exists" + + @allure.title("Создание пользователя без обязательных полей") + @pytest.mark.parametrize("missing_field", ["email", "password", "name"]) + def test_create_user_without_required_field(self, missing_field): + payload = get_valid_user() + payload.pop(missing_field) + + _, response = register_user(payload) + body = response.json() + + assert response.status_code == 403 + assert body["message"] == "Email, password and name are required fields" diff --git a/2_task/tests/test_user_login.py b/2_task/tests/test_user_login.py new file mode 100644 index 000000000..439a66716 --- /dev/null +++ b/2_task/tests/test_user_login.py @@ -0,0 +1,54 @@ +import allure +import pytest + +from utils.helpers import login_user + + +@allure.suite("Логин пользователя") +class TestUserLogin: + + @allure.title("Логин под существующим пользователем") + def test_login_existing_user(self, registered_user): + response = login_user( + email=registered_user["email"], + password=registered_user["password"] + ) + + body = response.json() + + assert response.status_code == 200 + assert "accessToken" in body + assert "refreshToken" in body + assert body["user"]["email"] == registered_user["email"] + + @allure.title("Логин с неверным логином и паролем") + def test_login_with_invalid_credentials(self): + response = login_user( + email="wrong@mail.ru", + password="wrongpassword" + ) + + body = response.json() + + assert response.status_code in [401, 403] + assert body["message"] == "email or password are incorrect" + + @allure.title("Логин без обязательных полей") + @pytest.mark.parametrize("missing_field", ["email", "password"]) + def test_login_without_required_field(self, missing_field): + payload = { + "email": "test@mail.ru", + "password": "password123" + } + payload.pop(missing_field) + + # вызываем helper напрямую с некорректными данными + response = login_user( + email=payload.get("email"), + password=payload.get("password") + ) + + body = response.json() + + assert response.status_code in [401, 403] + assert body["message"] == "email or password are incorrect" diff --git a/2_task/utils/__init__.py b/2_task/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/2_task/utils/helpers.py b/2_task/utils/helpers.py new file mode 100644 index 000000000..6249147d2 --- /dev/null +++ b/2_task/utils/helpers.py @@ -0,0 +1,65 @@ +import random +import string +import requests +import allure + +from utils.urls import BASE_URL + + +def random_email(): + return f"test_{''.join(random.choices(string.ascii_lowercase, k=8))}@mail.ru" + + +def random_password(): + return ''.join(random.choices(string.ascii_letters + string.digits, k=10)) + + +def random_name(): + return ''.join(random.choices(string.ascii_letters, k=6)) + + +@allure.step("Регистрация пользователя") +def register_user(payload=None): + if payload is None: + payload = { + "email": random_email(), + "password": random_password(), + "name": random_name() + } + + response = requests.post( + f"{BASE_URL}/api/auth/register", + json=payload + ) + return payload, response + + +@allure.step("Логин пользователя") +def login_user(email, password): + payload = { + "email": email, + "password": password + } + response = requests.post( + f"{BASE_URL}/api/auth/login", + json=payload + ) + return response + + +@allure.step("Получение списка ингредиентов") +def get_ingredients(): + response = requests.get( + f"{BASE_URL}/api/ingredients" + ) + return response.json()["data"] + + +@allure.step("Создание заказа") +def create_order(payload, headers=None): + response = requests.post( + f"{BASE_URL}/api/orders", + json=payload, + headers=headers + ) + return response diff --git a/2_task/utils/urls.py b/2_task/utils/urls.py new file mode 100644 index 000000000..8450f7f77 --- /dev/null +++ b/2_task/utils/urls.py @@ -0,0 +1 @@ +BASE_URL = "https://stellarburgers.education-services.ru"