diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..b96e392 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,170 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ + +# PyPI configuration file +.pypirc + +# Ruff files +.ruff_cache diff --git a/tests/components/basic_auth.yml b/tests/components/basic_auth.yml new file mode 100644 index 0000000..857f9ed --- /dev/null +++ b/tests/components/basic_auth.yml @@ -0,0 +1,71 @@ +name: Базовый stage для регистрации компаний +description: Этот документ переиспользуется в других тестах для уменьшения дублирования YAML. + +variables: + company1: + name: "Рекламное агенство Малинки-Вечеринки" + email: raspberryprod@mail.com + password: SuperStrongPassword2000! + company2: + name: "Рекламное агенство Вишенки-Вечеринки" + email: cherryprod@mail.com + password: HARDpassword@10101010! + +stages: + - name: "Регистрация компании [1]" + id: basic_auth_reg1 + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "{company1.name:s}" + email: "{company1.email:s}" + password: "{company1.password:s}" + response: + status_code: 200 + save: + json: + company1_token: token + + - name: "Аутентификация [1]" + id: basic_auth_auth1 + request: + url: "{BASE_URL}/business/auth/sign-in" + method: POST + json: + email: "{company1.email:s}" + password: "{company1.password:s}" + response: + status_code: 200 + save: + json: + company1_token: token + + - name: "Регистрация компании [2]" + id: basic_auth_reg2 + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "{company2.name:s}" + email: "{company2.email:s}" + password: "{company2.password:s}" + response: + status_code: 200 + save: + json: + company2_token: token + + - name: "Аутентификация [2]" + id: basic_auth_auth2 + request: + url: "{BASE_URL}/business/auth/sign-in" + method: POST + json: + email: "{company2.email:s}" + password: "{company2.password:s}" + response: + status_code: 200 + save: + json: + company2_token: token diff --git a/tests/components/basic_promo.yml b/tests/components/basic_promo.yml new file mode 100644 index 0000000..8cb1ff7 --- /dev/null +++ b/tests/components/basic_promo.yml @@ -0,0 +1,51 @@ +name: Базовый набор корректных структур с промокодами +description: Этот документ переиспользуется в других тестах для уменьшения дублирования YAML. + +variables: + basic_promo1: + description: "Повышенный кэшбек 10% для новых клиентов банка!" + image_url: "https://cdn2.thecatapi.com/images/3lo.jpg" + target: {} + max_count: 10 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + + basic_promo2: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + image_url: "https://cdn2.thecatapi.com/images/3lo.jpg" + target: + age_from: 15 + country: fr + max_count: 100 + active_from: "2028-12-20" + mode: "COMMON" + promo_common: "sale-40" + + basic_promo3: + description: "Подарочная маска для сна при оформлении кредита на машину" + target: + age_from: 28 + age_until: 50 + country: ru + max_count: 1 + active_from: "2025-01-01" + active_until: "2028-12-30" + mode: "UNIQUE" + promo_unique: + - uniq1 + - uniq2 + - uniq3 + + basic_promo4: + description: "Дарим глобус при оформлении заказа на 30000!" + target: + age_from: 28 + age_until: 50 + country: us + max_count: 1 + active_until: "2025-01-10" + mode: "UNIQUE" + promo_unique: + - only_youuuu + - not_only_you diff --git a/tests/components/json/promo1.json b/tests/components/json/promo1.json new file mode 100644 index 0000000..9013d6d --- /dev/null +++ b/tests/components/json/promo1.json @@ -0,0 +1,9 @@ +{ + "description": "Повышенный кэшбек 10% для новых клиентов банка!", + "image_url": "https://cdn2.thecatapi.com/images/3lo.jpg", + "target": {}, + "max_count": 10, + "active_from": "2025-01-10", + "mode": "COMMON", + "promo_common": "sale-10" +} diff --git a/tests/components/json/promo2.json b/tests/components/json/promo2.json new file mode 100644 index 0000000..ffed134 --- /dev/null +++ b/tests/components/json/promo2.json @@ -0,0 +1,12 @@ +{ + "description": "Повышенный кэшбек 40% для новых клиентов банка!", + "image_url": "https://cdn2.thecatapi.com/images/3lo.jpg", + "target": { + "age_from": 15, + "country": "fr" + }, + "max_count": 100, + "active_from": "2028-12-20", + "mode": "COMMON", + "promo_common": "sale-40" +} diff --git a/tests/components/json/promo3.json b/tests/components/json/promo3.json new file mode 100644 index 0000000..28cff15 --- /dev/null +++ b/tests/components/json/promo3.json @@ -0,0 +1,13 @@ +{ + "description": "Подарочная маска для сна при оформлении кредита на машину", + "target": { + "age_from": 28, + "age_until": 50, + "country": "ru" + }, + "max_count": 1, + "active_from": "2025-01-01", + "active_until": "2028-12-30", + "mode": "UNIQUE", + "promo_unique": ["uniq1", "uniq2", "uniq3"] +} diff --git a/tests/components/json/promo4.json b/tests/components/json/promo4.json new file mode 100644 index 0000000..9027274 --- /dev/null +++ b/tests/components/json/promo4.json @@ -0,0 +1,12 @@ +{ + "description": "Дарим глобус при оформлении заказа на 30000!", + "target": { + "age_from": 28, + "age_until": 50, + "country": "us" + }, + "max_count": 1, + "active_until": "2025-01-10", + "mode": "UNIQUE", + "promo_unique": ["only_youuuu", "not_only_you"] +} diff --git a/tests/components/json/promo5.json b/tests/components/json/promo5.json new file mode 100644 index 0000000..8a0932d --- /dev/null +++ b/tests/components/json/promo5.json @@ -0,0 +1,13 @@ +{ + "description": "Повышенный кэшбек 10000% для новых клиентов банка!", + "target": { + "country": "kz", + "age_from": 20, + "age_until": 100, + "categories": ["tbankvpered", "KOTEkote", "dogseverywhere"] + }, + "active_until": "2040-01-02", + "max_count": 10, + "mode": "COMMON", + "promo_common": "sale-1000" +} diff --git a/tests/compose.testing.yaml b/tests/compose.testing.yaml new file mode 100644 index 0000000..0dc8aaa --- /dev/null +++ b/tests/compose.testing.yaml @@ -0,0 +1,52 @@ +name: promocode + +services: + app: + build: ../solution + ports: + - 12320:8080 + environment: + - SERVER_ADDRESS=0.0.0.0:8080 + - SERVER_PORT=8080 + - POSTGRES_CONN=postgres://postgres:postgres@postgres:5432/postgres + - POSTGRES_JDBC_URL=jdbc:postgresql://postgres:5432/postgres + - POSTGRES_USERNAME=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - POSTGRES_DATABASE=postgres + - REDIS_HOST=redis + - REDIS_PORT=6379 + - ANTIFRAUD_ADDRESS=antifraud:9090 + - RANDOM_SECRET=yourRandomSecret128charsHere1234567890abcdef + depends_on: + - postgres + - redis + - antifraud + + postgres: + image: postgres:16.6-alpine3.21 + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + volumes: + - postgres_data:/var/lib/postgresql/data + shm_size: 128mb + + redis: + image: redis:7.4-alpine3.21 + + antifraud: + image: docker.io/lodthe/prod-backend-antifraud:latest + ports: + - 12321:9090 + environment: + - SERVER_PORT=9090 + - NUMBER_KILLER_REQUEST=4 + - CACHE_DURATION_MS=3000 + - BLOCKED_EMAILS=blocked@antifraud.com + - SLOWDOWN_AFTER=slowdown@antifraud.ru + +volumes: + postgres_data: diff --git a/tests/config.yml b/tests/config.yml new file mode 100644 index 0000000..a636c97 --- /dev/null +++ b/tests/config.yml @@ -0,0 +1,3 @@ +variables: + BASE_URL: "http://127.0.0.1:12320/api" + ANTIFRAUD_URL: "http://127.0.0.1:12321/internal" diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..5fcdf50 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,21 @@ +import logging +from collections.abc import MutableMapping +from typing import Any + + +def pytest_tavern_beta_before_every_request(request_args: MutableMapping): + message = f"Request: {request_args['method']} {request_args['url']}" + + params = request_args.get("params", None) + if params: + message += f"\nQuery parameters: {params}" + + message += f"\nRequest body: {request_args.get('json', '')}" + + logging.info(message) + + +def pytest_tavern_beta_after_every_response( + expected: Any, response: Any +) -> None: + logging.info(f"Response: {response.status_code} {response.text}") diff --git a/tests/pyproject.toml b/tests/pyproject.toml new file mode 100644 index 0000000..0f241cc --- /dev/null +++ b/tests/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "tests-final" +version = "0.1.0" +description = "Final tests for the second stage of the PROD olympiad." +requires-python = ">=3.11" +dependencies = [ + "google-api-python-client>=2.160.0", + "pytest>=7.2.2", + "tavern>=2.11.0", +] diff --git a/tests/pytest.ini b/tests/pytest.ini new file mode 100644 index 0000000..9721edc --- /dev/null +++ b/tests/pytest.ini @@ -0,0 +1,9 @@ +[pytest] +tavern-global-cfg = config.yml +tavern-strict = json:off headers:off + +log_cli = true +log_cli_level = ERROR + +filterwarnings = + ignore::DeprecationWarning diff --git a/tests/run-tests.sh b/tests/run-tests.sh new file mode 100644 index 0000000..b07eadf --- /dev/null +++ b/tests/run-tests.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +restart_stack() { + docker compose -f compose.testing.yaml down -v 2>/dev/null + docker compose -f compose.testing.yaml up -d 2>/dev/null + sleep 5 +} + +tests=( + reload + test_01_ping.tavern.yml + test_02_business_signup.tavern.yml + test_02_business_signup_invalid_password.tavern.yml + reload + test_03_business_signin.tavern.yml + reload + test_04_business_promo_create_valid.tavern.yml + test_04_business_promo_create_valid_tricky.tavern.yml + test_04_business_promo_create_invalid.tavern.yml + reload + test_04_business_promo_create_valid.tavern.yml + test_05_business_promo_list.tavern.yml + test_05_business_promo_list_invalid.tavern.yml + reload + test_06_business_promo_id_valid.tavern.yml + test_06_business_promo_id_invalid.tavern.yml + reload + test_07_user_signup.tavern.yml + test_07_user_signup_invalid.tavern.yml + reload + test_08_user_signin.tavern.yml + reload + test_09_user_profile.tavern.yml + test_09_user_profile_invalid.tavern.yml + reload + test_10_user_feed.tavern.yml + test_10_user_promo.tavern.yml + reload + test_11_user_like.tavern.yml + reload + test_12_user_comments.tavern.yml + reload + test_13_user_promo_activate.tavern.yml + test_13_user_promo_activate_validate_cache.tavern.yml + reload + test_14_business_activate_promo.tavern.yml + test_14_business_get_stat.tavern.yml + reload +) + +docker compose -f compose.testing.yaml up -d --build --force-recreate --remove-orphans 2>/dev/null + +for test in "${tests[@]}"; do + if [[ "$test" == "reload" ]]; then + restart_stack + continue + fi + + uv run pytest "$test" +done + +docker compose -f compose.testing.yaml down -v --remove-orphans 2>/dev/null diff --git a/tests/test_01_ping.tavern.yml b/tests/test_01_ping.tavern.yml new file mode 100644 index 0000000..22de037 --- /dev/null +++ b/tests/test_01_ping.tavern.yml @@ -0,0 +1,9 @@ +test_name: Базовая проверка работоспособности + +stages: + - name: "Проверить PING" + request: + url: "{BASE_URL}/ping" + method: GET + response: + status_code: 200 diff --git a/tests/test_02_business_signup.tavern.yml b/tests/test_02_business_signup.tavern.yml new file mode 100644 index 0000000..841a9a9 --- /dev/null +++ b/tests/test_02_business_signup.tavern.yml @@ -0,0 +1,24 @@ +test_name: Регистрация на уже зарегистрированный e-mail + +stages: + - name: "Регистрация нового бизнес аккаунта" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Малинки-Вечеринки" + email: raspberryprod@mail.com + password: SuperStrongPassword2000! + response: + status_code: 200 + + - name: "Повторная регистрация на тот же email" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Малинки-Вечеринки КОПИЯ" + email: raspberryprod@mail.com + password: SuperStrongPassword2000! + response: + status_code: 409 diff --git a/tests/test_02_business_signup_invalid_password.tavern.yml b/tests/test_02_business_signup_invalid_password.tavern.yml new file mode 100644 index 0000000..660670d --- /dev/null +++ b/tests/test_02_business_signup_invalid_password.tavern.yml @@ -0,0 +1,101 @@ +test_name: Проверка некорректного пароля при регистрации + +stages: + - name: "Регистрация нового бизнес аккаунта: слишком короткий пароль [1]" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Вишенки-Вечеринки" + email: cherryprod@mail.com + password: easypwd + response: + status_code: 400 + + - name: "Регистрация нового бизнес аккаунта: слишком короткий пароль [2]" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Вишенки-Вечеринки" + email: cherryprod@mail.com + password: Ar1@!$ + response: + status_code: 400 + + - name: "Регистрация нового бизнес аккаунта: пароль без цифр" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Вишенки-Вечеринки" + email: cherryprod@mail.com + password: easypwdddddddd + response: + status_code: 400 + + - name: "Регистрация нового бизнес аккаунта: пароль без спец символов" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Вишенки-Вечеринки" + email: cherryprod@mail.com + password: easypwd111111111 + response: + status_code: 400 + + - name: "Регистрация нового бизнес аккаунта: слишком короткое название" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "к" + email: cherryprod@mail.com + password: HARDpassword@10101010! + response: + status_code: 400 + + - name: "Регистрация нового бизнес аккаунта: некорректный e-mail [1]" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Вишенки-Вечеринки" + email: a@b + password: HARDpassword@10101010! + response: + status_code: 400 + + - name: "Регистрация нового бизнес аккаунта: некорректный e-mail [2]" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Вишенки-Вечеринки" + email: "привет@к" + password: HARDpassword@10101010! + response: + status_code: 400 + + - name: "Регистрация нового бизнес аккаунта: некорректный e-mail [3]" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Вишенки-Вечеринки" + email: "@edu.gmail.com" + password: HARDpassword@10101010! + response: + status_code: 400 + + - name: "Регистрация нового бизнес аккаунта: корректно" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Вишенки-Вечеринки" + email: cherryprod@mail.com + password: HARDpassword@10101010! + response: + status_code: 200 diff --git a/tests/test_03_business_signin.tavern.yml b/tests/test_03_business_signin.tavern.yml new file mode 100644 index 0000000..478b991 --- /dev/null +++ b/tests/test_03_business_signin.tavern.yml @@ -0,0 +1,23 @@ +test_name: Базовая регистрация и аутентификация + +stages: + - name: "Регистрация нового бизнес аккаунта" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Рекламное агенство Малинки-Вечеринки" + email: raspberryprod@mail.com + password: SuperStrongPassword2000! + response: + status_code: 200 + + - name: "Аутентификация" + request: + url: "{BASE_URL}/business/auth/sign-in" + method: POST + json: + email: raspberryprod@mail.com + password: SuperStrongPassword2000! + response: + status_code: 200 diff --git a/tests/test_04_business_promo_create_invalid.tavern.yml b/tests/test_04_business_promo_create_invalid.tavern.yml new file mode 100644 index 0000000..55ebb3f --- /dev/null +++ b/tests/test_04_business_promo_create_invalid.tavern.yml @@ -0,0 +1,380 @@ +test_name: Создание промокода с ошибкой + +stages: + - name: "Регистрация компании" + request: + url: "{BASE_URL}/business/auth/sign-up" + method: POST + json: + name: "Кто-то" + email: pochta@mail.com + password: SuperStrongPassword2000! + response: + status_code: 200 + save: + json: + company100_token_old: token + + - name: "Аутентификация" + request: + url: "{BASE_URL}/business/auth/sign-in" + method: POST + json: + email: pochta@mail.com + password: SuperStrongPassword2000! + response: + status_code: 200 + save: + json: + company100_token: token + + - name: "Попытка создать промокод со старым токеном" + id: 04_create1 + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token_old}" + json: !include components/json/promo1.json + response: + status_code: 401 + + - name: "Создание некорректного промокода (пропущено описание)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + target: {} + max_count: 10 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 400 + + - name: "Создание некорректного промокода (пропущен таргет)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 100 + active_from: "2028-12-20" + mode: "COMMON" + promo_common: "sale-40" + response: + status_code: 400 + + - name: "Создание некорректного промокода (некорректный mode)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Подарочная маска для сна при оформлении кредита на машину" + target: + age_from: 28 + age_until: 50 + country: ru + max_count: 1 + active_from: "2025-01-01" + active_until: "2028-12-30" + mode: "EMINEM" + promo_unique: + - uniq1 + - uniq2 + - uniq3 + response: + status_code: 400 + + - name: "Создание некорректного промокода (некорректный max_count)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Подарочная маска для сна при оформлении кредита на машину" + target: + age_from: 28 + age_until: 50 + country: ru + max_count: 3 + active_from: "2025-01-01" + active_until: "2028-12-30" + mode: "UNIQUE" + promo_unique: + - uniq1 + - uniq2 + - uniq3 + response: + status_code: 400 + + - name: "Создание некорректного промокода (некорректная страна и маленькое описание)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "small" + target: + age_from: 28 + age_until: 50 + country: Vietnam + max_count: 1 + active_until: "2025-01-10" + mode: "UNIQUE" + promo_unique: + - only_youuuu + - not_only_you + response: + status_code: 400 + + - name: "Создание некорректного промокода (несуществующая страна)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 100 + target: + country: aa + active_from: "2028-12-20" + mode: "COMMON" + promo_common: "sale-40" + response: + status_code: 400 + + - name: "Создание некорректного промокода (age_from > age_until)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 100 + target: + age_from: 50 + age_until: 49 + active_from: "2028-12-20" + mode: "COMMON" + promo_common: "sale-40" + response: + status_code: 400 + + - name: "Создание некорректного промокода (пропущенное promo_common)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 100 + target: {} + active_from: "2028-12-20" + mode: "COMMON" + response: + status_code: 400 + + - name: "Создание некорректного промокода (common и promo_unique)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 100 + target: {} + active_from: "2028-12-20" + mode: "COMMON" + promo_unique: + - "sale-40" + response: + status_code: 400 + + - name: "Создание некорректного промокода (unique и promo_common)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 1 + target: {} + active_from: "2028-12-20" + mode: "UNIQUE" + promo_common: "sale-40" + response: + status_code: 400 + + - name: "Создание некорректного промокода (promo_common и promo_unique)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 1 + target: {} + active_from: "2028-12-20" + mode: "UNIQUE" + promo_common: "sale-40" + promo_unique: + - "opa" + response: + status_code: 400 + + - name: "Создание некорректного промокода (слишком короткое promo_common)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 100 + target: {} + active_from: "2028-12-20" + mode: "COMMON" + promo_common: "str" + response: + status_code: 400 + + - name: "Создание некорректного промокода (некорректный тип promo_unique)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 1 + target: {} + active_from: "2028-12-20" + mode: "UNIQUE" + promo_unique: 123 + response: + status_code: 400 + + - name: "Создание некорректного промокода (некорректный тип max_count)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: "fifty" + target: {} + active_from: "2028-12-20" + mode: "COMMON" + promo_common: "sale-40" + response: + status_code: 400 + + - name: "Создание некорректного промокода (некорректный тип target)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 1 + target: 123 + active_from: "2028-12-20" + mode: "UNIQUE" + promo_unique: + - "opa" + response: + status_code: 400 + + - name: "Создание некорректного промокода (отрицательный max_count)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: -1 + target: {} + mode: "COMMON" + promo_common: "something-here" + response: + status_code: 400 + + - name: "Создание некорректного промокода (слишком большой max_count)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 100000001 + target: {} + mode: "COMMON" + promo_common: "something-here" + response: + status_code: 400 + + - name: "Создание некорректного промокода (огромный max_count)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + max_count: 1000000000001 + target: {} + mode: "COMMON" + promo_common: "something-here" + response: + status_code: 400 + + - name: "Создание некорректного промокода (некорректная ссылка)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + image_url: itsnotalink + max_count: 1000 + target: {} + mode: "COMMON" + promo_common: "something-here" + response: + status_code: 400 + + - name: "Создание некорректного промокода (некорректная ссылка)" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company100_token}" + json: + description: "Повышенный кэшбек 40% для новых клиентов банка!" + image_url: "privet@com" + max_count: 1000 + target: {} + mode: "COMMON" + promo_common: "something-here" + response: + status_code: 400 diff --git a/tests/test_04_business_promo_create_valid.tavern.yml b/tests/test_04_business_promo_create_valid.tavern.yml new file mode 100644 index 0000000..8ebf738 --- /dev/null +++ b/tests/test_04_business_promo_create_valid.tavern.yml @@ -0,0 +1,83 @@ +test_name: Корректное создание промокода + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + - !include components/basic_promo.yml + +stages: + - type: ref + id: basic_auth_reg1 + # Переиспользование шага из файла components/basic_auth.yml + + - type: ref + id: basic_auth_auth1 + # Переиспользование шага из файла components/basic_auth.yml + + - type: ref + id: basic_auth_reg2 + # Переиспользование шага из файла components/basic_auth.yml + + - type: ref + id: basic_auth_auth2 + # Переиспользование шага из файла components/basic_auth.yml + + - name: "Успешное создание промокода [1]" + id: 04_create1 + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + # Чтобы посмотреть на структуру запроса, смотрите файлы с соответствующим названием в директории components/json + json: !include components/json/promo1.json + response: + status_code: 201 + save: + json: + company1_promo1_id: id + + - name: "Успешное создание промокода [2]" + id: 04_create2 + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + # Чтобы посмотреть на структуру запроса, смотрите файлы с соответствующим названием в директории components/json + json: !include components/json/promo2.json + response: + status_code: 201 + save: + json: + company1_promo2_id: id + + - name: "Успешное создание промокода [3]" + id: 04_create3 + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + # Чтобы посмотреть на структуру запроса, смотрите файлы с соответствующим названием в директории components/json + json: !include components/json/promo3.json + response: + status_code: 201 + save: + json: + company1_promo3_id: id + + - name: "Успешное создание промокода [4]" + id: 04_create4 + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + # Чтобы посмотреть на структуру запроса, смотрите файлы с соответствующим названием в директории components/json + json: !include components/json/promo4.json + response: + status_code: 201 + save: + json: + company2_promo1_id: id diff --git a/tests/test_04_business_promo_create_valid_tricky.tavern.yml b/tests/test_04_business_promo_create_valid_tricky.tavern.yml new file mode 100644 index 0000000..b8ea80f --- /dev/null +++ b/tests/test_04_business_promo_create_valid_tricky.tavern.yml @@ -0,0 +1,83 @@ +test_name: Корректное создание промокода [усложненная версия] + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +stages: + - type: ref + id: basic_auth_auth1 + # Переиспользование шага из файла components/basic_auth.yml + + - type: ref + id: basic_auth_auth2 + # Переиспользование шага из файла components/basic_auth.yml + + - name: "Успешное создание промокода [5]" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "Повышенный кэшбек 10% для новых клиентов банка!" + image_url: "http://cdn2.thecatapi.com/" + target: {} + max_count: 10 + active_from: "1950-01-01" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + + - name: "Успешное создание промокода [6]" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "Повышенный кэшбек 10% для новых клиентов банка!" + image_url: "http://cdn2.thecatapi.com/" + target: + country: Ru + max_count: 10 + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + + - name: "Успешное создание промокода [6]" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "Повышенный кэшбек 10% для новых клиентов банка!" + image_url: "http://cdn2.thecatapi.com/" + target: + country: RU + max_count: 10 + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + + - name: "Успешное создание промокода [7]" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "Повышенный кэшбек 10% для новых клиентов банка!" + image_url: "http://cdn2.thecatapi.com/" + target: + age_from: 100 + age_until: 100 + max_count: 10 + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 diff --git a/tests/test_05_business_promo_list.tavern.yml b/tests/test_05_business_promo_list.tavern.yml new file mode 100644 index 0000000..f1f2c86 --- /dev/null +++ b/tests/test_05_business_promo_list.tavern.yml @@ -0,0 +1,266 @@ +test_name: Получение промокодов компанией + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + - !include components/basic_promo.yml + +# Перед этим тестом необходимо создать промокоды с помощью test_04_business_promo_create_valid.tavern.yml + +stages: + - type: ref + id: basic_auth_auth1 + + - type: ref + id: basic_auth_auth2 + + - name: "Получение всего списка промокодов без токена" + request: + url: "{BASE_URL}/business/promo" + method: GET + headers: + Authorization: "Bearer invalid" + response: + status_code: 401 + + - name: "Получение всего списка промокодов" + request: + url: "{BASE_URL}/business/promo" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + # Проверяем, что вернулись все промокоды компании, отсортированные в порядке убывания даты создания. + - !include components/json/promo3.json + - !include components/json/promo2.json + - !include components/json/promo1.json + headers: + X-Total-Count: "3" + + - name: "Получение списка промокодов с пагинацией [1]" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + offset: 1 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo2.json + - !include components/json/promo1.json + headers: + X-Total-Count: "3" + + - name: "Получение списка промокодов с пагинацией [2]" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + offset: 1 + limit: 1 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo2.json + headers: + X-Total-Count: "3" + + - name: "Получение списка промокодов с пагинацией [3]" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + offset: 100 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: [] + headers: + X-Total-Count: "3" + + - name: "Получение списка промокодов с фильтрами [1]" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: ru + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo3.json + - !include components/json/promo1.json + headers: + X-Total-Count: "2" + + - name: "Получение списка промокодов с фильтрами и пагинацией [2]" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: ru + sort_by: active_until + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo1.json + - !include components/json/promo3.json + headers: + X-Total-Count: "2" + + - name: "Получение списка промокодов с фильтрами и пагинацией [3]" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: ru,FR + sort_by: active_from + limit: 10 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo2.json + - !include components/json/promo1.json + - !include components/json/promo3.json + headers: + X-Total-Count: "3" + + - name: "Получение списка промокодов с фильтрами и пагинацией [4]" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: ru,FR + sort_by: active_from + limit: 2 + offset: 2 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo3.json + headers: + X-Total-Count: "3" + + - name: "Получение списка промокодов с фильтрами и пагинацией [5]" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: ru,FR,us + sort_by: active_from + offset: 0 + limit: 2 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo2.json + - !include components/json/promo1.json + headers: + X-Total-Count: "3" + + - name: "Получение списка промокодов с фильтрами и пагинацией limit=0" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + limit: 0 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: [] + + - name: "Успешное создание промокода [5]" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: !include components/json/promo5.json + response: + status_code: 201 + save: + json: + company1_promo5_id: id + + - name: "Получение списка промокодов с фильтрами и пагинацией" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: ru,FR + sort_by: active_from + limit: 10 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo2.json + - !include components/json/promo1.json + - !include components/json/promo3.json + headers: + X-Total-Count: "3" + + - name: "Получение промокода по ID" + request: + url: "{BASE_URL}/business/promo/{company1_promo5_id}" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + + - name: "Получение списка промокодов с фильтрами и пагинацией" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: ru,Kz,FR + sort_by: active_from + limit: 10 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo2.json + - !include components/json/promo1.json + - !include components/json/promo3.json + - !include components/json/promo5.json + headers: + X-Total-Count: "4" + + - name: "Получение списка промокодов с фильтрами и пагинацией" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: Kz + sort_by: active_until + limit: 10 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - !include components/json/promo1.json + - !include components/json/promo5.json + headers: + X-Total-Count: "2" diff --git a/tests/test_05_business_promo_list_invalid.tavern.yml b/tests/test_05_business_promo_list_invalid.tavern.yml new file mode 100644 index 0000000..83a4a18 --- /dev/null +++ b/tests/test_05_business_promo_list_invalid.tavern.yml @@ -0,0 +1,93 @@ +test_name: Получение промокодов компанией + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + - !include components/basic_promo.yml + +# Перед этим тестом необходимо создать промокоды с помощью test_04_business_promo_create_valid.tavern.yml + +stages: + - type: ref + id: basic_auth_auth1 + + - type: ref + id: basic_auth_auth2 + + - name: "Получение списка промокодов: некорректный формат sort_by" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: ru + sort_by: active_untilllll + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 400 + + - name: "Получение списка промокодов: некорректный формат country" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: russia + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 400 + + - name: "Получение списка промокодов: некорректный формат country" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + country: fr,us,russia + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 400 + + - name: "Получение списка промокодов: некорректный формат limit" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + limit: russia + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 400 + + - name: "Получение списка промокодов: некорректный формат offset" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + offset: russia + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 400 + + - name: "Получение списка промокодов: отрицательный offset" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + offset: -5 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 400 + + - name: "Получение списка промокодов: отрицательный limit" + request: + url: "{BASE_URL}/business/promo" + method: GET + params: + limit: -5 + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 400 diff --git a/tests/test_06_business_promo_id_invalid.tavern.yml b/tests/test_06_business_promo_id_invalid.tavern.yml new file mode 100644 index 0000000..20fde55 --- /dev/null +++ b/tests/test_06_business_promo_id_invalid.tavern.yml @@ -0,0 +1,260 @@ +test_name: Корректное получение и изменение промокода по ID + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +# Данный тест должен запускаться после test_06_business_promo_id_valid.tavern.yml + +stages: + - type: ref + id: basic_auth_auth1 + + - type: ref + id: basic_auth_auth2 + + - name: "Успешное создание промокода [компания 1]" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "Аааавтомобиль в подарок" + target: {} + max_count: 10 + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + company1_promo1_id: id + + - name: "Успешное создание промокода [компания 2]" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + json: + description: "Бесплатный скин на пуджа при регистрации по промокоду!" + target: {} + max_count: 1 + mode: UNIQUE + active_from: "2030-08-08" + promo_unique: + - dota2 + - doka2 + - warcraft3 + response: + status_code: 201 + save: + json: + company2_promo1_id: id + + - name: "Аутентификация компании 1 (инвалидация старого токена)" + request: + url: "{BASE_URL}/business/auth/sign-in" + method: POST + json: + email: "{company1.email:s}" + password: "{company1.password:s}" + response: + status_code: 200 + + - name: "Получение промокода [1] со старым токеном" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 401 + + - type: ref + id: basic_auth_auth1 + + - name: "Редактируем несуществующий промокод (uuid взят из google)" + request: + url: "{BASE_URL}/business/promo/550e8400-e29b-41d4-a716-446655440000" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + description: "Кэшбек 100%" + response: + status_code: 404 + + - name: "Редактируем чужой промокод" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + description: "Кэшбек 100%" + response: + status_code: 403 + + - name: "Редактируем промокод без токена" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + json: + description: "Кэшбек 100%" + response: + # Если пользователь передал некорректный токен (или не передал его вовсе), необходимо возвращать ошибку аутентификации + status_code: 401 + + - name: "Редактируем промокод, некорректный запрос: короткий description" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + description: "qqall" + response: + status_code: 400 + + - name: "Редактируем промокод, некорректный запрос: некорректный image_url" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + description: "Бонус 10000%!" + image_url: no + response: + status_code: 400 + + - name: "Редактируем промокод, некорректный запрос: некорректный image_url" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + description: "Бонус 10000%!" + image_url: "https://" + response: + status_code: 400 + + - name: "Редактируем промокод, некорректный запрос: некорректный image_url" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + description: "Бонус 10000%!" + image_url: notalink + response: + status_code: 400 + + - name: "Редактируем промокод, некорректный запрос: некорректный image_url" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + image_url: jpeg + response: + status_code: 400 + + - name: "Редактируем промокод, некорректный таргет" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + description: "Бонус 10000%!" + target: + age_from: 19 + age_until: 17 + response: + status_code: 400 + + - name: "Редактируем промокод, некорректный таргет" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + description: "Бонус 10000%!" + target: + country: "USA" + response: + status_code: 400 + + - name: "Редактируем промокод, некорректный таргет" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + description: "Бонус 10000%!" + target: + categories: + - "" + response: + status_code: 400 + + - name: "Редактируем промокод, некорректный max_count (для UNIQUE только 1)" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + max_count: 10 + response: + status_code: 400 + + - name: "Редактируем промокод, отрицательный max_count" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + max_count: -10 + response: + status_code: 400 + + - name: "Редактируем промокод, некорректный active_from" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company2_token}" + json: + active_from: "2024-12-28 12:00:00" + response: + status_code: 400 + + - name: "Получение промокода: проверяем, что поля остались неизменными" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: GET + headers: + Authorization: "Bearer {company2_token}" + response: + status_code: 200 + json: + description: "Бесплатный скин на пуджа при регистрации по промокоду!" + target: {} + max_count: 1 + mode: UNIQUE + active_from: "2030-08-08" + promo_unique: + - dota2 + - doka2 + - warcraft3 + # В рамках данной группы тестов значение поля active не валидируется diff --git a/tests/test_06_business_promo_id_valid.tavern.yml b/tests/test_06_business_promo_id_valid.tavern.yml new file mode 100644 index 0000000..4bf82a9 --- /dev/null +++ b/tests/test_06_business_promo_id_valid.tavern.yml @@ -0,0 +1,265 @@ +test_name: Корректное получение и изменение промокода по ID + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +stages: + - type: ref + id: basic_auth_reg1 + # Переиспользование шага из файла components/basic_auth.yml + + - type: ref + id: basic_auth_auth1 + # Переиспользование шага из файла components/basic_auth.yml + + - type: ref + id: basic_auth_reg2 + # Переиспользование шага из файла components/basic_auth.yml + + - type: ref + id: basic_auth_auth2 + # Переиспользование шага из файла components/basic_auth.yml + + - name: "Успешное создание промокода [компания 1]" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "Повышенный кэшбек 10% для новых клиентов банка!" + image_url: "https://cdn2.thecatapi.com/images/3lo.jpg" + target: {} + max_count: 10 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + company1_promo1_id: id + + - name: "Успешное создание промокода [компания 2]" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + json: + description: Дарим глобус при оформлении заказа на 30000! + target: + age_from: 28 + age_until: 50 + country: us + max_count: 1 + active_until: "2025-01-10" + mode: UNIQUE + promo_unique: + - only_youuuu + - not_only_you + response: + status_code: 201 + save: + json: + company2_promo1_id: id + + - name: "Получение промокода [компания 1]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + description: "Повышенный кэшбек 10% для новых клиентов банка!" + image_url: "https://cdn2.thecatapi.com/images/3lo.jpg" + target: {} + max_count: 10 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + promo_id: "{company1_promo1_id:s}" + company_name: "{company1.name:s}" + like_count: 0 + used_count: 0 + # В рамках данной группы тестов значение поля active не валидируется + + - name: "Получение промокода [компания 2]" + request: + url: "{BASE_URL}/business/promo/{company2_promo1_id}" + method: GET + headers: + Authorization: "Bearer {company2_token}" + response: + status_code: 200 + json: + description: Дарим глобус при оформлении заказа на 30000! + target: + age_from: 28 + age_until: 50 + country: us + max_count: 1 + active_until: "2025-01-10" + mode: UNIQUE + promo_unique: + - only_youuuu + - not_only_you + promo_id: "{company2_promo1_id}" + company_name: "{company2.name}" + like_count: 0 + used_count: 0 + # В рамках данной группы тестов значение поля active не валидируется + + - name: "Редактируем описание и image [компания 1]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + description: "Кэшбек 100%" + image_url: "https://doesitexist.com/" + response: + status_code: 200 + json: + description: "Кэшбек 100%" + image_url: "https://doesitexist.com/" + target: {} + # Для простоты тестов остальные поля не валидируются + + - name: "Редактируем active_from [компания 1]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + active_from: "2023-12-20" + response: + status_code: 200 + json: + description: "Кэшбек 100%" + target: {} + active_from: "2023-12-20" + # Для простоты тестов остальные поля не валидируются + + - name: "Редактируем target, заполненный частично [компания 1]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + target: + country: fr + age_from: 28 + response: + status_code: 200 + json: + target: + country: fr + age_from: 28 + # Для простоты тестов остальные поля не валидируются + + - name: "Заменяем target [компания 1]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + target: + country: Us + categories: + - ios + - ФУТБОЛЬЧИК + response: + status_code: 200 + json: + target: + country: Us + categories: + - ios + - ФУТБОЛЬЧИК + # Для простоты тестов остальные поля не валидируются + + - name: "Редактируем active_until [компания 1]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + active_until: "2050-10-08" + response: + status_code: 200 + json: + target: + country: Us + categories: + - ios + - ФУТБОЛЬЧИК + active_until: "2050-10-08" + # Для простоты тестов остальные поля не валидируются + + - name: "Зануляем target [компания 1]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + target: {} + response: + status_code: 200 + json: + target: {} + # Для простоты тестов остальные поля не валидируются + + - name: "Редактируем max_count вверх [common промокод]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + max_count: 20 + response: + status_code: 200 + json: + max_count: 20 + + - name: "Редактируем max_count вниз [common промокод]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + max_count: 4 + response: + status_code: 200 + json: + max_count: 4 + + - name: "Получение промокода [1]" + request: + url: "{BASE_URL}/business/promo/{company1_promo1_id}" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + description: "Кэшбек 100%" + image_url: "https://doesitexist.com/" + target: {} + max_count: 4 + active_from: "2023-12-20" + mode: "COMMON" + promo_common: "sale-10" + promo_id: "{company1_promo1_id:s}" + company_name: "{company1.name:s}" diff --git a/tests/test_07_user_signup.tavern.yml b/tests/test_07_user_signup.tavern.yml new file mode 100644 index 0000000..011a975 --- /dev/null +++ b/tests/test_07_user_signup.tavern.yml @@ -0,0 +1,35 @@ +test_name: Корректная регистрация и проверка дублирования e-mail + +stages: + - name: "Регистрация нового пользователя" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 200 + save: + json: + user1_token: token + + - name: "Повторная регистрация на тот же email" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Lui + surname: Jomalone + email: dota.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: 14 + country: fr + response: + status_code: 409 diff --git a/tests/test_07_user_signup_invalid.tavern.yml b/tests/test_07_user_signup_invalid.tavern.yml new file mode 100644 index 0000000..12b7b5a --- /dev/null +++ b/tests/test_07_user_signup_invalid.tavern.yml @@ -0,0 +1,290 @@ +test_name: Некорректный запрос на регистрацию пользователя + +stages: + - name: "Регистрация нового пользователя: некорректный e-mail" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota.fan + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: простой пароль" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota.for.fan@edu.hse.ru + password: whereismymoney777 + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: простой пароль" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota.for.fan@edu.hse.ru + password: fioejifojfieoAAAA9299 + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: простой пароль" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota.for.fan@edu.hse.ru + password: Aa7$b! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: некорректная ссылка" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + avatar_url: itsnotalink + email: dota.for.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: некорректная ссылка" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + avatar_url: itsnotalinkjpeg + email: dota.for.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: некорректная ссылка" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + avatar_url: "https://" + email: dota.for.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: некорректная ссылка" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + avatar_url: "grpc://" + email: dota.for.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: пустая ссылка" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + avatar_url: "" # Ссылка либо должна отсутствовать, либо быть корректной. Пустая строка - некорректно. + email: dota.for.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: не указана страна" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota.for.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: 23 + response: + status_code: 400 + + - name: "Регистрация нового пользователя: некорректный тип для age" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota.for.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: "23aaaaaa" + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: отсутствует age" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota.for.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: отрицательный age" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota.for.fan@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: -20 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: некорректный email" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: "@" + password: SuperStrongPassword2000! + other: + country: ru + age: 20 + response: + status_code: 400 + + - name: "Регистрация нового пользователя: некорректный email" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: dota + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: некорректный email" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: "@gmail.com" + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: некорректный email" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: Fedotova + email: "gmail.com" + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: пустое name" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: "" + surname: Fedotova + email: "gogogonow@gmail.com" + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 + + - name: "Регистрация нового пользователя: пустое surname" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Maria + surname: "" + email: "gogogonow@gmail.com" + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 400 diff --git a/tests/test_08_user_signin.tavern.yml b/tests/test_08_user_signin.tavern.yml new file mode 100644 index 0000000..6075727 --- /dev/null +++ b/tests/test_08_user_signin.tavern.yml @@ -0,0 +1,47 @@ +test_name: Базовая регистрация и аутентификация пользователя + +stages: + - name: "Регистрация нового пользователя" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Steve + surname: Jobs + email: minecraft.digger@edu.hse.ru + password: SuperStrongPassword2000! + other: + age: 23 + country: ru + response: + status_code: 200 + save: + json: + user1_token: token + + - name: "Аутентификация: некорректная структура запроса (отсутствующие поля)" + request: + url: "{BASE_URL}/user/auth/sign-in" + method: POST + response: + status_code: 400 + + - name: "Аутентификация: некорректный пароль" + request: + url: "{BASE_URL}/user/auth/sign-in" + method: POST + json: + email: minecraft.digger@edu.hse.ru + password: SuperInvalidPassword2000! + response: + status_code: 401 + + - name: "Аутентификация: успех" + request: + url: "{BASE_URL}/user/auth/sign-in" + method: POST + json: + email: minecraft.digger@edu.hse.ru + password: SuperStrongPassword2000! + response: + status_code: 200 diff --git a/tests/test_09_user_profile.tavern.yml b/tests/test_09_user_profile.tavern.yml new file mode 100644 index 0000000..3059d59 --- /dev/null +++ b/tests/test_09_user_profile.tavern.yml @@ -0,0 +1,118 @@ +test_name: Получение и редактирование профиля + +stages: + - name: "Регистрация нового пользователя" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Steve + surname: Wozniak + email: creator@apple.com + password: WhoLiveSInCalifornia2000! + other: + age: 23 + country: ru + response: + status_code: 200 + save: + json: + user1_token: token + + - name: "Получение профиля" + request: + url: "{BASE_URL}/user/profile" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + name: Steve + surname: Wozniak + email: creator@apple.com + other: + age: 23 + country: ru + + - name: "Изменение имени и фамилии" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + name: Valeriy + surname: Tsal + response: + status_code: 200 + json: + name: Valeriy + surname: Tsal + # Для компактности проверяем только те поля, которые должны были измениться. + + - name: "Изменение имени и фамилии" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + avatar_url: http://nodomain.com/kitten.jpeg + response: + status_code: 200 + json: + avatar_url: http://nodomain.com/kitten.jpeg + # Для компактности проверяем только те поля, которые должны были измениться. + + - name: "Изменение пароля" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + password: MegaGiant88888@dooRuveS + response: + status_code: 200 + json: + name: Valeriy + surname: Tsal + email: creator@apple.com + other: + age: 23 + country: ru + avatar_url: http://nodomain.com/kitten.jpeg + + - name: "Получение профиля со старым токеном" + request: + url: "{BASE_URL}/user/profile" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + name: Valeriy + surname: Tsal + email: creator@apple.com + + - name: "Аутентификация: старый пароль не должен подходить" + request: + url: "{BASE_URL}/user/auth/sign-in" + method: POST + json: + email: creator@apple.com + password: WhoLiveSInCalifornia2000! + response: + status_code: 401 + + - name: "Аутентификация: с новым паролем" + request: + url: "{BASE_URL}/user/auth/sign-in" + method: POST + json: + email: creator@apple.com + password: MegaGiant88888@dooRuveS + response: + status_code: 200 diff --git a/tests/test_09_user_profile_invalid.tavern.yml b/tests/test_09_user_profile_invalid.tavern.yml new file mode 100644 index 0000000..602679a --- /dev/null +++ b/tests/test_09_user_profile_invalid.tavern.yml @@ -0,0 +1,125 @@ +test_name: Некорректные запросы на редактирование профиля + +stages: + - name: "Регистрация нового пользователя" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Jack + surname: TheSparrow + email: sparrow@movie.com + password: WhoLiveSInTheOcean100500! + other: + age: 48 + country: gb + response: + status_code: 200 + save: + json: + user1_token: token + + - name: "Редактирование профиля: пустое имя и фамилия" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + name: "" + surname: "" + response: + status_code: 400 + + - name: "Редактирование профиля: некорректный url" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + avatar_url: notURLcom + response: + status_code: 400 + + - name: "Редактирование профиля: некорректный url" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + avatar_url: "https://" + response: + status_code: 400 + + - name: "Редактирование профиля: простой пароль" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + password: pro100 + response: + status_code: 400 + + - name: "Редактирование профиля: простой пароль" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + password: "!!!!!" + response: + status_code: 400 + + - name: "Редактирование профиля: простой пароль" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + password: "onlyYOUOOOO!" + response: + status_code: 400 + + - name: "Редактирование профиля: простой пароль" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + password: "yOu!@1" + response: + status_code: 400 + + - name: "Редактирование профиля: простой пароль" + request: + url: "{BASE_URL}/user/profile" + method: PATCH + headers: + Authorization: "Bearer {user1_token}" + json: + password: "11111@@@@@aaaaa" + response: + status_code: 400 + + - name: "Получение профиля" + request: + url: "{BASE_URL}/user/profile" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + name: Jack + surname: TheSparrow + email: sparrow@movie.com + other: + age: 48 + country: gb diff --git a/tests/test_10_user_feed.tavern.yml b/tests/test_10_user_feed.tavern.yml new file mode 100644 index 0000000..9c5d7e4 --- /dev/null +++ b/tests/test_10_user_feed.tavern.yml @@ -0,0 +1,481 @@ +test_name: Получение промокодов компанией + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +stages: + - type: ref + id: basic_auth_reg1 + + - type: ref + id: basic_auth_reg2 + + - name: "Регистрация нового пользователя [1]: gb, 60" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Steve + surname: Wozniak + email: creator1@apple.com + password: WhoLiveSInCalifornia2000! + other: + age: 60 + country: gb + response: + status_code: 200 + save: + json: + user1_token: token + + - name: "Регистрация нового пользователя [2]: us, 15" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Mike + surname: Bloomberg + email: mike@bloomberg.com + password: WhoLiveSInCalifornia2000! + other: + age: 15 + country: us + response: + status_code: 200 + save: + json: + user2_token: token + + - name: "Регистрация нового пользователя [3]: ru, 40" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Yefim + surname: Dinitz + email: algo@prog.ru + password: HardPASSword1! + other: + age: 40 + country: ru + response: + status_code: 200 + save: + json: + user3_token: token + + - name: "Создание промокода [1]: active, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[1] Активный COMMON промокод без таргета" + target: {} + max_count: 10 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo1_id: id + + - name: "Создание промокода [2]: active, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[2] Активный COMMON промокод для fr" + target: + country: fr + categories: + - ios + - tbank + - КОТЫ + max_count: 6 + active_from: "2023-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo2_id: id + + - name: "Создание промокода [3]: inactive, , 13.." + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[3] Неактивный COMMON промокод для us, 13.." + target: + country: us + age_from: 13 + categories: + - ios + max_count: 100000 + active_until: "2025-01-10" + mode: "COMMON" + promo_common: "sale-30" + response: + status_code: 201 + save: + json: + promo3_id: id + + - name: "Создание промокода [4]: active, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[4] Активный UNIQUE промокод для ru, 20..60" + target: + country: ru + age_from: 20 + age_until: 60 + categories: + - телевизор + max_count: 1 + active_until: "2055-01-10" + mode: "UNIQUE" + promo_unique: + - dream + - "of:" + - californication + response: + status_code: 201 + save: + json: + promo4_id: id + + - name: "Создание промокода [5]: active, , ..50" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[5] Активный COMMON промокод для ru, ..50" + target: + country: ru + age_until: 50 + max_count: 1000 + active_from: "2023-01-10" + active_until: "2080-05-30" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo5_id: id + + - name: "Создание промокода [6]: inactive, , 5..90" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + json: + description: "[6] Неактивный COMMON промокод для fr, 5..90" + target: + country: fr + age_until: 90 + age_from: 5 + categories: + - Телевизор + max_count: 1 + active_from: "2040-12-08" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo6_id: id + + - name: "Создание промокода [7]: active, , 16.." + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + json: + description: "[7] Активный COMMON промокод для ru, 16.." + target: + country: ru + age_from: 16 + categories: + - Телевизор + max_count: 1 + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo7_id: id + + - name: "Создание промокода [8]: inactive, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + json: + description: "[8] Неактивный COMMON промокод для всех" + target: + categories: + - ТЕЛЕВИЗОР + max_count: 0 # Разрешено по спецификации, ведет к active=false + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo8_id: id + + - name: "Создание промокода [9]: active, , ..70" + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + json: + description: "[9] Активный COMMON промокод для ru, ..70" + target: + country: ru + age_until: 70 + max_count: 1 + active_until: "2099-08-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo9_id: id + + - name: "Получение всех промокодов пользователем 1 [gb, 60]" + request: + url: "{BASE_URL}/user/feed" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: # Для компактности тестов валидируются только некоторые из полей (при этом сервер должен возвращать все обязательные поля) + - promo_id: "{promo8_id}" + company_name: "{company2.name}" + active: false + - promo_id: "{promo1_id}" + company_name: "{company1.name}" + active: true + headers: + X-Total-Count: "2" + + - name: "Получение всех промокодов пользователем 2 [us, 15]" + request: + url: "{BASE_URL}/user/feed" + method: GET + headers: + Authorization: "Bearer {user2_token}" + response: + status_code: 200 + json: # Для компактности тестов валидируются только некоторые из полей (при этом сервер должен возвращать все обязательные поля) + - promo_id: "{promo8_id}" + - promo_id: "{promo3_id}" + company_name: "{company1.name}" + active: false + - promo_id: "{promo1_id}" + headers: + X-Total-Count: "3" + + - name: "Получение всех промокодов пользователем 3 [ru, 40]" + request: + url: "{BASE_URL}/user/feed" + method: GET + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + # Для компактности тестов валидируются только некоторые из полей (при этом сервер должен возвращать все обязательные поля) + - promo_id: "{promo9_id}" + company_name: "{company2.name}" + active: true + - promo_id: "{promo8_id}" + - promo_id: "{promo7_id}" + company_name: "{company2.name}" + active: true + - promo_id: "{promo5_id}" + company_name: "{company1.name}" + active: true + - promo_id: "{promo4_id}" + company_name: "{company1.name}" + active: true + - promo_id: "{promo1_id}" + company_name: "{company1.name}" + active: true + headers: + X-Total-Count: "6" + + - name: "Получение всех промокодов пользователем 3 [ru, 40], пагинация (2-3)" + request: + url: "{BASE_URL}/user/feed" + method: GET + params: + offset: 2 + limit: 3 + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + - promo_id: "{promo7_id}" + - promo_id: "{promo5_id}" + - promo_id: "{promo4_id}" + headers: + X-Total-Count: "6" + + - name: "Получение всех промокодов пользователем 3 [ru, 40], пагинация (10-2)" + request: + url: "{BASE_URL}/user/feed" + method: GET + params: + offset: 10 + limit: 2 + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: [] + headers: + X-Total-Count: "6" + + - name: "Получение всех промокодов пользователем 3 [ru, 40], пагинация (3, 1)" + request: + url: "{BASE_URL}/user/feed" + method: GET + params: + offset: 3 + limit: 1 + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + - promo_id: "{promo5_id}" + headers: + X-Total-Count: "6" + + - name: "Получение active=true промокодов пользователем 3 [ru, 40]" + request: + url: "{BASE_URL}/user/feed" + method: GET + params: + active: "true" + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + - promo_id: "{promo9_id}" + - promo_id: "{promo7_id}" + - promo_id: "{promo5_id}" + - promo_id: "{promo4_id}" + - promo_id: "{promo1_id}" + headers: + X-Total-Count: "5" + + - name: "Получение active=true промокодов пользователем 3 [ru, 40], пагинация (2, 2)" + request: + url: "{BASE_URL}/user/feed" + method: GET + params: + active: "true" + limit: 2 + offset: 2 + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + - promo_id: "{promo5_id}" + - promo_id: "{promo4_id}" + headers: + X-Total-Count: "5" + + - name: "Получение active=false промокодов пользователем 3 [ru, 40]" + request: + url: "{BASE_URL}/user/feed" + method: GET + params: + active: "false" + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + - promo_id: "{promo8_id}" + headers: + X-Total-Count: "1" + + - name: "Получение промокодов пользователем 3 [ru, 40] по категории 'телевизор' (другой регистр)" + request: + url: "{BASE_URL}/user/feed" + method: GET + params: + category: "телевиЗОР" + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + - promo_id: "{promo8_id}" + - promo_id: "{promo7_id}" + - promo_id: "{promo4_id}" + headers: + X-Total-Count: "3" + + - name: "Получение active=true промокодов пользователем 3 [ru, 40] по категории 'телевизор'" + request: + url: "{BASE_URL}/user/feed" + method: GET + params: + category: "телевизор" + active: "true" + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + - promo_id: "{promo7_id}" + - promo_id: "{promo4_id}" + headers: + X-Total-Count: "2" + + - name: "Получение промокодов пользователем 3 [ru, 40] по несуществующей категории 'не существует'" + request: + url: "{BASE_URL}/user/feed" + method: GET + params: + category: "не существует" + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: [] + headers: + X-Total-Count: "0" diff --git a/tests/test_10_user_promo.tavern.yml b/tests/test_10_user_promo.tavern.yml new file mode 100644 index 0000000..60d8b47 --- /dev/null +++ b/tests/test_10_user_promo.tavern.yml @@ -0,0 +1,156 @@ +test_name: Получение промокода по ID со стороны пользователя + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +# Перед этим тестом необходимо создать промокоды с помощью test_10_user_feed.tavern.yml + +stages: + - type: ref + id: basic_auth_auth1 + + - type: ref + id: basic_auth_auth2 + + - name: "Регистрация нового пользователя [4]: sg, 83" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Leslie + surname: Lamport + email: leslie@lamport.com + password: Everyth1ngIsDistributed! + other: + age: 80 + country: sg + response: + status_code: 200 + save: + json: + user4_token: token + + - name: "Создание промокода [10]: active, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[10] Активный COMMON промокод для kz" + target: + country: kz + max_count: 10 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo10_id: id + + - name: "Создание промокода [11]: active, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[11] Активный COMMON промокод для sg" + target: + country: sg + max_count: 1000 + active_from: "2023-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo11_id: id + + - name: "Получение промокода по ID [1]: промокод, проходящий по настройкам таргетинга" + request: + url: "{BASE_URL}/user/promo/{promo11_id}" + method: GET + headers: + Authorization: "Bearer {user4_token}" + response: + status_code: 200 + json: + promo_id: "{promo11_id}" + + - name: "Получение промокода по ID [2]: промокод, не проходящий по настройкам таргетинга" + request: + url: "{BASE_URL}/user/promo/{promo10_id}" + method: GET + headers: + Authorization: "Bearer {user4_token}" + response: + status_code: 200 + json: + promo_id: "{promo10_id}" + description: "[10] Активный COMMON промокод для kz" + + - name: "Получение промокода по ID: неправильный токен" + request: + url: "{BASE_URL}/user/promo/{promo10_id}" + method: GET + headers: + Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXRhIjoi0K3RgtC-INC_0LDRgdGF0LDQu9C60LAhIn0.r-XAwfQPWGo_Z8GFbDOvixXfUl63Sf_fFirQPFcGoMg" + response: + status_code: 401 + + - name: "Получение промокода по ID: несуществующий промокод (uuid из google)" + request: + url: "{BASE_URL}/user/promo/550e8400-e29b-41d4-a716-446655440000" + method: GET + headers: + Authorization: "Bearer {user4_token}" + response: + status_code: 404 + + - name: "Получение всех промокодов пользователем 4" + request: + url: "{BASE_URL}/user/feed" + method: GET + headers: + Authorization: "Bearer {user4_token}" + response: + status_code: 200 + json: + - promo_id: "{promo11_id}" + active: true + - description: "[8] Неактивный COMMON промокод для всех" + - description: "[1] Активный COMMON промокод без таргета" + headers: + X-Total-Count: "3" + + - name: "Редактирование промокода [11], он должен стать active=false" + request: + url: "{BASE_URL}/business/promo/{promo11_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + active_until: "2024-08-10" + response: + status_code: 200 + + - name: "Получение всех промокодов пользователем 4 (после редактирования)" + request: + url: "{BASE_URL}/user/feed" + method: GET + headers: + Authorization: "Bearer {user4_token}" + response: + status_code: 200 + json: + - promo_id: "{promo11_id}" + active: false + - description: "[8] Неактивный COMMON промокод для всех" + - description: "[1] Активный COMMON промокод без таргета" + headers: + X-Total-Count: "3" diff --git a/tests/test_11_user_like.tavern.yml b/tests/test_11_user_like.tavern.yml new file mode 100644 index 0000000..cf928da --- /dev/null +++ b/tests/test_11_user_like.tavern.yml @@ -0,0 +1,260 @@ +test_name: Получение промокода по ID со стороны пользователя + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +stages: + - type: ref + id: basic_auth_reg1 + + - type: ref + id: basic_auth_reg2 + + - name: "Регистрация нового пользователя [1]: gb, 60" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Steve + surname: Wozniak + email: creator1@apple.com + password: WhoLiveSInCalifornia2000! + other: + age: 60 + country: gb + response: + status_code: 200 + save: + json: + user1_token: token + + - name: "Регистрация нового пользователя [2]: us, 15" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Mike + surname: Bloomberg + email: mike@bloomberg.com + password: WhoLiveSInCalifornia2000! + other: + age: 15 + country: us + response: + status_code: 200 + save: + json: + user2_token: token + + - name: "Регистрация нового пользователя [3]: ru, 40" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Yefim + surname: Dinitz + email: algo@prog.ru + password: HardPASSword1! + other: + age: 40 + country: ru + response: + status_code: 200 + save: + json: + user3_token: token + + - name: "Создание промокода [1]: active, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[1] Активный COMMON промокод для всех" + target: {} + max_count: 10 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo1_id: id + + - name: "Получение промокода [1] со стороны пользователя 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo_id: "{promo1_id}" + like_count: 0 + is_liked_by_user: false + + - name: "Получение промокода [1] со стороны компании" + request: + url: "{BASE_URL}/business/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + promo_id: "{promo1_id}" + like_count: 0 + + - name: "Лайк промокода [1] пользователем 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/like" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + status: ok + + - name: "Повторный лайк промокода [1] пользователем 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/like" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + status: ok + + - name: "Получение промокода [1] со стороны пользователя 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo_id: "{promo1_id}" + like_count: 1 + is_liked_by_user: true + + - name: "Получение промокода [1] со стороны пользователя 2" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user2_token}" + response: + status_code: 200 + json: + like_count: 1 + is_liked_by_user: false + + - name: "Лайк промокода [1] пользователем 2" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/like" + method: POST + headers: + Authorization: "Bearer {user2_token}" + response: + status_code: 200 + json: + status: ok + + - name: "Получение промокода [1] со стороны пользователя 2" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user2_token}" + response: + status_code: 200 + json: + like_count: 2 + is_liked_by_user: true + + - name: "Удаление несуществующего лайка промокода [1] пользователем 3" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/like" + method: DELETE + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + status: ok + + - name: "Получение промокода [1] со стороны пользователя 3" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + like_count: 2 + is_liked_by_user: false + + - name: "Получение промокода [1] со стороны компании" + request: + url: "{BASE_URL}/business/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + like_count: 2 + + - name: "Удаление лайка промокода [1] пользователем 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/like" + method: DELETE + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + status: ok + + - name: "Получение промокода [1] со стороны пользователя 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + like_count: 1 + is_liked_by_user: false + + - name: "Повторное удаление лайка промокода [1] пользователем 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/like" + method: DELETE + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + status: ok + + - name: "Получение промокода [1] со стороны пользователя 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + like_count: 1 + is_liked_by_user: false diff --git a/tests/test_12_user_comments.tavern.yml b/tests/test_12_user_comments.tavern.yml new file mode 100644 index 0000000..b94175b --- /dev/null +++ b/tests/test_12_user_comments.tavern.yml @@ -0,0 +1,424 @@ +test_name: Комментарии к промокодам + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +stages: + - type: ref + id: basic_auth_reg1 + + - type: ref + id: basic_auth_reg2 + + - name: "Регистрация нового пользователя [1]: gb, 60" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Steve + surname: Wozniak + email: creator2@apple.com + password: WhoLiveSInCalifornia2000! + other: + age: 60 + country: gb + response: + status_code: 200 + save: + json: + user1_token: token + + - name: "Регистрация нового пользователя [2]: us, 15" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Mike + surname: Bloomberg + email: mike2@bloomberg.com + password: WhoLiveSInCalifornia2000! + other: + age: 15 + country: us + response: + status_code: 200 + save: + json: + user2_token: token + + - name: "Регистрация нового пользователя [3]: kz, 40" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Yefim + surname: Dinitz + email: algo3@prog.ru + password: HardPASSword1! + other: + age: 40 + country: kz + response: + status_code: 200 + save: + json: + user3_token: token + + - name: "Создание промокода [1]: active, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[1] Активный COMMON промокод для всех" + target: {} + max_count: 10 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo1_id: id + + - name: "Создание промокода [2]: inactive, , 28.." + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + json: + description: "[1] Активный COMMON промокод для kz, 28.." + target: + country: kz + age_from: 28 + max_count: 10 + active_from: "2025-02-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo2_id: id + + - name: "Получение промокода [1] со стороны пользователя 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo_id: "{promo1_id}" + comment_count: 0 + + - name: "Написать комментарий к промокоду 1 [1]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments" + method: POST + headers: + Authorization: "Bearer {user1_token}" + json: + text: "[1] Комментарий к промокоду 1 от пользователя 1" + response: + status_code: 201 + json: + text: "[1] Комментарий к промокоду 1 от пользователя 1" + author: + name: Steve + surname: Wozniak + save: + json: + comment1_id: id + comment1_date: date + + - name: "Написать комментарий к промокоду 1 [2]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments" + method: POST + headers: + Authorization: "Bearer {user1_token}" + json: + text: "[2] Комментарий к промокоду 1 от пользователя 1" + response: + status_code: 201 + save: + json: + comment2_id: id + + - name: "Написать комментарий к промокоду 2 [3]" + request: + url: "{BASE_URL}/user/promo/{promo2_id}/comments" + method: POST + headers: + Authorization: "Bearer {user2_token}" + json: + text: "[3] Комментарий к промокоду 2 от пользователя 2" + response: + status_code: 201 + save: + json: + comment3_id: id + + - name: "Написать комментарий к промокоду 2 [4]" + request: + url: "{BASE_URL}/user/promo/{promo2_id}/comments" + method: POST + headers: + Authorization: "Bearer {user2_token}" + json: + text: "[4] Комментарий к промокоду 2 от пользователя 3" + response: + status_code: 201 + save: + json: + comment4_id: id + + - name: "Написать комментарий к промокоду 1 [5]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments" + method: POST + headers: + Authorization: "Bearer {user3_token}" + json: + text: "[5] Комментарий к промокоду 1 от пользователя 3" + response: + status_code: 201 + save: + json: + comment5_id: id + + - name: "Получение промокода [1]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo_id: "{promo1_id}" + comment_count: 3 + + - name: "Получение промокода [2]" + request: + url: "{BASE_URL}/user/promo/{promo2_id}" + method: GET + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + promo_id: "{promo2_id}" + comment_count: 2 + + - name: "Получить комментарии к промокоду 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + - id: "{comment5_id}" + - id: "{comment2_id}" + - id: "{comment1_id}" + + - name: "Получить комментарии к промокоду 1 (пагинация 1-5)" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments" + method: GET + params: + limit: 5 + offset: 1 + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + - id: "{comment2_id}" + - id: "{comment1_id}" + headers: + X-Total-Count: "3" + + - name: "Получить комментарий по ID" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments/{comment1_id}" + method: GET + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + text: "[1] Комментарий к промокоду 1 от пользователя 1" + + - name: "Получить комментарий по ID: некорректная связка id промокода - id комментария [1]" + request: + url: "{BASE_URL}/user/promo/{promo2_id}/comments/{comment1_id}" + method: GET + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 404 + + - name: "Получить комментарий по ID: некорректная связка id промокода - id комментария [2]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments/{comment4_id}" + method: GET + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 404 + + - name: "Редактирование комментария 1: корректно" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments/{comment1_id}" + method: PUT + headers: + Authorization: "Bearer {user1_token}" + json: + text: "[1] Отредактированная версия комментария к промокоду 1 от пользователя 1" + response: + status_code: 200 + json: + id: "{comment1_id}" + text: "[1] Отредактированная версия комментария к промокоду 1 от пользователя 1" + date: "{comment1_date}" + + - name: "Редактирование комментария 1: некорректная связка с promo_id" + request: + url: "{BASE_URL}/user/promo/{promo2_id}/comments/{comment1_id}" + method: PUT + headers: + Authorization: "Bearer {user1_token}" + json: + text: "Что-то не так, не тот promo_id" + response: + status_code: 404 + + - name: "Редактирование комментария 1: попытка не от владельца" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments/{comment1_id}" + method: PUT + headers: + Authorization: "Bearer {user3_token}" + json: + text: "Это не должно сработать! Редактировать содержимое может только владелец..." + response: + status_code: 403 + + - name: "Получить комментарий по ID" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments/{comment1_id}" + method: GET + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + id: "{comment1_id}" + text: "[1] Отредактированная версия комментария к промокоду 1 от пользователя 1" + date: "{comment1_date}" + + - name: "Получение промокода [1]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + comment_count: 3 + + - name: "Получить комментарии к промокоду 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + - id: "{comment5_id}" + - id: "{comment2_id}" + - id: "{comment1_id}" + + - name: "Удаление комментария 1: некорректная связка с promo_id" + request: + url: "{BASE_URL}/user/promo/{promo2_id}/comments/{comment1_id}" + method: DELETE + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 404 + + - name: "Удаление комментария 1: попытка не от владельца" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments/{comment1_id}" + method: DELETE + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 403 + + - name: "Получить комментарий [1] по ID" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments/{comment1_id}" + method: GET + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + + - name: "Удаление комментария 1: успешное удаление" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments/{comment1_id}" + method: DELETE + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + status: ok + + - name: "Удаление комментария 1: повторное удаление, комментарий не найден" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments/{comment1_id}" + method: DELETE + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 404 + + - name: "Получение промокода [1]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo_id: "{promo1_id}" + comment_count: 2 + + - name: "Получить комментарии к промокоду 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/comments" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + - id: "{comment5_id}" + - id: "{comment2_id}" + headers: + X-Total-Count: "2" diff --git a/tests/test_13_user_promo_activate.tavern.yml b/tests/test_13_user_promo_activate.tavern.yml new file mode 100644 index 0000000..0c383e5 --- /dev/null +++ b/tests/test_13_user_promo_activate.tavern.yml @@ -0,0 +1,326 @@ +test_name: Активация промокода + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +stages: + - type: ref + id: basic_auth_reg1 + + - type: ref + id: basic_auth_reg2 + + - name: "Регистрация нового пользователя [1]: gb, 60" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Steve + surname: Wozniak + email: creator2@apple.com + password: WhoLiveSInCalifornia2000! + other: + age: 60 + country: gb + response: + status_code: 200 + save: + json: + user1_token: token + + - name: "Регистрация нового пользователя [2]: us, 15" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Mike + surname: Bloomberg + email: blocked@antifraud.com + password: WhoLiveSInCalifornia2000! + other: + age: 15 + country: us + response: + status_code: 200 + save: + json: + user2_token: token + + - name: "Регистрация нового пользователя [3]: kz, 40" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Yefim + surname: Dinitz + email: algo3@prog.ru + password: HardPASSword1! + other: + age: 40 + country: kz + response: + status_code: 200 + save: + json: + user3_token: token + + - name: "Создание промокода [1]: active, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[1] Активный COMMON промокод для всех" + target: {} + max_count: 4 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo1_id: id + + - name: "Создание промокода [2]: inactive, , 28.." + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + json: + description: "[1] Активный COMMON промокод для kz, 28.." + target: + country: kz + age_from: 28 + max_count: 10 + active_from: "2025-02-10" + mode: "COMMON" + promo_common: "sale-20" + response: + status_code: 201 + save: + json: + promo2_id: id + + - name: "Создание промокода [3]: active, , 45.." + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company2_token}" + json: + description: "[3] Активный UNIQUE промокод для gb, 45.." + target: + country: gb + age_from: 45 + active_until: "2035-02-10" + mode: "UNIQUE" + max_count: 1 + promo_unique: + - uniq1 + - uniq2 + response: + status_code: 201 + save: + json: + promo3_id: id + + - name: "Активация промокода [2]: отказ, так как промокод inactive" + request: + url: "{BASE_URL}/user/promo/{promo2_id}/activate" + method: POST + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 403 + + - name: "Активация промокода [2]: отказ, так как промокод не соответствует настройкам таргетинга" + request: + url: "{BASE_URL}/user/promo/{promo2_id}/activate" + method: POST + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 403 + + - name: "Активация промокода [1] пользователем 1: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 3: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 1: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + # - name: "Внутренний запрос в Antifraud: заблокировать пользователя 2 (переменная ANTIFRAUD_URL, см. config.yml)" + # max_retries: 3 + # request: + # url: "{ANTIFRAUD_URL}/update_user_verdict" + # method: POST + # json: + # user_email: mike2@bloomberg.com + # ok: false + # response: + # status_code: 200 + + - name: "Активация промокода [1] пользователем 2: пользователь заблокирован" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user2_token}" + response: + status_code: 403 + + - name: "Активация промокода [1] пользователем 3: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 1: исчерпан лимит max_count" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 403 + + - name: "Попытка уменьшить max_count: сделать меньше used_count" + request: + url: "{BASE_URL}/business/promo/{promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + max_count: 3 + response: + status_code: 400 + + - name: "Активация промокода [3] пользователем 1: корректный запрос [1]" + request: + url: "{BASE_URL}/user/promo/{promo3_id}/activate" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + + - name: "Активация промокода [3] пользователем 1: корректный запрос [2]" + request: + url: "{BASE_URL}/user/promo/{promo3_id}/activate" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + + - name: "Активация промокода [3] пользователем 1: исчерпан лимит по числу активаций" + request: + url: "{BASE_URL}/user/promo/{promo3_id}/activate" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 403 + + - name: "Получение промокода [1] со стороны пользователя 1" + request: + url: "{BASE_URL}/user/promo/{promo1_id}" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo_id: "{promo1_id}" + active: false + is_activated_by_user: true + + - name: "Получение истории активаций пользователем 1" + request: + url: "{BASE_URL}/user/promo/history" + method: GET + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + - promo_id: "{promo3_id}" + active: false + is_activated_by_user: true + - promo_id: "{promo3_id}" + active: false + is_activated_by_user: true + - promo_id: "{promo1_id}" + active: false + is_activated_by_user: true + - promo_id: "{promo1_id}" + active: false + is_activated_by_user: true + + - name: "Получение истории активаций пользователем 1 (пагинация 2-3)" + request: + url: "{BASE_URL}/user/promo/history" + method: GET + params: + offset: 2 + limit: 3 + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + - promo_id: "{promo1_id}" + active: false + is_activated_by_user: true + - promo_id: "{promo1_id}" + active: false + is_activated_by_user: true + headers: + X-Total-Count: "4" + + - name: "Получение истории активаций пользователем 1 (пагинация -0)" + request: + url: "{BASE_URL}/user/promo/history" + method: GET + params: + limit: 0 + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: [] diff --git a/tests/test_13_user_promo_activate_validate_cache.tavern.yml b/tests/test_13_user_promo_activate_validate_cache.tavern.yml new file mode 100644 index 0000000..08a5ee9 --- /dev/null +++ b/tests/test_13_user_promo_activate_validate_cache.tavern.yml @@ -0,0 +1,149 @@ +test_name: Активация промокода + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +stages: + - type: ref + id: basic_auth_auth1 + + - type: ref + id: basic_auth_auth2 + + - name: "Получение списка промокодов для сохранения Promo ID" + request: + url: "{BASE_URL}/business/promo" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + save: + json: + promo1_id: "[0].promo_id" + + - name: "Регистрация нового пользователя [4]: by, 23" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Igor + surname: Baliuk + email: dontstopthemusic@gmail.com + password: CalifornicationIsNear2024! + other: + age: 23 + country: by + response: + status_code: 200 + save: + json: + user4_token: token + + - name: "Регистрация нового пользователя [5]: by, 23" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Aleksandr + surname: Shakhov + email: slowdown@antifraud.ru + password: IHaveADog!Love1t + other: + age: 28 + country: ru + response: + status_code: 200 + save: + json: + user5_token: token + + - name: "Редактирование промокода [1], он должен стать active=true" + request: + url: "{BASE_URL}/business/promo/{promo1_id}" + method: PATCH + headers: + Authorization: "Bearer {company1_token}" + json: + max_count: 100 + response: + status_code: 200 + + - name: "Активация промокода [1] пользователем 4: корректный запрос [1]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user4_token}" + response: + status_code: 200 + + - name: "Внутренний запрос в Antifraud: заблокировать пользователя 4" + max_retries: 3 + request: + url: "{ANTIFRAUD_URL}/update_user_verdict" + method: POST + json: + user_email: dontstopthemusic@gmail.com + ok: false + response: + status_code: 200 + + - name: "Активация промокода [1] пользователем 4: корректный запрос [1]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user4_token}" + response: + status_code: 200 + + - name: "Активация промокода [1] пользователем 4: отказ из-за сервиса антифрода (делаем искусственную задержку на 3 секунды)" + delay_before: 3 + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user4_token}" + response: + status_code: 403 + + - name: "Активация промокода [1] пользователем 5: корректный запрос [1]" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user5_token}" + response: + status_code: 200 + + # - name: "Внутренний запрос в Antifraud: установить искусственную задержку 2500-3000 мс, приложение должно кешировать предыдущий ответ" + # request: + # url: "{ANTIFRAUD_URL}/set_delay" + # method: POST + # json: + # min: 2500 + # max: 3000 + # response: + # status_code: 200 + + - name: "Активация промокода [1] пользователем 5: корректный запрос [1]" + request: + timeout: 1.0 # 1 секунда + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user5_token}" + response: + status_code: 200 + + - name: "Активация промокода [1] пользователем 5: корректный запрос [1]" + request: + timeout: 1.0 # 1 секунда + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user5_token}" + response: + status_code: 200 diff --git a/tests/test_14_business_activate_promo.tavern.yml b/tests/test_14_business_activate_promo.tavern.yml new file mode 100644 index 0000000..0d5f363 --- /dev/null +++ b/tests/test_14_business_activate_promo.tavern.yml @@ -0,0 +1,184 @@ +test_name: Создать и активировать промокоды + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +stages: + - type: ref + id: basic_auth_reg1 + + - type: ref + id: basic_auth_reg2 + + - name: "Регистрация нового пользователя [1]: gb, 60" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Steve + surname: Wozniak + email: creator2@apple.com + password: WhoLiveSInCalifornia2000! + other: + age: 60 + country: gb + response: + status_code: 200 + save: + json: + user1_token: token + + - name: "Регистрация нового пользователя [2]: us, 15" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Mike + surname: Bloomberg + email: mike3@bloomberg.com + password: WhoLiveSInCalifornia2000! + other: + age: 15 + country: us + response: + status_code: 200 + save: + json: + user2_token: token + + - name: "Регистрация нового пользователя [3]: kz, 40" + request: + url: "{BASE_URL}/user/auth/sign-up" + method: POST + json: + name: Yefim + surname: Dinitz + email: algo3@prog.ru + password: HardPASSword1! + other: + age: 40 + country: kz + response: + status_code: 200 + save: + json: + user3_token: token + + - name: "Создание промокода [1]: active, " + request: + url: "{BASE_URL}/business/promo" + method: POST + headers: + Authorization: "Bearer {company1_token}" + json: + description: "[1] Активный COMMON промокод для всех" + target: {} + max_count: 10 + active_from: "2025-01-10" + mode: "COMMON" + promo_common: "sale-10" + response: + status_code: 201 + save: + json: + promo1_id: id + + - name: "Активация промокода [1] пользователем 1: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 2: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user2_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 1: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 3: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 3: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user3_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 1: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user1_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 2: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user2_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 2: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user2_token}" + response: + status_code: 200 + json: + promo: "sale-10" + + - name: "Активация промокода [1] пользователем 2: успех" + request: + url: "{BASE_URL}/user/promo/{promo1_id}/activate" + method: POST + headers: + Authorization: "Bearer {user2_token}" + response: + status_code: 200 + json: + promo: "sale-10" diff --git a/tests/test_14_business_get_stat.tavern.yml b/tests/test_14_business_get_stat.tavern.yml new file mode 100644 index 0000000..ef62b3d --- /dev/null +++ b/tests/test_14_business_get_stat.tavern.yml @@ -0,0 +1,53 @@ +test_name: Получение статистики активаций + +# Подключение файлов из директории components для переиспользования в тестах +includes: + - !include components/basic_auth.yml + +# Предварительно необходимо запустить тест test_14_business_activate_promo.tavern.yml + +stages: + - type: ref + id: basic_auth_auth1 + + - type: ref + id: basic_auth_auth2 + + - name: "Получение списка промокодов для сохранения Promo ID" + request: + url: "{BASE_URL}/business/promo" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + - used_count: 9 + active: true + save: + json: + promo1_id: "[0].promo_id" + + - name: "Получение статистики активаций по промокоду [1]: нет доступа (другая компания)" + request: + url: "{BASE_URL}/business/promo/{promo1_id}/stat" + method: GET + headers: + Authorization: "Bearer {company2_token}" + response: + status_code: 403 + + - name: "Получение статистики активаций по промокоду [1]: получение промокода" + request: + url: "{BASE_URL}/business/promo/{promo1_id}/stat" + method: GET + headers: + Authorization: "Bearer {company1_token}" + response: + status_code: 200 + json: + activations_count: 9 + countries: + - activations_count: 3 + - activations_count: 2 + - activations_count: 4